1.Leetcode203 移除链表元素
解题思路:从头节点开始进行元素删除,每删除一个元素,需要重新链接节点
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode*dummyhead=malloc(sizeof(struct ListNode));
dummyhead->next=head;
struct ListNode*temp=dummyhead;
while(temp->next!=NULL)
{
if(temp->next->val==val)
{
temp->next=temp->next->next;
}
else
{
temp=temp->next;
}
}
return dummyhead->next;
}
2.Leetcode206 反转链表
解题思路: 此题一般常用的方法有两种,三指针翻转法和头插法
- 三指针翻转法:记录连续的三个节点,原地修改节点指向
struct ListNode* reverseList(struct ListNode* head) {
if(head == NULL || head->next == NULL)
return head;
struct ListNode* n1, *n2, *n3;
n1 = head;
n2 = n1->next;
n3 = n2->next;
n1->next = NULL;
//中间节点不为空,继续修改指向
while(n2)
{
//中间节点指向反转
n2->next = n1;
//更新三个连续的节点
n1 = n2;
n2 = n3;
if(n3)
n3 = n3->next;
}
//返回新的头
return n1;
}
- 头插法:每一个节点都进行头插
// 取节点头插的思想完成逆置
struct ListNode* reverseList(struct ListNode* head) {
struct ListNode* newhead = NULL;
struct ListNode* cur = head;
while(cur)
{
struct ListNode* next = cur->next;
//头插新节点,更新头
cur->next = newhead;
newhead = cur;
cur = next;
}
return newhead;
}
3.Leetcode876 链表的中间节点
解题思路:
通过快慢指针找到中间节点,快指针每次走两步,慢指针每次走一步,当快指针走到结尾的时候,慢指针正好走到中间位置
typedef struct ListNode Node;
struct ListNode* middleNode(struct ListNode* head){
Node* slow = head;
Node* fast = head;
while(fast!=NULL && fast->next != NULL)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
4.牛客:链表中倒数第k个结点
解题思路:
快慢指针法 fast, slow, 首先让fast先走k步,然后fast,slow同时走,fast走到末尾时,slow走到倒数第k个节点。
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
struct ListNode*slow,*fast;
slow=fast=pListHead;
while(k--)
{
if(fast==NULL)return NULL;
fast=fast->next;
}
while(fast)
{
slow=slow->next;
fast=fast->next;
}
return slow;
}
5.Leetcode 21 合并两个有序链表
解题思路:
此题可以先创建一个空链表,然后依次从两个有序链表中选取最小的进行尾插操作进行合并。
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
if(!list1)return list2;
if(!list2)return list1;
struct ListNode* cur1=list1,*cur2=list2;
struct ListNode* guard=NULL,*tail=NULL;
guard=tail=(struct ListNode*)malloc(sizeof(struct ListNode));
while(cur1&&cur2)
{
if(cur1->val<=cur2->val)
{
tail->next=cur1;
tail=tail->next;
cur1=cur1->next;
}
else
{
tail->next=cur2;
tail=tail->next;
cur2=cur2->next;
}
}
if(cur1)tail->next=cur1;
if(cur2)tail->next=cur2;
return guard->next;
}
6.牛客:链表分割
解题思路
创建两个链表,分别存放小于x的节点和大于等于x的节点,分别进行尾插,最后再将两个链表并成一个
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
struct ListNode*ghead,*gtail;
struct ListNode*lhead,*ltail;
ghead=gtail=(struct ListNode*)malloc(sizeof(struct ListNode));
lhead=ltail=(struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode *cur=pHead;
while(cur)
{
if(cur->val<x)
{
gtail->next=cur;
gtail=gtail->next;
}
else
{
ltail->next=cur;
ltail=ltail->next;
}
cur=cur->next;
}
gtail->next=lhead->next; //小的尾节点接到大的哨兵头上
ltail->next=NULL; //防止出现环
pHead=ghead->next;
free(ghead);
free(lhead);
return pHead;
}
};
7.牛客:链表的回文结构
解题思路:
此题可以先找到中间节点,然后把后半部分逆置,最近前后两部分一一比对,如果节点的值全部相同,则即为回文。
class PalindromeList {
public:
bool chkPalindrome(ListNode* A) {
struct ListNode* mid=middleNode(A); //找到链表的中间节点
struct ListNode* rA=reverseList(mid); //逆置中间节点以后的节点
while(mid&&rA)
{
if(A->val!=rA->val)return false;
A=A->next;
rA=rA->next;
}
return true;
}
struct ListNode* reverseList(struct ListNode* head) {
struct ListNode* tail = NULL, *cur = head;
while (cur) {
struct ListNode* next = cur->next;
cur->next = tail; //头插
tail = cur; //移动tail
cur = next;
}
return tail;
}
struct ListNode* middleNode(struct ListNode* head) {
struct ListNode* slow, *fast;
slow = fast = head;
while (fast &&
fast->next) { //两个都非空才能循环,有一个是空就结束循环
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
};
8.Leetcode160 相交链表
解题思路:
此题可以先计算出两个链表的长度,让长的链表先走相差的长度,然后两个链表同时走,直到遇到相同的节点,即为第一个公共节点
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode* tailA=headA,*tailB=headB;
int lenA=1,lenB=1;
while(tailA->next) //分别求出来两个链表的长度
{
tailA=tailA->next;
lenA++;
}
while(tailB->next) //分别求出来两个链表的长度
{
tailB=tailB->next;
lenB++;
}
if(tailA!=tailB) //链表最后一个节点的地址不相等,说明不相交
return NULL;
//让长的链表先走 长度差 的步数
int gap=abs(lenA-lenB);
struct ListNode*longlist=headA,*shortlist=headB;
if(lenA<lenB)
{
longlist=headB;
shortlist=headA;
}
//让长的链表先走 长度差 的步数
while(gap--)
{
longlist=longlist->next;
}
//然后两个链表同时走,比较节点地址是否相等
while(longlist!=shortlist)
{
longlist=longlist->next;
shortlist=shortlist->next;
}
return longlist;
}
9.Leetcode141 环形链表
解题思路:
定义快慢指针fast,slow, 如果链表确实有环,fast指针一定会在环内追上slow指针。
bool hasCycle(struct ListNode *head) {
struct ListNode* slow,*fast;
slow=fast=head;
//快慢指针
while(fast&&fast->next)
{
//慢指针走一步,快指针走两步,如果快指针等于慢指针说明有环
slow=slow->next;
fast=fast->next->next;
if(slow==fast)return true;
}
return false;
}
10.Leetcode142 环形链表Ⅱ
解题思路:
如果链表存在环,则fast和slow会在环内相遇
- 定义相遇点到入口点的距离为X
- 定义环的长度为C
- 定义头到入口的距离为L
fast在slow进入环之后一圈内追上slow,则会得知:
- slow所走的步数为:L + X
- fast所走的步数为:L + X + N * C
并且fast所走的步数为slow的两倍,故:
2*(L + X) = L + X + N * C 即: L = N * C - X
所以从相遇点开始slow继续走,让一个指针从头开始走,两者相遇点即为入口节点
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode *fast,*slow;
fast=slow=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
//让一个指针从链表起始位置开始遍历链表,同时让一个指针从判环时相遇点的位置开始绕环运行,两个指针都是每次均走一步,最终肯定会在入口点的位置相遇。
if(slow==fast)
{
struct ListNode*meet=slow;
struct ListNode*phead=head;
while(meet!=phead)
{
meet=meet->next;
phead=phead->next;
}
return meet;
}
}
return NULL;
}
Leetcode 138复制带随机指针的链表
解题思路:
1.拷贝节点链接在原节点的后面
2.拷贝节点的random指向原节点random的next
3.拷贝节点接下来,链接成新节点,原链表恢复原样
/**
* Definition for a Node.
* struct Node {
* int val;
* struct Node *next;
* struct Node *random;
* };
*/
struct Node* copyRandomList(struct Node* head) {
struct Node* cur=head;
//1.插入拷贝节点在原节点的后面
while(cur)
{
struct Node* copy=(struct Node*)malloc(sizeof(struct Node));
copy->val=cur->val;
struct Node* next=cur->next;
cur->next=copy;
copy->next=next;
cur=next;
}
//2.拷贝节点的random指向原节点random的next
cur=head;
while(cur)
{
struct Node* copy=cur->next;
if(cur->random==NULL)
{
copy->random=NULL;
}
else
{
copy->random=cur->random->next;
}
cur=cur->next->next;
}
//3.拷贝节点接下来,链接成新节点,并且恢复原链表
struct Node* copyhead=NULL ,*copytail=NULL;
cur=head;
while(cur)
{
struct Node* copy=cur->next;
struct Node* next=copy->next;
if(copyhead==NULL)
{
copyhead=copytail=copy;
}
else
{
copytail->next=copy;
copytail=copytail->next;
}
cur->next=next;
cur=next;
}
return copyhead;
}
本篇到此结束,码文不易,还请多多支持哦!