在你提供的代码中,isPalindrome
函数是用于判断一个链表是否为回文链表。下面是对代码的一些分析和可能需要修改的地方:
代码分析
将链表值存入数组:首先,你使用一个
vector<int> ans;
来存储链表节点的值。这段逻辑是正确的,可以遍历整个链表并将每个节点的值添加到数组中。检查回文:
- 你使用两个指针
left
和right
分别从数组的两端向中间移动来比较元素。 - 使用循环条件
(i >= 0, j <= size)
是不够准确的,因为这会导致下标越界(因为j
应该小于size
)。
- 你使用两个指针
错误与修正
循环边界: 在你的循环中,应该有一个适当的条件限制,以确保不会访问超出数组范围的位置。
索引调整: 对应地,应当这样写:
bool isPalindrome(ListNode* head) {
vector<int> ans;
while (head) {
ans.emplace_back(head->val);
head = head->next;
}
int size = ans.size();
int left = 0, right = size - 1;
while (left < right) { // 注意这里
if (ans[left] != ans[right]) {
return false;
}
left++;
right--;
}
return true;
}
改进点
- 使用双指针方法而不是使用额外的空间存储所有节点的值。在没有额外空间需求时,可以通过快慢指针找到链表中间节点,然后反转后半部分,再进行比较。
这是改进后的无额外空间解决方案:
bool isPalindrome(ListNode* head) {
if (!head || !head->next) return true;
// 快慢指针找到中间节点
ListNode *slow = head, *fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
// 反转后半部分
ListNode *prev = nullptr, *curr = slow;
while (curr) {
ListNode *nextTemp = curr->next;
curr->next = prev; // 反转指针
prev = curr; // 移动prev到当前
curr = nextTemp; // 移动curr到下一节点
}
// prev现在指向新头部,开始比较前半部分和后半部分
ListNode *firstHalfHead = head;
ListNode *secondHalfHead = prev;
while (secondHalfHead) {
if (firstHalfHead->val != secondHalfHead->val) {
return false;
}
firstHalfHead = firstHalfHead->next;
secondHalfHead = secondHalfHead->next;
}
return true;
}
这个算法在时间复杂度上仍然是 O(n),但仅需 O(1) 的额外空间。希望这些信息能帮助你更好地理解回文链表问题!如果有其他问题,请随时询问。
内容由零声教学AI助手提供,问题来源于学员提问