zoukankan      html  css  js  c++  java
  • 判断一个单链表中是否有环

    思路:快慢指针实现

    用两个指针,一个指针一次走一步,另一个指针一次走两步,如果存在环,则这两个指针会在环内相遇,时间复杂度为O(n)

      /**
         * 检测单链表中是否有环
         */
        public static boolean hasCircle(ListNode head) {
            if(null == head) {
                return false;
            }
            ListNode slow = head;
            ListNode fast = head;
            while(fast != null && fast.next != null){
                fast = fast.next.next;
                slow = slow.next;
                if(fast == slow){
                    return true;//两个指针相遇
                }
            }
            return false;
        }

    拓展1:如果单链表有环,找出环的入口节点(环的连接点)

      /**
         *如果单链表有环,找出环的入口节点(环的连接点)。
         *这里先证明一个定理:碰撞点到连接点的距离=头指针到连接点的距离
         *假设单链表的总长度为L,头结点到环入口的距离为a,环入口到快慢指针相遇的结点距离为x,环的长度为r,
         *慢指针总共走了s步,则快指针走了2s步。另外,快指针要追上慢指针的话快指针至少要在环里面转了一圈多(假设转了n圈加x的距离)
         *得到以下关系:
         *s = a + x
         *2s = a + nr + x
         *=>a + x = nr
         *=>a = nr - x //入口点
         */
        public static ListNode searchEntranceNode(ListNode head) {
            ListNode slow=head;//p表示从头结点开始每次往后走一步的指针
            ListNode fast=head;//q表示从头结点开始每次往后走两步的指针
            while(fast !=null && fast.next !=null) 
            {
                slow=slow.next;
                fast=fast.next.next;
                if(slow==fast) {
                    break;//p与q相等,单链表有环
                }
            }
            if(fast == null || fast.next == null){
                return null;
            }
            slow=head;
            while(slow != fast)
            {
                slow=slow.next;
                fast=fast.next;
            }
            return slow;
        }
      public static ListNode searchEntranceNode1(ListNode head){
            if(head == null || head.next == null)
                return null;
            ListNode slow = head;
            ListNode fast = head;
            while(fast != null && fast.next != null ){
                slow = slow.next;
                fast = fast.next.next;
                if(slow == fast){
                    fast=slow;//相遇点
                    slow=head;
                    while(slow != fast){
                        slow = slow.next;
                        fast = fast.next;
                    }
                    if(slow == fast)
                        return fast;
                    }
            }
            return null;
        }

    拓展二:求链表中环的长度

        /**
         * 求环的长度
         */
        public static int countCircleSize(ListNode head) {
            ListNode entranceNode = searchEntranceNode1(head);//环的入口点
            if(entranceNode == null) {
                return 0;
            }
            ListNode slow = entranceNode.next;
            int size = 1;
            while(slow != entranceNode) {
                slow = slow.next;
                size++;
            }
            return size;
        }
  • 相关阅读:
    C# DES加密和解密
    SQL设计技巧优化
    MS15-034漏洞技术研究
    Vustudy靶场环境快速搭建
    FastJson<=1.2.47漏洞复现
    多台电脑共享一套鼠键--Mouse Without Borders
    {Java初级系列四}---继承、接口和抽象类
    {Java初级系列三}---面向对象和类
    {Java初级系列二}---Java类基础知识
    {Java初阶系列一}---Java基本简介
  • 原文地址:https://www.cnblogs.com/cherish010/p/10572378.html
Copyright © 2011-2022 走看看