• 判断一个单链表中是否有环


    思路:快慢指针实现

    用两个指针,一个指针一次走一步,另一个指针一次走两步,如果存在环,则这两个指针会在环内相遇,时间复杂度为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;
        }
  • 相关阅读:
    5G终端测试 FOTA功能
    利尔达 UIS8910DM 模组的 发送短信TEXT格式
    利尔达 UIS8910DM 模组的 发送短信PDU格式
    altera原厂 cyclone V开发板使用记录
    【3】TensorFlow光速入门-训练及评估
    【2】TensorFlow光速入门-数据预处理(得到数据集)
    【1】TensorFlow光速入门-tensorflow开发基本流程
    【0】TensorFlow光速入门-序
    DbHelperSQL
    Git——简单的分支规范
  • 原文地址:https://www.cnblogs.com/cherish010/p/10572378.html
Copyright © 2020-2023  润新知