目录
必备知识:单链表的增删查改
【数据结构初阶】-3-链表 | 链表是什么?| 【单链表的增删查改|思路+源码】
概览及题目链接
- 一、链表的中间结点:给你单链表的头结点 head ,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
-
二、 链表倒数第k个结点:输入一个链表,输出该链表中倒数第k个结点。
链表中倒数第k个结点_牛客题霸_牛客网 (nowcoder.com)
-
三、回文结构:对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。
给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
测试样例: 1->2->2->1
返回:true
链表的回文结构_牛客题霸_牛客网 (nowcoder.com)
题一:反转链表(快慢指针)(速度差)
思路:快慢指针——v(fast)=2v(slow)
- 快指针fast:v(fast) = 2步/次;慢指针slow:v(slow) = 1步/次
- 分情况:链表有偶数个或奇数个结点
源码
struct ListNode* middleNode(struct ListNode* head)
{
if(!head)
return NULL;
struct ListNode*fast=head,*slow=head;
while(fast)
{
if(!fast->next)//奇数个的情况
return slow;
fast=fast->next->next;
slow=slow->next;
}
return slow;
}
循环体还可以写成:
while(fast&&fast->next)
{
fast=fast->next->next;
slow=slow->next;
}
题二:链表倒数第k个结点(快慢指针)(恒路程差)
思路:fast 比 slow 先走 k 步或(k-1)步,然后一起走
先走k步或者k-1步本质上都一样,只是循环判断的条件不一样
- 同样的先解决链表为空的情况
- 注意:k的个数可能要大于链表自身结点的个数,这个需要判断一下👇
int count=0;
while(tail){
count++;
tail = tail->next;
}
if(k>count)
return NULL;
源码
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k )
{
if(!pListHead)
return NULL;
struct ListNode*fast=pListHead,*slow=pListHead;
struct ListNode*tail=pListHead;
int count=0;
while(tail){
count++;
tail = tail->next;
}
if(k>count)
return NULL;
while(k--)//fast先走
{
fast=fast->next;
}
while(fast)
{
slow=slow->next;
fast=fast->next;
}
return slow;
}
题二:回文结构
思路:找到中间结点,后半段反转,看是否相等
关于链表的中间结点,见本文题一
关于反转链表→[数据结构初阶] | OJ | 【哨兵位】 | 【思路+源码】题:反转链表、移除单链表的元素、合并两个有序链表、链表分割(见此篇题一)
- 找到中间结点(A是所给的链表的头指针)
struct ListNode* mid = middleNode(A);
- 反转后半段
struct ListNode* otherhead = reverseList(mid);
3.对比前半段和后半段
struct ListNode* cur = A, * other = otherhead;
//cur指向前半段,other指向后半段
//比较👇
while (other)
{
if (cur->val != other->val)
{
return false;
}
cur = cur->next;
other = other->next;
}
return true;
源码
//中间结点
struct ListNode* middleNode(struct ListNode* head)
{
if (!head)
return NULL;
struct ListNode* fast = head, * slow = head;
while (fast)
{
if (!fast->next)
return slow;
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
//反转链表
struct ListNode* reverseList(struct ListNode* head)
{
if (head == NULL)
{
return NULL;
}
struct ListNode* cur = head;
struct ListNode* next = head->next;
struct ListNode* newhead = NULL;
while (cur)
{
cur->next = newhead;
newhead = cur;
cur = next;
if (next)
next = next->next;
}
return newhead;
}
//判断回文结构
bool chkPalindrome(struct ListNode* A) {
struct ListNode* mid = middleNode(A);
struct ListNode* otherhead = reverseList(mid);
struct ListNode* cur = A, * other = otherhead;
while (other) {
if (cur->val != other->val)
{
return false;
}
cur = cur->next;
other = other->next;
}
return true;
}
⇲——————————————————————————————@fantasy_13_7————————END——————