LeetCode刷题——链表2

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

题目链接.

  • 题意:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
  • 思路
  1. 遍历链表,得到链表长度,计算倒数第n个节点是正序的第几个节点,然后遍历删除该节点(暴力)。
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode * dummy = new ListNode(-1);
        dummy->next=head;
        ListNode *p=dummy;
        int l=0;
        while(p->next){
            l++;
            p=p->next;
        }
        int t=l-n+1,t1=0;
        ListNode *p1=dummy;
        while(p1->next){
            t1++;
            if(t1==t) p1->next=p1->next->next;
            else p1=p1->next;
        }
        return dummy->next;
    }
};
  1. 快慢指针,设置虚拟头节点,两个指针初始指向虚拟节点,快指针先走n步,然后快慢指针再同时走,当快指针指向链表结尾时,慢指针指向倒数n+1个节点,然后删除倒数第n个节点,返回虚拟头节点的下一个节点。
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy=new ListNode(-1);
        dummy->next=head;
        ListNode* p=dummy;
        ListNode* q=dummy;
        for(int i=0;i<n;++i) p=p->next;
        while(p->next){
            p=p->next;
            q=q->next;
        }
        q->next=q->next->next;
        return dummy->next;
    }
};

链表相交

题目链接.

  • 题意:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
  • 思路
  1. (暴力)两个循环,循环比较b中的节点是否等于a中的节点。
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode * a=headA;
        
        while(a!=nullptr){
            ListNode * b=headB;
            while(b!=nullptr){
                if(b==a) return a;
                else b=b->next;
            }
            a=a->next;
        }
        return nullptr;
    }
};
  1. (哈希表),将a中的节点放入哈希表中,循环b中的节点,看哈希表中是否存在。
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode * a=headA;
        ListNode * b=headB;
        unordered_set<ListNode *> h;
        while(a){
            h.insert(a);
            a=a->next;
        }
        while(b){
            if(h.find(b)!=h.end()) return b;
            b=b->next;
        }
        return nullptr;
    }
};
  1. (双指针)设链表A的长度为a,链表B的长度为b,A到相交结点的距离为c,B到相交节点的距离为d,显然可以得到两者相交链表的长度:a - c = b - d, 变换一下式子得到:a + d = b + c。用一个指针从链表A出发,到末尾后就从B出发,用另一个指针从B出发,到末尾后从A出发,由于上面的公式,当前一个指针走了a+d步数时,后一个指针走了b+c,两步数相等,即走到了相交节点。
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode * a=headA;
        ListNode * b=headB;
        while(a!=b){
            if(a!=nullptr) a=a->next;
            else a=headB;
            if(b!=nullptr) b=b->next;
            else b=headA;
        }
        return a;
    }

};

环形链表 II

题目链接.

  • 题意:给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
  • 思路
  1. (哈希表),初始化一个指针p指向头节点,如果p不为空,循环。如果p不在哈希表中,加入哈希表,如果存在,返回p。然后令p=p->next,如果循环顺利结束,则链表无环,返回nullptr。
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        unordered_set<ListNode *> h;
        ListNode* p=head;
        while(p){
            if(h.find(p)!=h.end()) return p;
            else h.insert(p);
            p=p->next;
        }
        return nullptr;
    }
};
  1. (快慢指针),快指针一次走两步,慢指针一次走一步。如果快指针能变成空指针,则链表无环。
    假设环之前的长度为a,环的长度为b。快指针走的长度为f,慢指针走的长度为s,当两个指针第一次相遇时f=2s。快指针比慢指针多走n个环的长度f=s+nb。得:s=nb,f=2nb.
    我们需要得到的是环入口的位置,第一次相遇并不一定在环入口处。从头节点出发到达环入口的长度l满足:l=a+nbs距离la,将快指针重新指向头节点,且变为一次走一步,慢指针同样一次走一步,a步后,快慢指针同时到达环入口,得到答案。
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode * fast=head;
        ListNode * slow=head;
        while(fast){
            if(fast->next==nullptr) return 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 nullptr;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值