链表Part02
24.两两交换链表中的节点
struct ListNode* swapPairs(struct ListNode* head) {
struct ListNode dummyNode ;
dummyNode.next = head;
struct ListNode *temp = &dummyNode;
while(temp->next!=NULL&&temp->next->next!=NULL){
struct ListNode *node1=temp->next;
struct ListNode *node2=temp->next->next;
temp->next = node2;
node1->next=node2->next;
node2->next=node1;
temp = node1;
}
return dummyNode.next;
}
使用迭代的方法实现两两交换链表中的节点,创建了一个虚拟节点。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode dummyNode;
dummyNode.next = head;
struct ListNode *slow=&dummyNode,*fast=&dummyNode;
for(int i = 0;i<=n;i++){
fast = fast->next;
}
while(fast!=NULL){
fast=fast->next;
slow=slow->next;
}
struct ListNode *temp = slow->next;
slow->next = temp->next;
free(temp);
return dummyNode.next;
}
使用快慢指针来解决,并设置一个虚拟节点,在题目中保证需要删除的节点下标小于链表大小的情况下,减少了判断次数。(虚拟节点确实好用,链表的头结点不是空无用处)
采用双指针解决,设链表A的长度为a+c=m,链表B的长度为b+c=n,pA和pB一起移动,存在几种情形
- 两个链表有交点
- 若m=n,则两个指针共同移动到交点处停止,返回其中一个指针
- 若m!=n,则两个指针到达链表末尾后,分别指向对方链表的头节点,最后共同达到交点处,pA移动次数为a+c+b,pB移动次数为b+c+a,返回其中一个指针】
- 两个链表没有交点
- 若m=n,两个指针同时移动到链表末尾,均指向NULL,返回NULL
- 若m!=n,两个指针在移动m+n次后指向链表末尾,均指向NULL,返回NULL
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if(headA==NULL||headB==NULL) return NULL;
struct ListNode *pA=headA,*pB=headB;
while(pA!=pB){
pA= pA==NULL?headB:pA->next;
pB= pB==NULL?headA:pB->next;
}
return pA;
}
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode *fast=head,*slow=head;
while(true){
if(fast==NULL||fast->next==NULL) return NULL;
slow=slow->next;
fast=fast->next->next;
if(slow==fast) break;
}
fast = head;
while(fast!=slow){
fast=fast->next;
slow=slow->next;
}
return slow;
}
采用快慢指针fast
,slow
指向链表头部head
,令fast
每轮走2步,slow
每轮走1步,执行后有以下情形(设链表中非环的部分长度为a
,环的部分长度为b
):
fast
指针到达过链表末端,说明链表无环,此时直接返回null
。如果链表存在环,则双指针一定会相遇。- 当
fast=slow
时,两指针在环中第一次相遇,设两个指针分别走了x
,y
步,则x=2y
,fast
比slow
多走了n倍的环的长度,环的长度为b
,则x=y+nb
,两个式子相减得y=2nb
,x=nb
,此时,我们可以计算出到达入口处需要走a+nb
步,则slow
指针再走a
步即可到达入口点,我们将fast
指针指向头节点,和slow
一同向后移动,经过a
步后,移动到入口节点处,返回该节点
采用该种方式解决问题需要数学知识的应用,时间复杂度为O(n)
,空间复杂度为O(1)
。
采用哈希表的方式空间复杂度较高,不过思路要简单许多,二刷时采用两种方式都做一遍。