• [编程题] nk 链表中的入环节点-快慢指针和哈希方法


    [编程题] nk:链表中的入环节点

    题目描述

    image-20200722095518414

    输入输出例子

    思路

    方法1、借助哈希表

    思想:我们通过一个dummyNode不断遍历每一个节点,当我们每次遍历到这个当前节点的时候就看他在不在哈希表中,不在的话加入进去;在的时候就恰好这个节点就是入环节点。

    时间复杂度:O(n)

    Java代码

    import java.util.*;
    /*
     public class ListNode {
        int val;
        ListNode next = null;
    
        ListNode(int val) {
            this.val = val;
        }
    }
    */
    public class Solution {
    
        //方法1:借助哈希表;
        //思想:每次遍历一个节点,就放入到哈希表,如果再次发现哈希表中有这个节点的时候就是环的入口
        public ListNode EntryNodeOfLoop(ListNode pHead){
            //跑龙套节点
            ListNode dummyNode = pHead;
            //哈希表
            HashSet<ListNode> hashSet = new HashSet<ListNode>();
            while(dummyNode!=null){
                if(hashSet.contains(dummyNode)){
                    return dummyNode;  //找到入环点
                }
                hashSet.add(dummyNode);  //否则放入哈希表
                dummyNode = dummyNode.next;
            }
            //退出循环,即为找到入环点,无环
            return null;
        }
    }
    

    输出的效率:

    image-20200722095802307

    方法2:快慢指针

    思想:

    总结思想:

    • 第一趟跑的时候找相遇点(定义fast=phead.next; slow = phead;错开的好)
    • 找到相遇点计算环长
    • 重新定义快慢指针指向,pFast指向phead,pSlow指向pHead后的环长n的位置;同时以step=1走
    • 相遇即返回该节点为入环点。

    时间复杂度O(n)

    Java代码

    //方法2:快慢指针(第一次快慢速度2:1找到相遇点,计算环长,第二次同步速度走,在入环点相遇)
        public ListNode EntryNodeOfLoop(ListNode pHead){
            //需要考虑只有一个节点的边界情况
            if(pHead==null) {return null;}
            
            //快慢指针
            ListNode pFast = pHead.next; //注意一开始让快慢指针错开,因为不错开的话,在第一次相遇点的逻辑中直接if比较返回相等。返回的就是首节点相遇
            ListNode pSlow = pHead;
            //标注是否有环
            boolean isCircle = false;
            //计算环长的计数器
            int count=1;
           
            //1 第一次走找是否有环和相遇点
            while(pFast!=null && pFast.next!=null){
                if(pFast==pSlow){  //在初始快慢指针赋值的时候让错开,不然在这里会返回首节点相遇的
                    isCircle = true;
                    break;//一定记得有环了跳出while
                }
                //否则快指针2倍速走,慢指针1倍速走
                pFast = pFast.next.next;
                pSlow = pSlow.next;
            }
            //2 检测isCircle字段看是否有环,有环的话就计算环长
            if(!isCircle){
                return null;//无环
            }else{//有环
               //2.1 让快指针从相遇点再绕环走一圈,计算环长
                pFast = pFast.next; 
                while(pFast!= pSlow){
                    count++; //这里while内用的dummyFast.next,故计算的count还差最后一步。
                    pFast = pFast.next;
                }
                
            }
            
            //3 我们得出了环长count值,重新把指针重新指向,快慢指针以step=1开始走,相遇就是入环点
            pFast = pSlow = pHead;
            //退出while后就是找到slow应该指向的节点的地方
            while(count>0){
                pSlow = pSlow.next;
                count--;
            }
            
            while(pFast!=pSlow){
                pFast = pFast.next;
                pSlow = pSlow.next;
            }
            //退出while,返回的节点就是相遇点
            return pFast;
        }
    
    

    时间复杂度 :O(n)

    输出:

    image-20200722111508410

    快慢指针简便一些的代码:

    //方法2:快慢指针
        public ListNode EntryNodeOfLoop1(ListNode pHead){
            if(pHead==null) {return null;}
            
            ListNode slow = pHead;  //慢指针
            ListNode fast = pHead;  //快指针
            
            //当快指针能退出的时候,肯定就是无环咯
            while(fast!=null && fast.next!=null){
                //k快慢指针不同速度走
                fast = fast.next.next;
                slow = slow.next;
                //当第一次相遇的时候,可能两并不在入环点相遇,那么此时:
                if(slow==fast){
                    //让慢指针回首节点
                    slow = pHead;
                    while(slow!=fast){
                        slow = slow.next;
                        fast = fast.next;
                    }
                    return fast; //再碰到了就是环点
                }
                 
            }
            return null;
        }
    
  • 相关阅读:
    【Selenium04篇】python+selenium实现Web自动化:文件上传,Cookie操作,调用 JavaScript,窗口截图
    【Selenium03篇】python+selenium实现Web自动化:元素三类等待,多窗口切换,警告框处理,下拉框选择
    【Selenium02篇】python+selenium实现Web自动化:鼠标操作和键盘操作!
    【Selenium01篇】python+selenium实现Web自动化:搭建环境,Selenium原理,定位元素以及浏览器常规操作!
    面试官看到一定会打我---软件测试工程师面试套路和暗语灵魂解密
    十年测试老鸟告诉你--自动化测试选JAVA还是选Python--写给还在迷茫中的朋友
    华为十年测试老鸟教您如何便写高质量的自动化测试工程师简历--看完必有所获
    工作中常用的Android系统ADB命令收集
    自动化测试中的三类等待深入剥析
    JAVA自动化之Junit单元测试框架详解
  • 原文地址:https://www.cnblogs.com/jiyongjia/p/13359591.html
Copyright © 2020-2023  润新知