0
点赞
收藏
分享

微信扫一扫

3.<tag-链表和快慢针>lt.141-环形链表 + lt.142-环形链表 II

东言肆语 2022-04-01 阅读 52

lt.141-环形链表

[案例需求]
在这里插入图片描述在这里插入图片描述

[思路分析]

  • 环形链表快慢针哈哈, 固定搭配了.
  • 同向快慢针一般是fast走两步, slow移动一步, 在探测环时, 由于slow与fast在环内, 随着快指针遍历完一圈后, fast与slow的距离就靠近了一个结点的距离, 经过在圈内多轮的你追我赶, 必将重逢在某一个节点上.
    在这里插入图片描述

[代码实现]

/**
 
 为什么fast 走两个节点,slow走一个节点,有环的话,一定会在环内相遇呢,而不是永远的错开呢?

首先第一点: fast指针一定先进入环中,如果fast 指针和slow指针相遇的话,一定是在环中相遇,这是毋庸置疑的。

那么来看一下,为什么fast指针和slow指针一定会相遇呢?

这是因为fast是走两步,slow是走一步,其实相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合。
 
  */
public class Solution {
    public boolean hasCycle(ListNode head) {
        //快慢针
        if(head == null) return false;  

        ListNode slow = head.next;
        ListNode fast = head.next;

        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;

            if(fast == slow) return true;
        }

        return false;
    }
}

lt.142-环形链表 II

[案例分析]

在这里插入图片描述

[思路分析一, 标记法(会修改链表结点的内容)]

- 把遍历过的结点都通过结点的val打上标记(这个val的值我们设为题目给定范围( node ∈([10的-5次方, 10的5次方])之外;
- 每次遇到的新节点我们先判断是否为标记值, 如果已经是标记值了那就存在环, 如果不是就打上标记, 继续往下遍历, 知道遇到null值或标记值
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head == null || head.next == null)return null;
        //标记法
        //一次遍历即可
        ListNode cur = head;

        while(cur != null && cur.val != 2147483647){
                    
            cur.val = 2147483647;  
            cur = cur.next;
        }
         return cur;       
    }
}
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head==null)return null;
        if(head.val==100001){
            return head;
        }else{
            head.val=100001;
            return detectCycle(head.next);
        }
    }
}

[思路分析二, 哈希表法]

  • 遍历链表, 每个遍历后的结点都要加入到List或Map中, 在加入之前我们先进行判断, 如果结合中已经存在这个节点了, 那么肯定存在环, 直接返回这个节点即可
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head == null) return null;

        /**
            遍历一遍链表, 遍历前添加第一个结点,  每遍历一个结点就把当前节点 temp.next 与 集合中的相比
            集合中存在, 则说明有环,  返回当前节点 temp;
            由于要求返回的是结点, 所以key为索引, value为ListNode 结点
         */

        Map<ListNode, Integer> map = new HashMap<>();

        ListNode temp = head;
        if(temp.next == temp) return temp;
        if(temp.next != null && temp.next != temp) map.put(temp, 0);
        int index = 1;
        while(true){
            if(temp == null) return null;

            if(map.containsKey(temp.next)){
                return temp.next;
            }

            map.put(temp, index++);
            temp = temp.next;        
        }

        return null;
        }
 }

[思路分析二, 快慢针法法]

public class Solution {
    public ListNode detectCycle(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {// 有环
                ListNode index1 = fast;
                ListNode index2 = head;
                // 两个指针,从头结点和相遇结点,各走一步,直到相遇,相遇点即为环入口
                while (index1 != index2) {
                    index1 = index1.next;
                    index2 = index2.next;
                }
                return index1;
            }
        }
        return null;
    }
}
举报

相关推荐

0 条评论