链表刷题篇
一 . 链表中倒数第k个结点
1. 题目描述
假设给定某个链表, 让你输出链表中倒数第k个结点
2. 题解
思路一 – 快慢指针的应用方式
思路 : 让指针一比指针二快k个结点, 如此当指针一走到链表尾部时, 指针二恰好走到链表倒数第k+1个结点, 当指针一指向空时, 指针二恰好指向链表倒数第k个结点
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
{
ListNode* fast = pListHead;
ListNode* slow = pListHead;
int num = k;
int count = 0;
while(k--)
{
if(!fast)
{
break;
}
fast = fast->next;
count++;
}
if(num>count)
{
return NULL;
}
while(fast)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
};
作者 : Joker不是Joker
时间复杂度 : O(n) // 最差运行 n次
空间复杂度 : O(1)
评价 : 此题 快慢指针应用思路简单 , 但是数组越界情况较多, 或者说实际中特殊情况较恶心, 导致代码需要多次使用if语句进行判断。
思路二 – 单指针二次遍历
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
{
ListNode* cur=pListHead;
int count = 0;
while(cur)
{
cur = cur->next;
++count;
}
cur = pListHead;
count=count-k+1;
int num = 1;
while(cur)
{
if(num == count)
{
break;
}
cur = cur->next;
++num;
}
return cur;
}
};
作者 : Joker不是Joker
时间复杂度 : O(n) // 最差运行 2n次
空间复杂度 : O(1)
二 . 链表分割
1. 题目描述
现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针
2. 题解
思路一 双指针的应用
两个指针一前一后, 指针一指向指针二前一个结点, 每次循环判断指针二指向的结点的数值域是否小于x , 如果小于x将其头插入该链表中, 指针一用于记录指针二指向的节点
三. 链表的回文结构
1.题目描述
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。
给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
2. 题解
思路一 – 快慢指针的应用
先让一个指针遍历一次该链表, 然后统计链表中节点的个数。 记为count
如果节点个数为奇数 , 返回false
如果节点为偶数 , 让两个指针都指向链表中的第一个节点 ,
然后更新 fast指针, 让其先走count/2个节点
此时进行while循环,每次循环判断fast 与slow指向的节点的指针域是否相同 ,如果不同返回 false
如果循环正常结束, 代表该链表是回文结构, 返回true 。