本思路参考网上解法和相关视频,整理并注释解析。
LeetCode 面试题02.06 回文链表
反转链表题同思路
回文链表的判断类似于回文数,所以
第一种方法:
数组的方式
typedef struct ListNode ListNode;
bool isPalindrome(struct ListNode* head)
{
ListNode* cur = head;
int count = 0;
while (cur)//统计链表节点的个数
{
count++;
cur = cur->next;
}
int* Array = (int*)malloc(sizeof(int)*count);//动态开辟相应大小的数组
int i = 0;
cur = head;
while (cur)//填充
{
Array[i++] = cur->val;
cur = cur->next;
}
int left = 0; int right = count - 1;
while (left < right)//头尾指针判断
{
if (Array[left] != Array[right])
{
return false;
}
left++;
right--;
}
return true;
}
该种做法虽然能通过,但是空间复杂度较大,也比较取巧= =
所以
推荐使用进阶做法:
思路:1.运用快慢指针找出链表的中点
2.运用三个指针对链表后半部分进行反转
3.链表分别从头节点和尾节点相向遍历,进行回文判断
以下为代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool isPalindrome(struct ListNode* head)
{
struct ListNode* fast=head; struct ListNode*slow=head;
while(fast != NULL && fast->next != NULL)//快慢指针运用
{
fast=fast->next->next;
slow=slow->next;//找中点
}
//此时使用 Green Red Yellow三个指针
struct ListNode* Green=slow;
struct ListNode* Red = NULL;
while(Green)//对链表后半部分的反转
{
struct ListNode* Yellow=Green->next;//Yellow保存Green的原下一个链接结点
Green->next = Red; // Green链接Red ****断开与原链接的链接
Red = Green; // Red移动到Green,代替 ***** 使用Red保存新链接
Green = Yellow; // 重新把Yellow(原链接)给Green链上,从而逐步实现链表反转
}
//反转结束后,Green和Yellow都已经变为NULL,Red位于反转后的链表的头结点
struct ListNode* HeadN = head;
while(Red) // 此时需用Red作为循环起点,否则会导致空指针问题
{
if(HeadN->val != Red->val)
{
return false;
}
HeadN=HeadN->next;
Red=Red->next;
}
return true;
}
图例说明————本人作图水平较差,望理解
当Green指向空时,反转循环中止
此时对于回文链表的判断形式为
Head
1->2->3->2->1->NULL
Red
1->2->3->NULL
当Red指向空时恰好结束判断
该解法运行
运用时间复杂度O(n) 空间复杂度O(1),即LeetCode该题进阶解法
--------------------------------------------------------------------------------------------------------------------------------