算法练习篇之:链表中环的入口节点

算法练习篇之:链表中环的入口节点

题目描述

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

解题思路

此题有两种思路来做:
第一种:利用HashSet()储存节点
从链表头节点开始,依次将链表每一个节点存入到hashset中,并检查每次存入的元素是否已经在hashset中重复出现,因为链表中存在环的结构,当某一次检查到当前将要add的节点已在hashset中存在时,该节点即为链表的入环节点。可能有人已经发现了一些小问题,对的,这种方法必须针对链表元素没有重复出现的情况才能适用!
第二种:设置快慢指针(一般方法)
这种方法适用任何情况,包括元素重复出现。这题的思想和寻找链表倒数第K个节点有些相似,本题中,我们假设快指针每次移动两步,而慢指针每次移动一步。如果链表有环形结构,其两个指针一定会在环内相遇,相遇后,我们在重新设定一个指针从头节点出发,而慢指针则在相遇点继续出发,两指针移动速度相同,每次都移动一步,则当两指针相遇时一定会在链表的入环节点处

图示

在这里插入图片描述
快指针P1和慢指针P2,同时从头节点‘1’出发时,第一次在节点**‘5’处相遇**。慢指针P2在‘5’处移动,而P1从头节点‘1’开始移动,两指针速度保持一致,最后第二次在节点‘3’,也是链表的入环节点处相遇

代码实现

博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

import java.util.HashSet;

class ListNode{ //定义链表节点
    ListNode next;
    int val;
    public ListNode(ListNode listNode,int val){
        this.val=val;
        this.next=listNode;
    }
    public ListNode(){}
}

public class entryNodeOfLoop {
    //用快慢指针寻找链表环形的入口
    public ListNode entryOfLoop_1(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;
        }

        ListNode newStart=pHead;//重新定义一个指针从头节点出发
        while (slow!=null&&newStart!=null){
            if (slow==newStart){//pHead与slow相遇在环的入口节点处
                return slow;
            }
            slow=slow.next;
            newStart=newStart.next;
        }
        return null;
    }

    public ListNode entryOfLoop_2(ListNode pHead){
        HashSet<ListNode> pSet=new HashSet<>();
        while (pHead!=null){
            if (pSet.contains(pHead)){
                return pHead;
            }
            pSet.add(pHead);
            pHead=pHead.next;
        }
        return null;
    }
    public static void main(String[] args) {

        ListNode first = new ListNode();
        ListNode second = new ListNode();
        ListNode third = new ListNode();
        ListNode fourth = new ListNode();

        first.val = 1; first.next = second;
        second.val = 2; second.next = third;
        third.val = 3; third.next = fourth;
        fourth.val = 4; fourth.next = second;

        entryNodeOfLoop entry=new entryNodeOfLoop();
        ListNode node=entry.entryOfLoop_1(first);
        System.out.println(node);
    }
}


总结

本题来源于面试经典教材《剑指offer》中 归属于链表类型题目。
同许多在算法道路上不断前行的人一样,不断练习,修炼自己!
如有博客中存在的疑问或者建议,可以在下方留言一起交流,感谢各位!
最后,感谢Jerry算法!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值