数据结构-线性表(数组)-双指针-快慢指针 Offer22&19&141+142floyd判环法

剑指 Offer 22. 链表中倒数第k个节点

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

  • 思路
    对链表操作时,为了首尾节点操作与其他节点相同,需要添加头节点(哑节点dummy node)。
  1. 先确定链表的长度,然后找到要删除节点的前驱节点,进行删除。需要添加哑节点
  2. 双指针(快慢指针):快指针比慢指针快n+1个,因为慢指针要指向被删除元素的前驱节点,遍历整个链表,当快指针指向空时,慢指针正好指向被删除节点的前驱节点。初始化慢指针指向哑节点,快指针指向链表第一个节点
  • 代码
    第一个方法;
ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy  = new ListNode(0,head);
        ListNode* low = dummy;
        ListNode* res = nullptr;
        int len = 0;;
        while(head){
            ++len;
            head = head->next;
        }
        for(int i = 0;i<len-n;++i){
            low = low->next;
        }
        low->next = low->next->next;
        res = dummy->next;
        return res;
    }

快慢指针;

ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy  = new ListNode(0,head);
        ListNode* low = dummy;
        ListNode* fast = head;
        ListNode* res = nullptr;
        int i = 0;
        while(i<n){
            ++i;
            fast = fast->next;
        }
        while(fast){
            low = low->next;
            fast = fast->next;
        }
        low->next = low->next->next;
        res = dummy->next;
        return res;
    }
  • 总结
    1:对列表操作为了首节点操作不失一般性,需要添加哑节点
    2:链表确定长度
    3:删除链表某个节点 p->next = p->next->next; 不一定非要找到指向被删除节点的下一个节点的指针p1使p->next = p1;

环形链表

  • 思想
    判断循环链表;
  1. 判断链表的长度
  2. 算法-floyd判环(圈)算法(又称龟兔赛跑算法) 当龟兔进入环后,一快一慢,必定会相遇。
  • 代码
  1. 长度
bool hasCycle(ListNode *head) {
        int len = 0;
        while(head){
            ++len;
            head = head->next;
            if(len>10000) return true;
        }
        return false;
    }
  1. 龟兔赛跑算法
bool hasCycle(ListNode *head) {
        if(head==NULL || head->next==NULL) return false;
        ListNode * low = head;
        ListNode * fast = head->next;
        
        while(fast){
            if(low == fast) return true;
            if(fast->next==NULL || fast->next->next==NULL) return false;
            fast = fast->next->next;
            low = low->next;
        }
        return false;
    }

142

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        if(head==NULL ||head->next==NULL) return NULL;
        ListNode* low = head;
        ListNode* fast = head;
        while(fast){
            if(fast->next==NULL || fast->next->next==NULL) return NULL;
            low = low->next; 
            fast = fast->next->next; 
            if(low==fast){
                low = head;
                //low = low->next;肯定报错
                //fast = fast->next;
                //if(low==fast) return low;
                while(low != fast){//这个处理的很棒
                    low = low->next;
                    fast = fast->next;
                }
                return low;
            }
        }
        return NULL;
    }
};
  • 总结
  1. 链表中是否有环的判断
  2. 环起点判断
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值