算法训练记录——Day04
前言
(补一篇)现在有时间了,可以开始跟上进度了,今日目标——链表
● 24. 两两交换链表中的节点
● 19.删除链表的倒数第N个节点
● 07. 链表相交
● 142.环形链表II
● 总结
24.两两交换链表中的节点
思路:a->b->c … a->c & b->c … b->a->c ?
刚开始写的代码,乍一看好像没问题呀,但是少了节点,cur节点没了?
ListNode* swapPairs(ListNode* head) {
ListNode* node = head;
while(node != nullptr && node->next != nullptr){
ListNode* cur = node->next;
node->next = cur->next;
cur->next = node;
node = node->next;
Print(head);
}
return head;
}
这个写法让链表断开了,cur确实是更新了,但是没有办法跟head联系起来。
ListNode* swapPairs(ListNode* head) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* cur = dummyHead;
while(cur->next != nullptr && cur->next->next != nullptr){
ListNode* tmp1 = cur->next; // 改变cur指向前保存next指针
cur->next = cur->next->next; // 改变cur指向
ListNode* tmp2 = cur->next->next; // 改变cur->next指向前保存next指针
cur->next->next = tmp1; // 反转cur->next指向
tmp1->next = tmp2; // 改变tmp1指向
cur = cur->next->next; // cur后移
}
return dummyHead->next;
}
大概懂了,反转两个节点首先要获得这两个节点,由于有头节点的关系,用dummyHead模拟头节点,将头节点变成子节点,用cur来保存已反转链表,每次断开连接前先保存对应节点的next节点,然后将链表重新串联就ok了
19.删除链表的倒数第N个节点
思路:做过的题,为啥一点影响没有。。。第一反应循环两次,一次找数量一次删节点。看了几分钟,好像有点熟悉了,双指针,快指针先走n步,然后慢指针开始动。
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyNode = new ListNode();
dummyNode->next = head;
ListNode* fast = head;
ListNode* slow = dummyNode;
while(n--) { // 这里输入有限制,因此不做判空
fast = fast->next;
}
while(fast != nullptr) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return dummyNode->next;
}
时间复杂度: O(n)
空间复杂度: O(1)
虽然方法已经知道了,但这道题做出来还是耗费了10分钟,主要用在处理各种边界问题,还是没完全搞明白,先打卡以后再看吧。
面试题02.07.链表相交
思路:怎么看两个链表相交?链表节点的指向相同?那岂不是要比较n²次?
不靠谱,直接看题解。原来是从交点往后都相同,计算两个链表长度,tail对齐开始查询
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* chang = headA;
ListNode* duan = headB;
int lenA = 0, lenB = 0;
while(chang != nullptr){
++lenA;
chang = chang->next;
}
while(duan != nullptr){
++lenB;
duan = duan->next;
}
int diff = lenA - lenB;
chang = headA;
duan = headB;
if(diff > 0) {
while(diff--){
chang = chang->next;
}
} else {
while(diff++){
duan = duan->next;
}
}
while(chang != nullptr && duan != nullptr){
if(chang == duan)
return chang;
else {
chang = chang->next;
duan = duan->next;
}
}
return nullptr;
}
142.环形链表II
思路:想到了判断循环链表的方法,但这道题让确定第一个交点,超纲了
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast != nullptr && fast->next != nullptr) {
fast = fast->next->next;
slow = slow->next;
if (fast == slow) {
fast = head;
while(fast != slow){
fast = fast->next;
slow = slow->next;
}
return fast;
}
}
return NULL;
}
涉及到公式推导,先记结论