题目1:24 两两交换链表中的节点
题目链接:24 两两交换链表中的节点
题意
两两交换链表中相邻的节点,返回交换后链表的头节点
虚拟头节点
注意终止条件,考虑节点的奇偶数,根据奇偶数确定终止条件
注意定义中间变量,temp temp1,节点的指向改变时,使用中间变量保存以前指向的节点,以便后续的链表查询操作
完整操作1
代码1
/*** 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* dummyhead = new ListNode(0);dummyhead->next = head;ListNode* cur = dummyhead;//头节点交换时,要知道其前一个节点(dummyhead),所以cur=dummyheadwhile(cur->next!=NULL && cur->next->next!=NULL){ListNode* temp = cur->next;cur->next = cur->next->next;ListNode* temp1 = cur->next->next;cur->next->next = temp;temp->next = temp1;cur = cur->next->next;}return dummyhead->next; }
};
- 时间复杂度:O(n)
- 空间复杂度:O(1)
完整操作2(先将上述分析的需要定义的中间变量全部提前定义好)
代码
/*** 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* dummyhead = new ListNode(0);dummyhead->next = head;ListNode* cur = dummyhead;//头节点交换时,要知道其前一个节点(dummyhead),所以cur=dummyheadwhile(cur->next!=NULL && cur->next->next!=NULL){ListNode* temp = cur->next;ListNode* temp1 = cur->next->next->next;cur->next = cur->next->next;cur->next->next = temp;temp->next = temp1;cur = cur->next->next;}return dummyhead->next; }
};
- 时间复杂度:O(n)
- 空间复杂度:O(1)
题目2:19 删除链表的倒数第N个节点
题目链接:19 删除链表的倒数第N个节点
题意
删除链表中的倒数第n个节点,返回链表的头节点
虚拟头节点
先让fast走n+1步,然后fast和slow再同时移动,这样slow就会到达要删除节点的前一个节点
伪代码
代码
/*** 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;ListNode* fast = dummyhead;ListNode* slow = dummyhead;n++;while(n && fast!=NULL){fast = fast->next;n--;}while(fast!=NULL){fast = fast->next;slow = slow->next;}ListNode* tmp = slow->next;//定义临时变量,用于释放内存slow->next = slow->next->next;delete tmp;return dummyhead->next;}
};
- 时间复杂度: O(n)
- 空间复杂度: O(1)
题目3:链表相交
题目链接:链表相交
题意
找到两个单链表相交的起始节点;如果没有交点,则返回NULL
注意交点不是数值相等,而是指针相等
步骤
① 链表A定义一个curA指针 curA=headA; 链表B定义一个curB指针 curB=headB
② 链表A的长度lenA 链表B的长度lenB
③ lenA 与 lenB 的差gap
④ 将curA移动gap步 此时curA与curB在相同的位置处(到链表末尾的距离相等)
⑤ curA与curB一同移动 若curA==curB 返回curA 否则,一直移动curA和curB
curA==NULL 代表curA与curB还是不相等,则返回NULL
代码1
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode* curA = headA;ListNode* curB = headB;int lenA = 0;int lenB = 0;while(curA!=NULL){curA = curA->next;lenA++;}while(curB!=NULL){curB = curB->next;lenB++;}cout<<lenA<<endl;cout<<lenB<<endl;//此时curA curB已经移动到了NULL位置,将curA curB重新指向head处curA = headA;curB = headB;//求解长度差//首先使得A是最长的链表if(lenB > lenA){swap(lenA,lenB);swap(curA,curB);}cout<<lenA<<endl;cout<<lenB<<endl;int gap = lenA - lenB;//将curA移动到与链表B对齐的位置while(gap){curA = curA->next;gap--;}//这样curA与curB在同一长度处while(curA!=NULL && curA!=curB){curA=curA->next;curB=curB->next;}if(curA!=NULL){return curA;}else{return NULL;}}
};
代码2
/*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode* curA = headA;ListNode* curB = headB;int lenA = 0;int lenB = 0;while(curA!=NULL){curA = curA->next;lenA++;}while(curB!=NULL){curB = curB->next;lenB++;}//此时curA curB已经移动到了NULL位置,将curA curB重新指向head处curA = headA;curB = headB;//求解长度差//首先使得A是最长的链表if(lenB > lenA){swap(lenA,lenB);swap(curA,curB);}int gap = lenA - lenB;//将curA移动到与链表B对齐的位置while(gap){curA = curA->next;gap--;}//这样curA与curB在同一长度处while(curA!=NULL){if(curA==curB){return curA;}curA=curA->next;curB=curB->next;} return NULL;}
};
- 时间复杂度:O(n + m)
- 空间复杂度:O(1)
题目4:142 环形链表Ⅱ
题目链接:142 环形链表Ⅱ
题意
判断链表有无环,有环的话则返回开始入环的第一个节点;无环则返回null
主要分两个步骤:
①判断有环 无环
使用fast slow两个指针,fast每次走两个节点,slow每次走1个节点,若有环,则fast,slow一定会在环内相遇 因为相对于slow,fast是每次走1个节点靠近slow,所以一定会和slow重合
②有环的话,返回入环的第一个节点;无环的话,返回null
fast,slow相遇时,fast走过的节点数为x+y+n(y+z),slow走过的节点数为x+y
fast走过的节点数=2*slow走过的节点数 n>=1
伪代码
代码
/*** 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) {ListNode* fast = head;ListNode* slow = head;while(fast!=NULL && fast->next!=NULL){fast = fast->next->next;slow = slow->next;//是否出现环if(fast==slow){ListNode* index1 = fast;ListNode* index2 = head;while(index1!=index2){index1 = index1->next;index2 = index2->next;}return index1;}}return NULL;}
};
- 时间复杂度: O(n),快慢指针相遇前,慢指针走的次数小于链表长度(没走1圈fast和slow就相遇了),快慢指针相遇后,两个index指针走的次数也小于链表长度,总体为走的次数小于 2n
- 空间复杂度: O(1)