24. 两两交换链表中的节点
![](https://img-blog.csdnimg.cn/8cff0a696ec84cf6a563e87697d7409a.png)
使previous为node1,进行下一轮循环
由于头节点就是第一个node1,所以要在头节点之前创建虚拟节点,作为第一个privous,返回时返回dummy的next
终止条件为node1或node2为NULL
题解
struct ListNode* swapPairs(struct ListNode* head){
struct ListNode dummyNode;
struct ListNode* previous;
struct ListNode* node1;
struct ListNode* node2;
struct ListNode* nextNode;
dummyNode.next = head;
previous = &dummyNode;
while((previous->next != NULL) && (previous->next->next != NULL))
{
node1 = previous->next;
node2 = node1->next;
nextNode = node2->next;
previous->next = node2;
node2->next = node1;
node1->next = nextNode;
previous = node1;
}
return dummyNode.next;
}
创建fast、slow两个节点,fast和slow都从head节点顺着链表往后移动,只要fast比slow先走n步,当fast为NULL的时候,slow就是倒数第n个节点,此时将slow节点删除即可
由于要删除slow节点,需要获取前一个节点,可以新创建一个previous节点,记录slow的上一个节点,不过这样会多N步的时间复杂度(previous = slow, slow = slow->next)
可以让fast比slow先走n+1步,这样当fast为NULL时,slow->next = slow->next->next,即可将倒数第n个节点从链表移除
由于会有链表长度刚好等于n的情况,此时需要将链表头移除, 若fast从头节点出发,经过n步,刚到到达队尾的下一个节点NULL,slow比fast慢n+1,slow节点就在head节点之前,可以在头节点前创建虚拟节点,使slow从此出发
fast从head出发,往后走n步,若fast为NULL时,n步未走完,则没有倒数第n个节点,根据题意返回NULL
题解
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
struct ListNode dummy;
struct ListNode* fast = head;
struct ListNode* slow;
dummy.next = head;
slow = &dummy;
while((n != 0) && (fast != NULL))
{
n--;
fast = fast->next;
}
if(n != 0)
{
return NULL;
}
while(fast != NULL)
{
slow = slow->next;
fast = fast->next;
}
slow->next = slow->next->next;
return dummy.next;
}
面试题 02.07. 链表相交
题目来源 :leetcode 面试题 02.07. 链表相交
两个链表若相交,则从相交节点之后的链表剩余长度一定相等
将两个链表从头到尾走一遍,获取链表长度,两个链表长度相减,得到长度差值,长度长的链表先移动该差值次数,之后两个链表一起移动,若第一次节点相同,则找到相交节点;没有相同节点,则两链表不相交
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
int lenA = 0, lenB = 0;
struct ListNode * currA = headA;
struct ListNode * currB = headB;
struct ListNode * Ret = NULL;
while(currA != NULL)
{
lenA++;
currA = currA->next;
}
while(currB != NULL)
{
lenB++;
currB = currB->next;
}
currA = headA;
currB = headB;
if(lenA > lenB)
{
lenA = lenA - lenB;
while(lenA != 0)
{
lenA--;
currA = currA->next;
}
}
else
{
lenA = lenB - lenA;
while(lenA != 0)
{
lenA--;
currB = currB->next;
}
}
if(currA == currB)
{
Ret = currA;
}
else
{
while((lenB != 0) && (currA != currB))
{
lenB--;
currA = currA->next;
currB = currB->next;
}
if(currA == currB)
{
Ret = currA;
}
}
return Ret;
}
142.环形链表II
参考详解:
创建fast、slow两个指针,都从head从发,fast每次移动2步,slow每次移动1步。
若链表中存在环,在fast不会为NULL,且fast一定会与slow在环上相遇,fast额外比slow多走了n圈。
slow走过的距离:x+y
fast走过的距离:x+n*(y+z)
2x+2y = x + n*(y+z)
x = n*(y+z) - y
一个指针从相遇点出发,一个指针从head出发,相遇在环形入口处
题解
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode * fast = head;
struct ListNode * slow = head;
struct ListNode * Ret = NULL;
while((fast != NULL) && (fast->next != NULL))
{
fast = fast->next;
fast = fast->next;
slow = slow->next;
if(fast == slow)
{
fast = head;
while(fast != slow)
{
fast = fast->next;
slow = slow->next;
}
Ret = fast;
break;
}
}
return Ret;
}