判断链表是否有环 如果有,那么找出环的入口

20 篇文章 0 订阅
15 篇文章 0 订阅

常见的面试题,除了会写代码之外,还要会数学推导,也就是深入理解原理,下面进行说明

1 判断链表是否有环

设置两个指针,一个快指针和一个慢指针,快指针每次向前移动2步,慢指针每次移动1步,由于快指针的移动速度快于慢指针,所以链表如果无环,快指针会先到达末尾,也就是NULL的位置;链表如果有环,快指针会先进入环内,之后会一直在环内移动,快慢指针最终在环内的某个位置相遇。

慢指针p;快指针q;环的长度为C

2 找出单链表中环入口的位置

//两个指针,一个从链表头部开始走,一个从相遇点开始走,相遇的位置即为入口结点

//剑指offer--链表中环的入口结点
public static ListNode EntryNodeOfLoop(ListNode pHead)
{
    if (pHead == null || pHead.next == null)
        return null;
    ListNode slow = pHead;
    ListNode fast = pHead;

    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;

        if (slow == fast) {
            break;
        }
    }

    if (fast == null || fast.next == null) {
        return null;
    }

    int circleNode = 1;
    ListNode p = slow;

    while (p.next != slow) {
        p = p.next;
        circleNode++;
    }

    slow = pHead;
    fast = pHead;

    while (circleNode > 0) {
        fast  = fast.next;
        circleNode--;
    }

    while ( slow != fast) {
        slow = slow.next;
        fast = fast.next;
    }

    return slow;
}

//leetcode142--链表中环的入口结点
//两个指针,一个从链表头部开始走,一个从相遇点开始走,相遇的位置即为入口结点
public static ListNode detectCycle(ListNode head) {
    if (head == null || head.next == null) {
        return null;
    }

    ListNode walker = head;
    ListNode runner = head;

    while (runner != null && runner.next != null) {
        walker = walker.next;
        runner = runner.next.next;

        if (walker == runner) {
            break;
        }
    }

    if (runner == null || runner.next == null)
        return null;

    //walker指向链表头部
    walker = head;

    while (walker != runner) {
        walker = walker.next;
        runner = runner.next;
    }

    return walker;
}

public static void main(String[] args) {
    ListNode head = new ListNode(0);
    ListNode p1 = new ListNode(1);
    ListNode p2 = new ListNode(2);
    ListNode p3 = new ListNode(3);
    ListNode p4 = new ListNode(4);
    ListNode p5 = new ListNode(5);
    head.next = p1;
    p1.next = p2;
    p2.next = p3;
    p3.next = p4;
    p4.next = p5;
    p5.next = p3;

    ListNode p = detectCycle(head);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值