剑指OFFER笔记_23_链表中环的入口节点_JAVA实现

剑指OFFER笔记_23_链表中环的入口节点_JAVA实现

  • 题目:链表中环的入口节点
    • 解题思路
  • 代码
    • ListNode结构代码
    • 函数主体部分代码
    • 测试部分代码
    • 运行结果截图

题目:链表中环的入口节点

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

解题思路

  • 首先应该判断这个链表中有没有环。
  • 可以定义两个节点都赋值为头节点,然后一个节点一次走一步,另一个一次走两步,如果没有环,走得快的节点会遇到node.next==null的情况,否则两个节点会在某一时刻相遇(即相同)。
  • 在确定了有无环之后,需要判断哪个节点是入口节点。如果这个环的长度为4,我们再定义两个节点,其中一个节点比另一个提前多走4步。然后两个节点同时前进,由于两个节点之间的距离就等于环的长度,所以当两个节点相遇的时候,它们所在的位置就是环的入口。
  • 所以我们在此之前还需要去求得环的长度。因为在确定有无环的时候,我们让两个节点在某一时刻相遇了,我们可以将此刻的位置记录下来,然后继续走,直到回到这个点,这是走过的长度就是环的一周。这样环的长度也就求出来了。
  • 综合上面的逻辑思路,可以写出如下代码:
  • 由于此题在LeetCode上没有类似题目,所以没有LeetCode测试。

代码

ListNode结构代码

package q23;

public class ListNode {
    public int val;
    public ListNode next;
    public ListNode(int x) {
        this.val = x;
        this.next = null;
    }

    public static void outputLink(ListNode head)
    {
        ListNode pNode = head;
        while (pNode != null)
        {
            System.out.print(pNode.val + " ");
            pNode = pNode.next;
        }
        System.out.println();
    }
}

函数主体部分代码

package q23;

/**
 * 如果一个链表中包含环,如何找出环的入口节点?
 */
public class Solution {
    public ListNode findEntranceNode(ListNode head)
    {
        if (head == null) {
            return null;
        }
        //确定是否包含环
        ListNode slowNode = head;   //一次走一步
        ListNode fastNode = head;   //一次走两步
        ListNode nodeInCircle = null;

        while (fastNode.next != null)
        {
            fastNode = fastNode.next;
            slowNode = slowNode.next;

            if (fastNode.next != null)
            {
                fastNode = fastNode.next;
            }else{
                return null;
            }

            if (slowNode == fastNode)
            {
                nodeInCircle = slowNode;
                break;
            }
        }

        //得到环中节点的数目
        ListNode pNode = nodeInCircle;
        int countInCircle = 1;
        while (pNode.next != nodeInCircle)
        {
            pNode = pNode.next;
            countInCircle++;
        }

        //找到环的入口
        slowNode = head;
        fastNode = head;
        //fastNode先走
        for (int i = 0; i < countInCircle; i++) {
            fastNode = fastNode.next;
        }

        //slowNode和fastNode同步走,直到相同
        while (slowNode != fastNode)
        {
            fastNode = fastNode.next;
            slowNode = slowNode.next;
        }
        return slowNode;
    }
}

测试部分代码

package q23;

public class TestApp {
    public static void main(String[] args) {
        ListNode node1 = new ListNode(1);
        node1.next = new ListNode(2);
        node1.next.next = new ListNode(3);
        node1.next.next.next = new ListNode(4);
        node1.next.next.next.next = new ListNode(5);
        node1.next.next.next.next.next = new ListNode(6);
        node1.next.next.next.next.next.next = node1.next.next;
        Solution s = new Solution();
        System.out.println(s.findEntranceNode(node1).val);
    }
}

运行结果截图

剑指OFFER笔记_23_链表中环的入口节点_JAVA实现_第1张图片

  • 此时可以看出得到的入口节点的值为3,与设计的环情况相同。

你可能感兴趣的:(学习笔记)