剑指offer---链表中环的入口节点

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

         解题思路

          对于这个题,我们可以选择遍历一遍整个链表,每次用一个list存起来,然后每存一个节点的时候都看一下list里面是否存在这个节点,如果存在,就为环。且因为我们是从头开始遍历,所以第一个后来遍历到并且存在于list里面的节点肯定是环的入口。

          但是考虑到可以用set,因为set中是不能存重复的元素的,所以我们可以存在set里面,每次存入一个节点的时候都只是比较加入一个节点之后和之前set的size,如果size没变,就确定刚刚这个set里面存了这个元素,就说明有环,并且第一个找到在set里面可以存在的元素就是环的入口。这样的好处是避免了每次contain都是全局扫描,时间复杂度O(N),比较size的时间复杂度是O(1)

       代码:

 

public  ListNode EntryNodeOfLoop(ListNode pHead) {
    if(pHead==null||pHead.next==null)
        return null;
    //因为set不能重复存储,每次只要比较set的大小,可以避免list的contains全局搜索
    Set<ListNode>set=new HashSet<>();
    ListNode cur=pHead;
    while (cur!=null){
        //先记录当前set的size,方便与后面的作比较
        int size=set.size();
        set.add(cur);
        //如果这边size没有变,说明没有添加进去,就说明是有环了,
        // 并且我们是从头开始,碰到的第一个加不进去的肯定就是环的入口
        if(size==set.size()){
            return cur;
        }
        cur=cur.next;
    }
    return cur;
}

 

      补充:如果仅仅只是判断一个链表有没有环,不需要找到环的入口,考虑到空间复杂度,通常不会用一个list或者set,而是用快慢两个指针,一个一次性走一步,一个一次性走两步,如果两个指针最终相遇,就说明链表是有环的。

public  boolean NodeOfLoop(ListNode pHead) {
    if(pHead==null||pHead.next==null)
        return false;
    ListNode quickNode=pHead;
    ListNode slowNode=pHead;
    //因为除了第一个,而我们在前面判断过不为空,快指针比满指针走的快,
    // 所以慢指针走的都是快指针走过的,所以每次只需要判断快指针就可以
    while (quickNode!=null&&quickNode.next!=null){
        //quickNode.next==pHead、quickNode.next.next==pHead和slowNode.next==pHead是存在跑了一圈回到起点的情况,
       //可以提前结束遍历            if(quickNode.next==pHead||quickNode.next.next==slowNode.next||quickNode.next.next==pHead||slowNode.next==pHead){
             return true;
}
               
           quickNode=quickNode.next.next;
            slowNode=slowNode.next;
        }
   return false;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值