一、 移除链表元素

🎬 博主名称 :键盘敲碎了雾霭
🔥 个人专栏 : 《C语言》《数据结构》
⛺️指尖敲代码,雾霭皆可破

文章目录
- [一、 移除链表元素](#一、 移除链表元素)
- 四、返回倒数第k个节点
-
- [4.1 问题描述](#4.1 问题描述)
- [4.2 解题思想](#4.2 解题思想)
- [4.3 代码实现](#4.3 代码实现)
- 五、合并两个有序链表
-
- [5.1 问题描述](#5.1 问题描述)
- [5.2 解题思想](#5.2 解题思想)
- [5.3 代码实现](#5.3 代码实现)
- 六、链表分割
-
- [6.1 问题描述](#6.1 问题描述)
- [6.2 解题思想](#6.2 解题思想)
- [6.3 代码实现](#6.3 代码实现)
- 七、链表的回文结构
-
- [7.1 问题描述](#7.1 问题描述)
- [7.2 解题思想](#7.2 解题思想)
- [7.3 代码实现](#7.3 代码实现)
- 八、相交链表
-
- [8.1 问题描述](#8.1 问题描述)
- [8.2 解题思想](#8.2 解题思想)
- [8.3 代码实现](#8.3 代码实现)
- 九、环形链表
-
- [9.1 问题描述](#9.1 问题描述)
- [9.2 解题思想](#9.2 解题思想)
- [9.3 代码实现](#9.3 代码实现)
- 十、环形链表2
-
- [10.1 问题描述](#10.1 问题描述)
- [10.2 解题思想](#10.2 解题思想)
- [10.3 代码实现](#10.3 代码实现)
1.1 问题描述
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
原题链接:203.移除链表元素
1.2 解题思想
创建新链表,遍历原链表
1.3 代码实现
c
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode*phead=NULL;
struct ListNode*ptail=NULL;
struct ListNode *pur=head;
while(pur)
{
if(pur->val!=val)
{
if(phead==NULL)
{
phead=ptail=pur;
}
else
{
ptail->next=pur;
ptail=pur;
}
}
pur=pur->next;
}
if(phead==NULL)
{
return NULL;
}
ptail->next=NULL;
return phead;
}
二、反转一个单链表
2.1 问题描述
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
原题链接:206.反转链表
2.2 解题思想
建立三个指针,依次遍历
2.3 代码实现
c
struct ListNode* reverseList(struct ListNode* head)
{
if(head==NULL)
{
return head;
}
struct ListNode*l1=NULL;
struct ListNode*l2=head;
struct ListNode*l3=l2->next;
while(l2)
{
l2->next=l1;
l1=l2;
l2=l3;
if(l3!=NULL)
l3=l3->next;
}
return l1;
}
三、链表的中间结点
3.1 问题描述
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
原题链接:876.链表的中间结点
3.2 解题思想
建立三个指针,依次遍历
3.3 代码实现
c
struct ListNode* middleNode(struct ListNode* head)
{
struct ListNode*slow=head;
struct ListNode*fast=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
}
return slow;
}
四、返回倒数第k个节点
4.1 问题描述
实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。
原题链接:面试题02.02.返回倒数第k个节点
4.2 解题思想
建立快慢指针,有原始距离
4.3 代码实现
c
int kthToLast(struct ListNode* head, int k)
{
struct ListNode*slow=head;
struct ListNode*fast=head;
while(k--)
{
fast=fast->next;
}
while(fast)
{
slow=slow->next;
fast=fast->next;
}
return slow->val;
}
五、合并两个有序链表
5.1 问题描述
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
原题链接:21.合并两个有序链表
5.2 解题思想
新建立一个链表,遍历两个原链表
5.3 代码实现
c
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
if(list1==NULL)
{
return list2;
}
else if(list2==NULL)
{
return list1;
}
struct ListNode*l1=list1;
struct ListNode*l2=list2;
struct ListNode*phead=NULL;
struct ListNode*ptail=NULL;
phead=ptail=malloc(sizeof(struct ListNode));
while(l1&&l2)
{
if(l1->val<l2->val)
{
ptail->next=l1;
ptail=l1;
l1=l1->next;
}
else
{
ptail->next=l2;
ptail=l2;
l2=l2->next;
}
}
if(l1)
{
ptail->next=l1;
ptail=l1;
l1=l1->next;
}
if(l2)
{
ptail->next=l2;
ptail=l2;
l2=l2->next;
}
struct ListNode*next =phead->next;
free(phead);
phead=next;
return phead;
}
六、链表分割
6.1 问题描述
现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针
原题链接:CM11 链表分割
6.2 解题思想
构建两个链表,最后再合并起来
6.3 代码实现
c
class Partition {
public:
ListNode* partition(ListNode* pHead, int x)
{
struct ListNode *pur=pHead;
struct ListNode * phead1=(struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode *ptail1=phead1;
struct ListNode*phead2=(struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode*ptail2=phead2;
while(pur)
{
if(pur->val<x)
{
ptail1->next=pur;
ptail1=pur;
}
else
{
ptail2->next=pur;
ptail2=pur;
}
pur=pur->next;
}
ptail2->next=NULL;
ptail1->next=phead2->next;
return phead1->next;
// write code here
}
};
七、链表的回文结构
7.1 问题描述
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。
给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
原题链接:OR36 链表的回文结构
7.2 解题思想
先找中间节点,再反转链表,然后两链表比较
7.3 代码实现
c
class PalindromeList {
public:
struct ListNode* CheckMid(struct ListNode*head)
{
struct ListNode*slow=head;
struct ListNode*fast=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
}
return slow;
}
struct ListNode*Rverse(struct ListNode*head)
{
struct ListNode*l1=NULL;
struct ListNode*l2=head;
struct ListNode*l3=head->next;
while(l2)
{
l2->next=l1;
l1=l2;
l2=l3;
l3=l3->next;
}
return l1;
}
bool chkPalindrome(ListNode* A)
{
struct ListNode*pur=A;
struct ListNode* mid =CheckMid(A);
struct ListNode*phead=Rverse((mid));
while(pur&&phead)
{
if(phead->val!=pur->val)
{
return false;
}
pur=pur->next;
phead=phead->next;
}
return true;
// write code here
}
};
八、相交链表
8.1 问题描述
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
原题链接:160.相交链表
8.2 解题思想
利用快慢指针,算出相差的距离,快的先走,从同一位置依次遍历
8.3 代码实现
c
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
struct ListNode*l1=headA;
struct ListNode*l2=headB;
int count1=0;
int count2=0;
while(l1->next)
{
count1++;
l1=l1->next;
}
while(l2->next)
{
count2++;
l2=l2->next;
}
if(l1!=l2)
{
return NULL;
}
int dif=abs(count2-count1);
struct ListNode*longlist=headA;
struct ListNode*shortlist=headB;
if(count1<count2)
{
longlist=headB;
shortlist=headA;
}
while(dif--)
{
longlist=longlist->next;
}
while(longlist!=shortlist)
{
longlist =longlist->next;
shortlist = shortlist->next;
}
return longlist;
}
九、环形链表
9.1 问题描述
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
原题链接:141.环形链表
9.2 解题思想
利用快慢指针必相遇
9.3 代码实现
c
bool hasCycle(struct ListNode *head)
{
struct ListNode*slow=head;
struct ListNode*fast=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(fast==slow)
{
return true;
}
}
return false;
}
十、环形链表2
10.1 问题描述
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
原题链接:142. 环形链表
10.2 解题思想
利用快慢指针,找到相遇的节点,从该节点到成环的起始节点与头节点到成环的起始节点距离相同,会相遇
10.3 代码实现
c
struct ListNode *detectCycle(struct ListNode *head)
{
struct ListNode*slow=head;
struct ListNode*fast=head;
struct ListNode*phead=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(fast==slow)
{
struct ListNode*meet=fast;
while(meet!=phead)
{
meet=meet->next;
phead=phead->next;
}
return meet;
}
}
return NULL;
}