代码随想录Day 4 链表
24两两交换链表中的节点
本题技巧是添加dummy head
我把我的解题思路归纳为两个步骤:
- 确定好循环结束条件,需要分奇数偶数,即需要考虑链表中节点的个数;
- 在循环体内进行交换操作时,要注意添加temp指针(我的理解是:当某个指针改变其指向时,原来的next指针就需要用temp保存起来。
话不多说,直接上C++代码:
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode *dummy = new ListNode();
dummy->next = head;
// cur这个节点指针每次指向需要交换的两个节点的前一个节点
ListNode * cur = dummy;
//当链表节点为偶数个,恰好两两一组相互交换;当为奇数个,最后一个节点不用交换;
// 这里注意偶数判断情况(cur->next != nullptr )要写在前面
while(cur->next != nullptr && cur->next->next != nullptr){
ListNode * temp1 = cur->next;
ListNode * temp2 = cur->next->next->next;
cur->next = cur->next->next;
cur->next->next = temp1;
temp1->next = temp2;
cur = cur->next->next;
}
return dummy->next;
}
};
19删除链表的倒数第N个节点
本题的关键是找到倒数第N个节点的位置,以及记录该节点的前一个节点。本题技巧是使用双指针+ dummy head。
题目中已描述N大于等于1且小于等于链表长度。当N等于链表长度时,需要删除头节点,我们添加dummy head可以将删除头节点时的情况转换为删除一般节点的情况。添加双指针则是为了定位到待删除节点的位置。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode * dummy = new ListNode();
dummy->next = head;
// 先定义两个指针
ListNode * fast = dummy;
ListNode * slow = dummy;
// 让fast指针先走n步,由于fast一开始指向dummy head,在走了n步之后,停留在原链表的第n个节点处
while(n-- && fast!=nullptr){
fast = fast->next;
}
// fast和slow两个指针同时移动,当fast指向链表的最后一个节点时,slow刚好指向待删除节点的前一个位置
// 这里要判断fast->next还是fast要根据上面fast到底走了多少步来确定(如果上面fast走了n+1步,那么这里要判断fast != nullprt)
while(fast->next != nullptr){
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return dummy->next;
}
}
160链表相交
解法一:哈希集合
一个一个对比两个链表中是否有内存地址相等的元素;
解法二: 双指针
定义p1和p2两个指针分别指向两个headA和headB两个链表,让两个指针同时移动。
假设headA长度为m,headB长度为n,如果相交,则重合部分长度为k:
(1)m == n且不相交: 两个指针移动m个
(2)m != n且不相交: 两个指针移动m+n个
(3)m == n且相交: 两个指针移动m-k个
(4)m != n且相交: 两个指针移动m+n-k个
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode * pa = headA;
ListNode * pb = headB;
while(pa != pb){
// if(pa->next == NULL && pb->next == NULL){
// return NULL;
// }
pa = pa ? pa->next : headB; //如果判断条件是pa->next,需要上面注释的判断,否则对于无相交情况是死循环
pb = pb ? pb->next : headA;
}
// 当两链表不相交时,pa=pb=nullptr; 当相交时,此时pa=pb,都指向最开始相交的那个节点
return pa;
}
};