地址:
力扣https://leetcode-cn.com/problems/palindrome-linked-list/
题目:
给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
示例 1:
输入:head = [1,2,2,1] 输出:true |
示例 2:
输入:head = [1,2] 输出:false |
提示:
链表中节点数目在范围[1, 105] 内 0 <= Node.val <= 9 |
进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
既然是回文判定,一定是前后值相互比较,如果不相等一定不是回文
因为是单链表,所以没办法同时移动指针,容易想到的是把单链表的值存放到一维数组
这样就可以进行比较
方法一、数组保存值比较
考虑测试用例的不同情况,可能前序指针不会超过,或者超过数组半数
所以最后还是以数组长度为界限
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool isPalindrome(struct ListNode* head){
if(head == NULL)
return true;
int cnt = 0;
int k = 0;
struct ListNode *p = head;
while(p)
{
p = p->next;
cnt++;
}
int *array = (int *)malloc(sizeof(int) * cnt);
p = head;
while(p)
{
array[k++] = p->val;
p = p->next;
}
for(int i = 0, j = cnt - 1; i < cnt; i++, j--)
{
if(array[i] != array[j])
{
free(array);
return false;
}
}
free(array);
return true;
}
方法二、反转链表比较
如果能够找到链表的中间点,那么链表后半部的子链表我们可以进行反转
反转链表的具体操作可以查看:206. 反转链表
反转完成后相当于两个子链表的比较,就很容易
引入fast(每次 2 步),slow(每次 1 步)指针
当 fast 到达末尾时,slow 位于中点,这里要区分 链表个数的奇偶性,才能处理好 slow 的位置进行反转
示例:
奇数链表
fast 移动到末尾时的样子
把 slow 移动到下一个节点
如果链表是偶数的话,最后样子是:
以 slow 开始作为新链表进行反转,再与 fast 进行比较
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head){
struct ListNode *cur = head;
struct ListNode *pre = NULL;
struct ListNode *next = NULL;
while(cur != NULL)
{
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
bool isPalindrome(struct ListNode* head){
if(head == NULL)
return true;
struct ListNode* fast = head;
struct ListNode* slow = head;
//while(fast->next != NULL && fast->next->next != NULL)
while(fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
}
/*
nodes %2 == 1:
1 2 3 2 1 NULL
<s> <f>
1 2 2 1 NULL
<s> <f>
*/
if(fast != NULL) // nodes %2 == 1
{
slow = slow->next;
}
slow = reverseList(slow);
fast = head;
//while(fast->next != NULL && slow->next != NULL)
while(slow != NULL)
{
if(fast->val != slow->val)
return false;
fast = fast->next;
slow = slow->next;
}
return true;
}