LeetCode——141. Linked List Cycle && 142. Linked List Cycle II
来源:互联网 发布:网络女主播直播间 编辑:程序博客网 时间:2024/06/06 07:25
今天再次推出一套组合题。
首先是:141.Linked List Cycle
问题描述:
Given a linked list, determine if it has a cycle in it.Follow up:Can you solve it without using extra space?
题目大致的意思就是给你一个链表,判断它里面是否含有环,有的话返回true,没有的话返回false。
我们可以把这个链表抽象成一条直线加一个圆(如果它有环的情况下),如下图:
对于这道题,我一开始的想法就是,保存你走过的点,然后当你再次走到你走过的点,不就可以证明链表有环咯。这种方法很简单,我就没写代码,用一个hashmap来保存点就可以实现了。
但是,题目要求的是常数级的空间复杂度,说明我们不能通过保存状态的这种方法来实现了,得想另外一种方法。最近刚好要体育测试,我就想起与女朋友跑步的情形:她跑得慢,我跑得快,最后我跑多一圈还是会追上她,与她相遇。放在这里就是:如果有环的话,我用一个快指针(移动比较快的)在前面跑,一个慢指针(移动比较慢的)在后面跑,如果最后快指针能够与慢指针相遇,不就说明链表中有环了吗?问题迎刃而解。我写了两种代码,第一种是两者的速度是会不断变大的,他们之间速度的差距也会不断变大,这样子可以快一点到达环,但是在环中也要走比较多的路两者才能相遇;第二种是固定快指针的速度是慢指针速度的两倍,快指针一次走两步,慢指针一次走一步,这样子虽然比较慢到达环,不过在环中两者会很快就相遇。两者其实差别不大,第二种是我在做第二题的时候才写的,因为第二题就需要具体的量化了,所以必须要有一个准确的量。下面是代码:
public boolean hasCycle(ListNode head) { //方法1,两者的速度差距越来越大,最后也会相遇,不过可能会走了多余的路,效率低一点 ListNode fastP = head; ListNode slowP = head; int fastPath = 1; int slowPath = 0; while(slowP != null) { //根据速度来移动快指针 for(int i = 1; i <= fastPath; i++) { fastP = fastP.next; if(fastP == null) return false; if(fastP == slowP) return true; } //根据速度来移动慢指针 for(int i = 1; i <= slowPath; i++) { slowP = slowP.next; if(slowP == null) return false; if(slowP == fastP) return true; } //因为快指针移动地比慢指针快,因此,快指针所移动的步数一定逐渐多余慢指针,才能显出两者速度的差距 slowPath += 1; fastPath += 2; } return false; //方法2,两者的速度定下来,快指针的速度是满指针的两倍 //那么实际上只要快指针比满指针走多一圈,两者就可以相遇了,不需要走冤枉路 ListNode fastP = head; ListNode slowP = head; while(fastP != null && fastP.next != null) { fastP = fastP.next.next; slowP = slowP.next; if(slowP == fastP) return true; } return false; }
第一题的解法就是这样,其实也不难。
接下来就是第二道题:142. Linked List Cycle II
问题描述:
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.Note: Do not modify the linked list.Follow up:Can you solve it without using extra space?
这道题与上一道题差不多,只不过这道题是要找到环的起点,并返回。如果链表中不存在环就返回null。
最开始依然是想到用hashmap来保存访问过的点,当你再次访问到已经访问过的点时,那个点就是起点,很容易理解,不过不满足常数级空间复杂度,代码如下:
public ListNode detectCycle(ListNode head) { //这是使用了额外空间的方法 Map<Integer, List<ListNode>> tempMap = new HashMap<>(); ListNode cur = head; while(cur != null) { if(!tempMap.containsKey(cur.val)) { List<ListNode> tempList = new LinkedList<>(); tempList.add(cur); tempMap.put(cur.val, tempList); } else { for(ListNode p : tempMap.get(cur.val)) { if(p == cur) return cur; } tempMap.get(cur.val).add(cur); } cur = cur.next; } return null; }
当然了,我们肯定是要继续优化,实现常数级的空间复杂度。不过说实话,挺难想的。后来我也是直接看大神的解答,才发现,这里涉及到了一点简单的几何推导。我是真的没想到啊,写个算法题,简单的几何推导也弄出来了。下面就看我的图来跟着我的思路走吧,其实很简单的:
a是链表起点到环起点Y的距离,Z是快指针与慢指针第一次相遇的点,b是Y到Z的劣弧,c是Z到Y的优弧
前方高能!!!
根据快指针的速度是慢指针速度的两倍,有:
2(a + b) = a + b + c + b
a+b是慢指针在相同时间内走的距离,a + b + c + b是快指针在相同时间内走的距离
两边相互消去,可以得到:
a + b = b + c
a = c!!!!!!
这一个等式相当重要。它意味着,用两个相同速度的指针,一个从第一次相遇点出发,另一个从链表起点出发,两者第一次相遇的点,就是环的起点!!!问题不就解决了吗!!!
下面是代码:
public ListNode detectCycle(ListNode head) { //不使用额外空间的方法,依旧是使用快慢指针,只不过这里限制了快指针的速度为慢指针速度的两倍 ListNode fastP = head; ListNode slowP = head; //这个循环是为了获取快指针和满指针的相遇点 while(true) { if(fastP == null || fastP.next == null) return null; fastP = fastP.next.next; slowP = slowP.next; if(fastP == slowP) break; } ListNode begin = head; //根据公式,从相遇点出发与从链表起点出发,两者最终相遇的地方,就是起点 while(begin != fastP) { begin = begin.next; fastP = fastP.next; } return begin; }
这种解法真是太6了!有没有!我根本就没想到这种题目还能抽象成几何题来做,看来我还是太弱了。
我觉得吧,以上两道题,都考了我们一种将具体的模型进行抽象的方法。如果在这两道题中,我们能够对这个模型进行抽象,然后运用到几何中一些简单的原理,问题是很容易解决的。所以有时我们需要将抽象的模型具象化,有时也需要将具体的模型抽象化,这也是一种很重要的思维。
谢谢大家观看我的博客。如果有不明白的地方,或者是文中有错误的地方,欢迎指出,谢谢!如果大家喜欢我的博客,也可以给我点点赞。你们的点赞就是我的动力!
- [LeetCode]141. Linked List Cycle【&142. Linked List Cycle II】
- leetcode--141. Linked List Cycle&&142. Linked List Cycle II
- LeetCode 141. Linked List Cycle && 142. Linked List Cycle II
- LeetCode——141. Linked List Cycle && 142. Linked List Cycle II
- LeetCode——Linked List Cycle II
- LeetCode——Linked List Cycle II
- 142. Linked List Cycle II leetcode list
- 141. Linked List Cycle & 142. Linked List Cycle II
- 141. Linked List Cycle&142. Linked List Cycle II
- LeetCode[Linked List]: Linked List Cycle II
- Algorithms—142.Linked List Cycle II
- 【LeetCode】 Linked List Cycle II
- Leetcode: Linked List Cycle II
- <Leetcode>Linked List Cycle II
- [LeetCode] Linked List Cycle II
- Leetcode: Linked List Cycle II
- LeetCode:Linked List Cycle II
- Leetcode Linked List Cycle II
- 对话|索尼音频高层:重点布局耳机、回音壁、智能音箱三大领域
- 搜狗递交赴美IPO申请;特斯拉召回万辆ModelX
- 谷歌自曝无人驾驶核心技术!700亿估值Waymo炼成之谜【附下载】| 智东西内参
- Java设计模式之模板模式(Template )
- Android设计模式(一)
- LeetCode——141. Linked List Cycle && 142. Linked List Cycle II
- 快速排序 quick sort
- React key值问题
- 马化腾:我创办腾讯的这些年
- 全球AI报告:探索人工智能革命
- 大牛激辩:AI 该像婴儿一样生来就懂事,还是该从零学习?
- 科学:螳螂虾大脑拥有记忆和学习中心
- 深度丨我们可以有多信任人工智能
- “芯”战争,人工智能芯片研发攻略