【算法训练记录——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;
    }

涉及到公式推导,先记结论

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值