zoukankan      html  css  js  c++  java
  • 【Offer】[23] 【链表中环的入口结点】

    题目描述

    一个链表中包含环,如何找出环的入口结点?

    思路分析

    1. 判断链表中是否有环:用快慢指针的方法,慢指针走一步,快指针走两步,如果快指针追上了慢指针,就说明有环,而且他们相遇的节点是处于环中的节点
    2. 统计环中节点的个数:利用1中返回的节点,当再次走到该节点时,正好遍历了整个环,从而可以统计出个数n。
    3. 找出入口结点:也是设置两个指针,第一个指针先向后移动n,第二个指针指向头节点,然后同时移动两个指针,它们相遇时的节点就是环的入口节点,(类似于 【链表中倒数第k个结点】 中的思路)

    测试用例

    1. 功能测试:链表中包含或者不包含环;链表中有多个或者只有一
      节点。
    2. 特殊输入测试:链表头节点为nullptr指针。

    Java代码

    public class Offer23 {
        public static void main(String[] args) {
            test1();
            test2();
            test3();
            test4();
            test5();
        }
    
        public static ListNode EntryNodeOfLoop(ListNode head) {
            return Solution1(head);
        }
    
        /**
         * 1.判断链表中是否有环,并找出环中节点个数n 2.将一个指针向前移动n,另个一指针指向头节点 3. 然后同时移动两个指针,两个指针相遇时,就是环的入口
         * 
         * @param head
         * @return
         */
        private static ListNode Solution1(ListNode head) {
            if (head == null) {
                return null;
            }
            // 判断链表中是否有环,并找到快慢指针相遇的节点
            ListNode meetNode = MeetingNode(head);
            if (meetNode == null) {// 说明链表中没有环
                return null;
            }
            int count = 1; // 统计环中节点的个数
            ListNode pLoop = meetNode;
            while (pLoop.next != meetNode) {
                pLoop = pLoop.next;
                ++count;
            }
    
            ListNode p1 = head;
            for (int i = 0; i < count; i++) {
                p1 = p1.next;
            }
            ListNode p2 = head;
            while (p1 != p2) {
                p1 = p1.next;
                p2 = p2.next;
            }
    
            return p1;
        }
    
        /**
         * 设置两个指针,快指针一次走两步,慢指针一次走一步 如果快指针 追上了慢指针,就说明有环
         * 如果快指针走到尾部(null)时两个指针没有相遇,就说明两个指针没有环存在,
         * 
         * @param head
         * @return
         */
        private static ListNode MeetingNode(ListNode head) {
    
            if (head == null) {
                return null;
            }
            ListNode pSlow = head.next;
            if (pSlow == null) {
                return null;
            }
            ListNode pFast = pSlow.next;
    
            while (pSlow != null && pFast != null) {
                if (pSlow == pFast) {
                    return pFast;
                }
                pSlow = pSlow.next;
                pFast = pFast.next;
                if (pFast != null) {
                    pFast = pFast.next;
                }
            }
            return null;
        }
    
        private static void test1() {
    
            ListNode node1 = new ListNode(1);
            ListNode node2 = new ListNode(2);
            ListNode node3 = new ListNode(3);
            ListNode node4 = new ListNode(4);
            ListNode node5 = new ListNode(5);
            ListNode node6 = new ListNode(6);
    
            node1.next = node2;
            node2.next = node3;
            node3.next = node4;
            node4.next = node5;
            node5.next = node6;
            node6.next = node3;
    
            System.out.println("链表中有环而且有多个节点(>=3)---->");
            ListNode entryLoop = EntryNodeOfLoop(node1);
            if (entryLoop != null) {
                System.out.println(entryLoop.val);
            } else {
                System.out.println("null");
            }
        }
    
        private static void test2() {
            ListNode node1 = new ListNode(1);
            ListNode node2 = new ListNode(2);
            ListNode node3 = new ListNode(3);
            ListNode node4 = new ListNode(4);
            ListNode node5 = new ListNode(5);
            ListNode node6 = new ListNode(6);
            node1.next = node2;
            node2.next = node3;
            node3.next = node4;
            node4.next = node5;
            node5.next = node6;
            System.out.println("链表中没有环---->");
            ListNode entryLoop = EntryNodeOfLoop(node1);
            if (entryLoop != null) {
                System.out.println(entryLoop.val);
            } else {
                System.out.println("null");
            }
        }
    
        private static void test3() {
    
            ListNode node1 = new ListNode(1);
            ListNode node2 = new ListNode(2);
            node1.next = node2;
            node2.next = node1;
    
            ListNode entryLoop = EntryNodeOfLoop(node1);
            System.out.println("链表中有环,只有有两个个节点---->");
            if (entryLoop != null) {
                System.out.println(entryLoop.val);
            } else {
                System.out.println("null");
            }
        }
    
        private static void test4() {
    
            ListNode node1 = new ListNode(1);
            node1.next = node1;
    
            ListNode entryLoop = EntryNodeOfLoop(node1);
            System.out.println("链表中有环,只有一个节点---->");
            if (entryLoop != null) {
                System.out.println(entryLoop.val);
            } else {
                System.out.println("没有环");
            }
        }
    
        private static void test5() {
            ListNode entryLoop = EntryNodeOfLoop(null);
            System.out.println("传入null---->");
            if (entryLoop != null) {
                System.out.println(entryLoop.val);
            } else {
                System.out.println("null");
            }
        }
    
    }
    

    代码链接

    剑指Offer代码-Java

  • 相关阅读:
    C#深入浅出 修饰符(二)
    HDU 5785 Interesting
    HDU 5783 Divide the Sequence
    HDU 5781 ATM Mechine
    UVA 714 Copying Books
    uva 1471 Defense Lines
    UVA 11134 Fabled Rooks
    UVA 11572 Unique Snowflakes
    UVA 11093 Just Finish it up
    UVA 10954 Add All
  • 原文地址:https://www.cnblogs.com/haoworld/p/offer23-lian-biao-zhong-huan-de-ru-kou-jie-dian.html
Copyright © 2011-2022 走看看