【Day3】代码随想录二刷Chapter2——链表part2

今天要把代码随想录中的链表部分刷完,开冲!!!

今日任务:

  • 删除链表的倒数第N个节点
  • 链表相交
  • 环形链表ii

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

Leetcode题目:【19.删除链表的倒数第N个节点】

请添加图片描述这个题目就是需要转化下,倒数第N个元素可以转化为正数第size - N + 1个元素。
需要考虑的问题是:
(1)如何由正数第几个元素 ——》 倒数第几个元素
(2)如何偏移到要删除的元素那里。

/**
 * 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) {
        int size = 0;
        ListNode *dummyNode = new ListNode(0);
        dummyNode -> next = head;
        ListNode *cur = dummyNode;
        while(cur -> next != NULL){
            size++;
            cur = cur-> next;
        }
        cur = dummyNode;
        // 倒数第2个代表就是正数size - n + 1
        for(int i = 1; i<size - n + 1; i++){
            cur = cur -> next;
        }
        ListNode * tmp = cur -> next;
        cur -> next = cur -> next -> next;
        delete tmp;
        return dummyNode -> next;
        
    }
};

二、面试题02.07.链表相交(思想很重要)

Leetcode题目:【面试题02.07.链表相交】

在这里插入图片描述
这个题目一上来确实没啥思路,感觉是两个链表需要上个指针进行偏移。

需要注意的点:
(1)两个链表的交点注意不是数值相等,而是指针相等;
(2)两个链表如果相交,那后面一定是一样的,所以它的思路就是先计算数量,然后偏移到短的那个的共同位置;
(3)后买你如果curA和curB是否相同,如果相同那就是叫交点,否则循环退出返回空指针。

思路描述
在这里插入图片描述

这个题目中非常重要的点:
(1)为了减少代码,需要保证A链表的长度必须大于B链表的长度,如果小于,那么就需要交换两者;
(2)curA提前走的索引的步数一定要算清楚。

/**
 * 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) {
        ListNode *dummyNodeA = new ListNode(0);
        ListNode *dummyNodeB = new ListNode(0);
        ListNode *curA = dummyNodeA;
        ListNode *curB = dummyNodeB;
        dummyNodeA -> next = headA;
        dummyNodeB -> next = headB;
        int length_A = 0, length_B = 0;
        while(curA -> next != NULL){
            length_A++;
            curA = curA -> next;
        }
        while(curB -> next != NULL){
            length_B++;
            curB = curB -> next;
        }
        
        // 保证curA始终是长的,curB始终是短的
        if(length_A < length_B){
            swap(length_A, length_B);
            swap(dummyNodeA, dummyNodeB);
        }

        curA = dummyNodeA;
        curB = dummyNodeB;

        int gap = length_A - length_B;
        for(int i = 0; i<gap; i++) curA = curA -> next;
        
        while(curA != NULL){
            if(curA == curB){
                return curA ;
            }
            curA = curA -> next;
            curB = curB -> next;
        }
        return NULL;
    }
};

三、142.环形链表II

Leetcode题目:【142.环形链表II】

在这里插入图片描述

这个题非常有印象,而且最后求进入点好像还有个公式,但是现在有点忘记了,所以需要看一下才能回忆起来。
解决问题主要有两点:
(1)如何判断有环?
(2)环的入口在哪里?

  • 如何判断有环
    • 定义两个指针,一个快指针(每次走两步),一个慢指针(每次走一步),只要两者能相遇,那就是有环,因为按照常识,如果有环的话,指针是1个单位长度依次去追,一定可以追上.
  • 如何确定环的入口:
    在这里插入图片描述
    在这里插入图片描述
    结论:从头节点出发一个指针,从相遇节点出发,这两个指针每次都只走一个几点,那么当这两个指针相遇的时候就是环形入口的节点。

写代码时需要注意的点:
(1)终止条件:fast和fast->next均不为空才可实现,原因是需要考虑链表为空或者只有一个元素的情况;
(2)判断是否成环的时候,应该先走,然后在判断,这是因为刚开始fast和slow指针都指向head,因为直接就进循环了;
(3)当判断成环之后,如何利用结论求解入环位置是直接利用结论:一个从头节点head,另一个从相遇点,然后第一次相遇的点就是环的入点。

/**
 * 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) {
        // 首先判断是否有环,环的入口在哪里
        ListNode* fastpoint = head;
        ListNode* slowpoint = head;
        while(fastpoint != NULL && fastpoint -> next!= NULL){
            fastpoint = fastpoint -> next -> next;
            slowpoint = slowpoint -> next;
            if(fastpoint == slowpoint){
                cout << "The link is true circle link" << endl;
                fastpoint = head;
                while(fastpoint != slowpoint){
                    fastpoint = fastpoint -> next;
                    slowpoint = slowpoint -> next;
                }
                return fastpoint;
            }
            
        }
        return NULL;
        
    }
};

四、总结:

链表主要还是看操作的数量程度,其中翻转链表、链表相交和环形链表注意求解的思想。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值