代码随想录算法训练营第四天 |24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交 ,142.环形链表II
24. 两两交换链表中的节点
题目链接
具体实现(C++):
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode * dummyNode = new ListNode(0);
dummyNode->next = head;
ListNode * cur = dummyNode;
while(cur->next != nullptr && cur->next->next != nullptr){
ListNode * tmp1 = cur->next; // 记录临时节点
ListNode * tmp2 = cur->next->next;
ListNode * tmp3 = cur->next->next->next;
cur->next = tmp2; // 步骤1、2、3,因为先处理最前面的写着舒服些
cur->next->next = tmp1; //注意不能对tmp操作
cur->next->next->next = tmp3;
cur = cur->next->next; // cur移动两位,准备下一轮交换
}
ListNode * result = dummyNode->next;
delete dummyNode;
return result;
}
};
时间复杂度:O(n)
空间复杂度:O(1)
209.长度最小的子数组
题目链接
具体实现(C++):
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *dummyHead = new ListNode(0); //第一反应以为不用虚拟头节点,写完了感觉只有一个或者没有的时候不知道怎么处理了,又不想多写,卡了半天...
dummyHead->next = head; //第一遍忘记把next指向head...
ListNode * p1 = dummyHead;
ListNode * p2 = dummyHead; //最开始定义时写一起了,p1相当于没赋值...
while(n-- && p2->next !=nullptr){ //最开始忘记考虑p2->next !=nullptr的情况
p2 = p2->next;
}
// p2 = p2 ->next;
while(p2->next != nullptr){
p2 = p2->next;
p1 = p1->next;
}
// ListNode * tmp = p1->next;
// p1->next = p1->next->next;
// delete tmp;
p1->next = p1->next->next;
return dummyHead->next;
}
};
时间复杂度:O(n)
空间复杂度:O(1)
面试题 02.07. 链表相交
题目链接
具体实现(C++):
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA = headA;
ListNode* curB = headB;
int lenA = 0, lenB = 0;
while (curA != NULL) { // 求链表A的长度
lenA++;
curA = curA->next;
}
while (curB != NULL) { // 求链表B的长度
lenB++;
curB = curB->next;
}
curA = headA;
curB = headB;
// 让curA为最长链表的头,lenA为其长度
if (lenB > lenA) {
swap (lenA, lenB);
swap (curA, curB);
}
// 求长度差
int gap = lenA - lenB;
// 让curA和curB在同一起点上(末尾位置对齐)
while (gap--) {
curA = curA->next;
}
// 遍历curA 和 curB,遇到相同则直接返回
while (curA != NULL) {
if (curA == curB) { //! 比的是节点地址,不是节点值
return curA;
}
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
时间复杂度:O(n+m)
空间复杂度:O(1)
142.环形链表II
题目链接
具体实现(C++):
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 = head;
ListNode * index2 = slow;
while(index1 != index2){
index1 = index1->next;
index2 = index2->next;
}
return index1;
}
}
return NULL;
}
};
时间复杂度:O(n)
空间复杂度:O(1)
总结
- 基本操作不够熟练,不能太钻牛角尖,卡住了及时看解析。
- 面试题 02.07. 链表相交第一遍没太看懂,以为是比较节点值且相交后节点值都必须相同
- 了解了142.环形链表II的解题思路,进一步掌握了快慢指针,在环中,相对于slow来说,fast是一个节点一个节点的靠近slow的。最开始看解析的时候也在想慢指针会不会在环里走好几圈才遇到快指针,后来假设快慢指针离得最远的情况就是慢指针刚入环,而快指针就在slow前一个位置,这样slow走一圈的时间,fast一定走了2圈了,而此时fast已经再一次超过了slow。