[自我记录]随想录刷题第四天 | 24. 两两交换链表中的节点, 19.删除链表的倒数第N个节点, 面试题 02.07. 链表相交, 142.环形链表II

代码随想录打卡第四天, 新手自我记录一下刷题历程, 仅为自我打卡使用.

周末较忙, 周六做的题目, 周日记录的博客


24. 两两交换链表中的节点

题目不难, 捋清楚每次要做的几个步骤就行

比方说 1->2->3->4 这样的一个链表

在节点1要做的几件事分别为:

把1->next指向节点3, (但是第二个节点不能丢, 所以先用一个tmp1存一下节点2)

把3->next指向原本的节点2(也就是刚存的tmp1, 但是节点4不能丢, 所以先用另一个tmp2存一下节点4)

再把2->next指向节点4(也就是刚存的tmp2)

在节点2不需要动作, 在节点3需要重复类似在节点1的操作, 所以每轮操作之后走两步, 最终完成两两交换.

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyHead = new ListNode(0, head);
        ListNode* cur = dummyHead;
        ListNode* tmp1;
        ListNode* tmp2;

        while (cur->next != nullptr && cur->next->next != nullptr){
                tmp1 = cur->next;
                cur->next = cur->next->next;
                tmp2 = cur->next->next;
                cur->next->next = tmp1;
                cur->next->next->next = tmp2;
                cur = cur->next->next;
        }
        return dummyHead->next;
    }
};

 19.删除链表的倒数第N个节点

正常思路是先遍历一次链表得到长度L, 然后删除倒数第n个节点 就要走到从头数第(L-n)节点的位置并删除他的下一个节点

要一次扫描就找到,考虑用双指针, fast和slow初始都指向首元节点, fast先走n个节点, 然后fast和slow一起往后走, 直到fast到达最后一个节点, 此时slow正好处于第(L-n)个节点位置, 删除其下一个节点即可.

这里我实现的时候习惯性的建立了虚拟头节点, 写完之后发现完全没必要, 因为本来也不需要对头节点区分操作, 不过懒得改了.

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyHead = new ListNode(0, head);
        
        ListNode* fast = dummyHead;
        ListNode* slow = dummyHead;

        for (int i = 0; i < n; ++i){
            fast = fast->next;
        }

        while (fast->next != nullptr){
            fast = fast->next;
            slow = slow->next;
        }
        ListNode* tmp = slow->next;
        slow->next = slow->next->next;
        delete tmp;

        return dummyHead->next;
    }
};

面试题 02.07. 链表相交

两个单链表如果相交, 一定是后面的n个节点相同. 如果能找到两者剩余元素相等的节点, 从此处开始用两个指针同时向后移动, 遍历两个链表, 一一比较每步两个指针所指的节点是否相同即可.

所以要先分别遍历两个链表一次得到各自的长度.

这里我的代码里的虚拟头节点也是不必要的, 二刷时候要改正! 越简洁越好.

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* dummyHeadA = new ListNode(0, headA);
        ListNode* dummyHeadB = new ListNode(0, headB);
        ListNode* curA = dummyHeadA;
        ListNode* curB = dummyHeadB;
        int sizeA = 0;
        int sizeB = 0;

        while (curA->next != nullptr){
            sizeA++;
            curA = curA->next;
        }

        while (curB->next != nullptr){
            sizeB++;
            curB = curB->next;
        }

        curA = dummyHeadA;
        curB = dummyHeadB;

        if (sizeA >= sizeB){
            for (int i = 0; i < sizeA - sizeB; ++i){
                curA = curA->next;
            }
        }
        else{
            for (int i = 0; i < sizeB - sizeA; ++i){
                curB = curB->next;
            }
        }

        while (curA->next != nullptr){
            if (curA->next == curB->next){
                return curA->next;
            }
            curA = curA->next;
            curB = curB->next;
        }
        return NULL;
    }
};

142.环形链表II

这题真的好难! 第一次接触链表环的时候完全想不到是这么做的!

这里就不强行分析了, 我是看了leetcode大神题解和carl哥视频之后才完全懂的.

class Solution {
public:
    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 slow;
            }
        }
        return NULL;
    }
};

到这随想录的链表部分的主干题目就完成了!

撒花!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值