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

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

题目链接: 24. 两两交换链表中的节点

思路: 利用虚拟头结点保证链表的头不变,分别找到要交换的两个节点,依次交换位置(注意交换的顺序很重要,不然会断链)
在这里插入图片描述
代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        auto dummy = new ListNode(0);
        dummy->next = head;
        for(auto p = dummy;p->next && p->next->next;){//循环条件一定要这样,否则会出现访问异常或者runtime error
            auto a = p->next, b = a->next;//找到要交换的结点
            p->next = b;
            a->next = b->next;
            b->next = a;
            p = a;
        }
        return dummy->next;
    }
};

总结我自己写题过程中的问题:

  1. for循环若是没有在开始写递进语句,则在下面一定要补上,且谁的for循环谁在变,不要乱变变量(for循环需要加强练习,感觉写带码的本质是将自己的思维转化成代码的过程)
  2. &&与|| ,其中 &&是左边不成立则不判断右边的语句(因此我们写判断条件时要注意先后顺序),||则是两边都要判断。

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

题目链接: 19. 删除链表的倒数第 N 个结点
思路: 首先记录下链表的长度,再用总长度减去倒数点,其删除时我们必须先找到被删除的前一个结点,及len - index - 1 的位置才行

代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 **/
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        auto dummy = new ListNode(0);
        dummy->next = head;
        int len = 0;
        for(auto p = dummy; p->next; p = p->next) len++;
        int index = len - n - 1;
        auto q = dummy;
        for(int i = 0; i <= index;i++) q = q->next;
        auto temp = q->next->next;
        q->next = temp;
        return dummy->next;
    }
};

面试题 02.07. 链表相交

题目链接: 面试题 02.07. 链表相交
思路1: (暴力求解),利用两层循环,每层每层的找,直到找到相等的点。
代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        auto dummy1 = new ListNode(-1);
        auto dummy2 = new ListNode(-1);
        dummy1->next = headA;
        dummy2->next = headB;
        auto p = dummy1;
        auto q = dummy2;
        for(p = dummy1; p->next; p = p->next){
            for(q = dummy2; q->next; q = q->next){
                if(p->next == q->next) return p->next;
            }
        }
        if(p->next != q->next) return NULL; 
        else return p->next;   
    }
};

思路2: 若是两个链表相交则他们后面的结点一定是一样的,因此我们可以先将两者的长度的差值求出来,然后将两者中长度较长的向后移动差值的位置,使两者对齐,再依次判断每一个是否相等。
在这里插入图片描述
代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int lenA = 0, lenB = 0;
        for(auto p = headA; p ;p = p->next) lenA++;
        for(auto q = headB; q ;q = q->next) lenB++;
        int dec;
        auto tempA = headA, tempB = headB;
        if(lenA > lenB) {
            dec = lenA -lenB;
            for(int i = 1; i <= dec; i++) tempA = tempA->next;
            while(tempA && tempB){
                if(tempA == tempB) return tempA;
                else{
                    tempA = tempA->next;
                    tempB = tempB->next;
                }
             }
            }
        else {
              dec = lenB -lenA;
            for(int i = 1; i <= dec; i++) tempB = tempB->next;
            while(tempA && tempB){
                if(tempA == tempB) return tempA;
                else{
                    tempA = tempA->next;
                    tempB = tempB->next;
                }
             }
        }
        if(tempA != tempB) return NULL;
        else return tempA;
    }
};

142. 环形链表 II

题目链接: 142. 环形链表 II
本题主要学习链表中快慢指针的思路
思路: 判断两者是否有环,让slow指针每次走一步,让fast指针每次走两步,若是有环由于速度差则两者一定会在某一点处相遇,我们可以利用快慢指针找到相遇点

前置题目链接: 141. 环形链表
在这里插入图片描述
代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(!head || !head->next) return false;
        auto slow = head, fast = slow -> next;
        while(fast){
            slow = slow->next, fast = fast->next;
            if(!fast) return false;
            fast = fast->next;
            if(slow == fast) return true;
        }
        return false;      
    }
};

本题:
在这里插入图片描述
在这里插入图片描述
代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(!head || !head->next) return NULL;
        auto slow = head, fast = slow -> next;
        while(fast){
            slow = slow->next, fast = fast->next;
            if(!fast) return NULL;
            fast = fast->next;
            if(slow == fast){
                slow = head;
                while(slow != fast->next){
                    slow = slow->next;
                    fast = fast->next;
                }
                return slow;
            }
        }
        return NULL;     
    }
};

注: 一定要自己动手推一推公式和过程,才能更好的理解(不要懒)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值