【每日一题-leetcode】判断链表是否有环、环形链表的长度、入环节点

解题思路

首先创建两个对象p1和p2,让它们同时指向这个链表的头节点

  • 然后开始一个大循环,在循环体中,让对象p1每次向后移动1个节点

  • 让对象p2每次向后移动2个节点

  • 比较两个指针指向的节点是否相同

如果相同,则可以判断出链表有环,如果不同,则继续下一次循环

package com.interview;

/**
 * @Date 2020/5/23 10:53
 * @Author by hp
 * @Description 环形链表
 */
public class NodeCycleDemo {

    /**
     * 判断是否有环
     *
     * @param head 链表头节点
     * @return
     */
    public static boolean isCycle(Node head) {
        Node p1 = head;
        Node p2 = head;
        while (p2.next != null && p2 != null) {
            p1 = p1.next;
            p2 = p2.next.next;
            if (p1 == p2) {
          		//环形链表的长度
                nodeLength(p1, p2);
                
				//入环节点
                startCycle(head, p2);
                return true;
            }
        }
        return false;
    }

环形链表长度

当两个指针首次相遇,证明链表有环的时候

  • 让两个指针从相遇点继续循环前进,并统计前进的循环次数,直到两个指针第2次相遇。
  • 此时,统计出来的前进次数就是环长。

因为指针p1每次走1步,指针p2每次走2步,两者的速度差是1步。 当两个指针再次相遇时,p2比p1多走了整整1圈

环长 = 每一次速度差 × 前进次数 = 前进次数

/**
 * 环形链表的长度
 *
 * @param p1 每次移动1格
 * @param p2 每次移动2格
 * @return
 */
public static void nodeLength(Node p1, Node p2) {
    int temp = 0;
    do {
        p2 = p2.next;
        temp++;
    }
    while (p1 != p2);
    System.out.println("环形链表长度 = " + temp);
}

入环节点

  • 把其中一个指针放回到头节点位置, 另一个指针保持在首次相遇点
  • 两个指针都是每次向前走1步。
  • 那么,它们最终相遇的节点,就是入环节点。
   /**
     * 入环节点
     *
     * @param p1 回到头结点每次移动一格
     * @param p2 每次移动一格
     *           p1 和p2再次相遇的位置就是入环节点
     */
    public static void startCycle(Node p1, Node p2) {
        while (p1 != p2) {
            p1 = p1.next;
            p2 = p2.next;

        }
        System.out.println("入环节点 = " + p2.data);
    }
static class Node {
    private int data;
    private Node next;

    Node(int data) {
        this.data = data;
    }
}
  public static void main(String[] args) throws Exception {
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);
        Node node5 = new Node(5);
        Node node6 = new Node(6);
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        node5.next = node6;
        node6.next = node2;

        System.out.println("是否存在环形链表:"+isCycle(node1));
    }

测试结果

【每日一题-leetcode】判断链表是否有环、环形链表的长度、入环节点_第1张图片

你可能感兴趣的:(【每日一题-leetcode】判断链表是否有环、环形链表的长度、入环节点)