LeetCode 234. 回文链表
题目描述
给你一个单链表的头节点 head
,请你判断该链表是否为回文链表。如果是,返回 true
;否则,返回 false
。
示例
示例 1:
输入:head = [1,2,2,1] 输出:true
示例 2:
输入:head = [1,2] 输出:false
解法
1.辅助数组
解题思路
创建一个数组,用了来存储整条链表的数据,遍历链表的同时,记录链表长度,使用双指针方法判断数组是不是回文即可。
class Solution {
public:bool isPalindrome(ListNode* head) {int l = 0;ListNode* LNode = head;vector<int> temp;while(LNode != nullptr){temp.push_back(LNode -> val);LNode = LNode -> next;l ++;}for(int i = 0,j = l - 1;i <= j;i ++,j --){if(temp[i] != temp[j]) return false;}return true;}
};
时间复杂度O(N),空间复杂度O(N)
2.快慢指针
解题思路:
回想一下,怎么判断一个字符串是不是回文串?我们可以从最左最右开始,比较第一个字母和最后一个字母是不是一样的,一样的话,就继续比较第二个字母和倒数第二个字母,依此类推。但对于链表,如何快速找到最后一个节点、倒数第二个节点、倒数第三个节点……?
首先,找链表的中间节点:
- 如果链表有奇数个节点,找正中间的节点。
- 如果链表有偶数个节点,找正中间右边的节点。
然后,把中间节点到链表末尾反转。如上图,反转后得到链表 6→5→4,其头节点记作 head2。这样我们就能从 head2开始,依次访问原链表的最后一个节点、倒数第二个节点、倒数第三个节点……
最后,同时遍历 head 和 head2这两个链表,每次循环判断 head.val 是否等于 head2.val,若不相等,则返回 false。循环直到 head2链表遍历结束。如果循环中没有返回 false,说明链表是回文的,返回 true。
⚠注意:第一张图中的 2→3,在反转链表后,并不会断开。第一张图反转链表后,我们得到了两条链表,一条是 1→2→3,另一条是 5→4→3。
⚠注意:第二张图中的 3→4,在反转链表后,并不会断开。第二张图反转链表后,我们得到了两条链表,一条是 1→2→3→4,另一条是 6→5→4。这意味着下面代码在写循环的时候,循环条件要判断 head2是否为空而不是 head 是否为空。如果判断 head 是否为空,会错误地多循环一次,导致访问 head2.val 出现空指针异常。
class Solution {// 876. 链表的中间结点ListNode* middleNode(ListNode* head) {ListNode* slow = head, *fast = head;while (fast && fast->next) {slow = slow->next;fast = fast->next->next;}return slow;}// 反转链表ListNode* reverseList(ListNode* head) {ListNode* pre = nullptr, *cur = head;while (cur) {ListNode* nxt = cur->next;cur->next = pre;pre = cur;cur = nxt;}return pre;}public:bool isPalindrome(ListNode* head) {ListNode* mid = middleNode(head);ListNode* head2 = reverseList(mid);while (head2) {if (head->val != head2->val) { // 不是回文链表return false;}head = head->next;head2 = head2->next;}return true;}
};
时间复杂度O(N),空间复杂度O(1)