【代码随想录算法训练营第四天| 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点 、面试题 02.07. 链表相交、142.环形链表II】

代码随想录算法训练营第四天| 24. 两两交换链表中的节点、19.删除链表的倒数第N个节点 、面试题 02.07. 链表相交、142.环形链表II

第三四题题解请参考《代码随想录》:https://programmercarl.com/0203.%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8%E5%85%83%E7%B4%A0.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE
我的代码一些代码参考acwing的yxc的

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

先看代码:

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head == NULL || head->next == NULL) return head;
        ListNode* dummy = new ListNode();
        dummy->next = head;
        for(auto p = dummy;p->next && p->next->next;)
        {
            auto a = p->next,b = p->next->next;
            a->next = b->next;
            b->next = a;
            p->next = b;
            p = a;
        }
        return dummy->next;
    }
};

欢迎朋友来看我这个一看就会,一写就费的同学的博客。
读完题目,首先思考一下,这个题目要不要使用没有存储值的头节点,目的是简化代码,不用单独处理头节点head,这里你一看返回的是一个链表,那么大概率是需要一个空节点作为头节点的。然后是交换,交换的话有两种方式可以选择,我画一下图,我用的方式一。
方式一:
交换方式一方式二:
交换方式二

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

先看代码:
我的:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode();
        dummy->next = head;
        ListNode* q = head;
        int len = 0;
        for(auto p = head;p;p = p->next) len++;
        if(n == len) dummy->next = head->next;
        for(int i = 0;i < len - n - 1;i++) q = q->next;
        if(q->next)  q->next = q->next->next;
        return dummy->next;
    }
};

y总的:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        auto dummy = new ListNode(-1);
        dummy->next = head;
        int len = 0;
        for (auto p = dummy; p; p = p->next) len ++ ;
        auto p = dummy;
        for (int i = 0; i < len - n - 1; i ++ ) p = p->next;
        p->next = p->next->next;
        return dummy->next;
       
    }
};

这个删除倒数的这个也是没有太难,倒数第n个也就是正数第len - n + 1个,然后找到后删除即可,找的时候还是要注意,因为这是链表,所以找的时候要找到被删除节点的前一个节点,然后将指针停在那个位置,再删除。这里一对比可以看出大佬的代码不愧是大佬的代码,首先简洁,而且显示出缜密的思考,我的还要去判断删除倒数的最后一个节点,也就是第一个节点还要单独拿出来,因为我的指针是从head开始的,不是从dummy开始的。

面试题 02.07. 链表相交

看代码:

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* p = headA;
        ListNode* q = headB;
        int lenA = 0,lenB = 0;
        for(ListNode* i = headA;i;i = i->next) lenA++;
        for(ListNode* j = headB;j;j = j->next) lenB++;
        int res = 0;
        if(lenA > lenB)
        {
            res = lenA - lenB;
            for(int i = 0;i < res;i++) p = p->next;
        }
        else
        {
            res = lenB - lenA;
            for(int j = 0;j < res;j++) q = q->next;
        }

        while(p)
        {
            if(p == q) return p;
            else {
                p = p->next;
                q = q->next;
            }
        }
    return nullptr;
    }
};

这道题看《代码随想录》的思路就行,很简洁易懂。

142.环形链表II

先看代码:

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(!head || !head->next) return nullptr;
        ListNode* s = head;
        ListNode* f = head->next;
        while(f)
        {
            s = s->next,f = f->next;
            if(!f) return nullptr; //f因为是走两部,所以每走一步看看f是否到头了
            f = f->next; //f走两步
            if(s == f) //如果f和s相遇
            {
                s = head; //s回到起始位置
                f = f->next; //f也回到起始位置,注意这里的起始位置是f自己的起始位置,以为他起始的时候就比s多一步
                while(s != f) {
                    s = s->next;
                    f = f->next;
                }
                return s;
            }
        }
        return nullptr;
    }
};

这里的讲解也看《代码随想录就行》,思路好,画的图也很清晰。
这道题目我还犯了一个二百五的错误,就是找到链表尾,用链表尾的next指向谁,谁就是入口,我真是大聪明,都带环了,那还能找到链表尾,哈哈哈。

总结

做了两天的链表,也是2023年的最后一天做的了,明天就2024年了,这里祝大家元旦快乐。然后也写一下我近连天做链表的一些总结或者套路:

  1. 读完题目之后,想一下需不需要加空的头节点,来简化代码,不用把头节点head单独拿出来了。
  2. 链表的头尾会有的时候需要特别考虑。
  3. 就是能使用for()循环对链表进行移动,有的时候比while好多了,尤其涉及用下标来决定添加或者删除节点的时候。
  4. 还有一个使当if后有return的时候,看if里面的条件使不成立简洁还是成立简洁。
  5. 链表题目容易出现越界情况
  6. 多在纸上画画。
  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值