链表中环的问题

链表中环的问题

使用哈希表进行判断
遍历并添加节点到哈希表,如果存在冲突,则表示成环。
如果不存在冲突,则表示未成环

   /**
     * 方法1:通过HashSet判断
     * 遍历并加入Map,key = val, value = node
     * 如果存在冲突则表示有环
     *
     * @param head
     * @return
     */
    public static boolean hasCycleByMap(ListNode head) {
        if (head == null) {
            return false;
        }
        Set<ListNode> set = new HashSet<>();
        while (head != null) {
            if (!set.add(head)) {
                return true;
            } else {
                head = head.next;
            }
        }
        return false;
    }

使用双指针进行判断
使用快慢指针进行判断,快2慢1,如果快==慢,则表示成环。
需要注意判断快指针的边界条件。

 /**
     * 方法2 通过双指针实现
     * 使用快慢指针,快2慢1,如果相遇则表示成环。
     *
     * @param head
     * @return
     */

    public static boolean hasCycleByTwoPoint(ListNode head) {
        if (head == null || head.next == null) {
            return false;
        }
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (slow == fast) {
                return true;
            }
        }
        return false;
    }

确定入口的方法

依然可以使用hashSet进行判断
遍历链表并添加到Set集合中,如果没出现冲突,表示就不存在环;
如果出现冲突,那么第一个冲突点即为环的入口节点。

 /**
     * 方法1:通过HashMap或者实现
     * 遇到重复的第一个元素,就是入口元素
     * @param head
     * @return
     */
    public static ListNode detectCycleByMap(ListNode head) {
        if (head == null || head.next == null) {
            return null;
        }
        Set<ListNode> set = new HashSet<>();
        while (head != null) {
            if (set.contains(head)) {
                return head;
            } else {
                set.add(head);
            }
            head = head.next;
        }
        return null;
    }

使用双指针进行判断
使用快慢指针进行判断,快2慢1,如果快==慢,则表示成环。
成环之后,在成环处和链表头节点各放一个指针,同时移动一个节点,相遇处即为入口节点。

/**
     * 方法2 通过双指针实现
     * 快慢指针先确定成环,在交集处以及head放两个指针,同时一部前进,交汇处为入口节点。
     *
     * @param head
     * @return
     */

    public static ListNode detectCycleByTwoPoint(ListNode head) {
        if (head == null) {
            return null;
        }
        ListNode slow = head, fast = head;
        ListNode pNode = null;
        while (fast !=  null && fast.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast == slow) {
                pNode = slow;
                break;
            }
        }
        if (pNode != null) {
            while (head != null){
                head = head.next;
                pNode = pNode.next;
                if (pNode == head) {
                    return head;
                }
            }
        }
        return null;
    }

Tips:个人总结,判断链表的边界条件时,可以这样理解,如果while循环体内使用到 node.next.next,则判断条件中一定得有node.next !=null;
如果用到node.next,则判断条件中一定得有node !=null,否则会出现NPE。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值