代码随想录算法训练营第四天|链表part02
24. 两两交换链表中的节点
题目链接:24. 两两交换链表中的节点 - 力扣(LeetCode)
文章讲解:代码随想录
方法一:交换值
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* swapPairs(ListNode* head) {ListNode*curNode=head;while( curNode&&curNode->next){//这里不能仅判断curNode->next 因为curNode是空ListNode* nextNode=curNode->next;int curV=curNode->val;curNode->val=nextNode->val;nextNode->val=curV;curNode=nextNode->next;}return head;}
};
错误代码:
class Solution {
public:ListNode* swapPairs(ListNode* head) {ListNode*dummyNode=new ListNode;dummyNode->next=head;ListNode*curNode=dummyNode;while( curNode->next&&curNode->next->next){auto temp=curNode->next;auto temp1=curNode->next->next->next;temp->next=temp1;//这里提前绑定 会出现回路导致超时curNode->next=curNode->next->next;curNode->next->next=temp;// curNode->next->next->next=temp1;curNode=curNode->next->next;}auto ans=dummyNode->next;delete dummyNode;return ans;}
};
正确解答:
class Solution {
public:ListNode* swapPairs(ListNode* head) {//虚拟头节点ListNode*dummyNode=new ListNode;dummyNode->next=head;ListNode*curNode=dummyNode;while( curNode->next&&curNode->next->next){//交换auto temp=curNode->next;auto temp1=curNode->next->next->next;curNode->next=curNode->next->next;curNode->next->next=temp;curNode->next->next->next=temp1;curNode=curNode->next->next;}auto ans=dummyNode->next;//这里是必须的 因为头指针会被换到后一个去了delete dummyNode;return head;}
};
19.删除链表的倒数第N个节点
题目链接:19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
文章讲解:代码随想录
思路:
遍历一遍链表 统计有多少个节点 然后再计算出被删除节点前一个节点的编号
遍历到被删除节点前一个节点 然后再进行删除操作
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode*dummyHead=new ListNode(0);dummyHead->next=head;auto cur=dummyHead;int length=0;while(cur){length++;cur=cur->next;}auto pre=dummyHead;int count=length-n-1;while(count--){pre=pre->next;}if(pre&&pre->next){pre->next=pre->next->next;}auto ans=dummyHead->next;delete dummyHead;return ans;}
};
事实上 有更好的方法 这题是典型的应用快慢指针的方法
快指针先走n步
然后快慢指针一起走
class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {auto dummyHead=new ListNode(0);dummyHead->next=head;auto slow=dummyHead;auto fast=dummyHead;while(n--){fast=fast->next;}while(fast->next){slow=slow->next;fast=fast->next;}slow->next=slow->next->next;return dummyHead->next;}
};
面试题 02.07. 链表相交
题目链接:面试题 02.07. 链表相交 - 力扣(LeetCode)
文章讲解:代码随想录
思路:
也是用快慢指针
先分别求两个链表的长度
然后比较长度 长的先走
然后再一起走 判断当前指针是否相同
class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {int lengthA=0;auto curA=headA;while(curA){lengthA++;curA=curA->next;}int lengthB=0;auto curB=headB;while(curB){lengthB++;curB=curB->next;}if(lengthA>=lengthB){int dis=lengthA-lengthB;while(dis--){headA=headA->next;}while(headA){if(headA==headB)return headA;headA=headA->next;headB=headB->next;}}else{int dis=lengthB-lengthA;while(dis--){headB=headB->next;}while(headA){if(headA==headB)return headA;headA=headA->next;headB=headB->next;}}return NULL;}
};
142.环形链表II
题目链接:142. 环形链表 II - 力扣(LeetCode)
文章讲解:代码随想录
思路:
同样是用快慢指针
快指针每次走两格,慢指针每次走一格。
有环一定会相遇
无环则不会相遇
假设相遇的地方在E
从头到环入口的距离为x
从入口到相遇的距离为y
从相遇到入口的距离为z
可以推出:
x=(n-1)(y+z)+z
说明此时 在相遇的地方定义一个指针index1
头定义一个指针index2
两者一起走 他们相遇的地方就是环的入口
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode *detectCycle(ListNode *head) {auto fast=head;auto slow=head;while(fast&&fast->next){fast=fast->next->next;slow=slow->next;if(slow==fast){//相遇auto index1=slow;auto index2=head;while(index1!=index2){ //一起移动index1=index1->next;index2=index2->next;}return index1;}}return NULL;}
};