Leetcode287. 寻找重复数(数组模拟链表的快慢指针法)
Posted xdcat
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode287. 寻找重复数(数组模拟链表的快慢指针法)相关的知识,希望对你有一定的参考价值。
寻找重复数
根据题意,数组中的数字都在1~n之间,所以数字的范围是小于数组的范围的,数组的元素可以和数组的索引相联系。
例如:nums[0] = 1 即可以将nums[0]作为索引 通过nums[0] 可以访问到nums[1],以此类推。
如左图所示,环的入口就是重复元素。
那么问题就转化为了如何找到入环的第一个节点的问题。时间复杂度为O(n)
慢指针可以定义为:nums[slow] 快指针可以定义为:nums[nums[fast]]
1 class Solution { 2 public int findDuplicate(int[] nums) { 3 int slow = 0; 4 int fast = 0; 5 slow = nums[slow]; 6 fast = nums[nums[fast]]; 7 while(slow != fast){ 8 slow = nums[slow]; 9 fast = nums[nums[fast]]; 10 } 11 fast = 0; 12 while(slow != fast){ 13 fast = nums[fast]; 14 slow = nums[slow]; 15 } 16 return slow; 17 } 18 }
【下面顺便复习一下关于链表的题】
环形链表
141. 环形链表
1. 判断是否有环的思路:使用快慢指针。快指针走两步,慢指针走一步,最终快慢指针在环上相遇,且绕圈小于两圈。
1 public class Solution { 2 public boolean hasCycle(ListNode head) { 3 if(head == null || head.next == null || head.next.next == null){ 4 return false; 5 } 6 ListNode slow = head.next; 7 ListNode fast = head.next.next; 8 while(slow != fast){ 9 if(fast.next == null || fast.next.next == null){ 10 return false; 11 } 12 slow = slow.next; 13 fast = fast.next.next; 14 } 15 return true; 16 } 17 }
142. 环形链表 II
2. 寻找入环第一个节点:使用快慢指针。快指针走两步,慢指针走一步,一起走到相遇节点后,慢指针不动,快指针回到原点,然后快慢指针再一起一步一步地走,相遇点即入环的第一个节点。
1 public class Solution { 2 public ListNode detectCycle(ListNode head) { 3 if(head == null || head.next == null|| head.next.next == null){ 4 return null; 5 } 6 ListNode slow = head.next; 7 ListNode fast = head.next.next; 8 while(slow!=fast){ 9 if(fast.next == null || fast.next.next == null){ 10 return null; 11 } 12 slow = slow.next; 13 fast = fast.next.next; 14 } 15 fast = head; 16 while(slow != fast){ 17 slow = slow.next; 18 fast = fast.next; 19 } 20 return slow; 21 } 22 }
相交链表
3. 找出两个链表相交的第一个节点
两个链表的三种可能情况:
- 一个有环,一个无环:不可能相交
- 两个都无环:需要判断是否相交。相交,则是第一个相交节点。不相交,返回null。
- 两个都有环
- 两个各自一个环:不相交,返回null
- 两个共用一个环
- 先找入环的第一个节点 loop1和loop2
- 入环节点一样:loop1==loop2 可以转化为无环的相交问题,终止节点变成了loop节点。
- 入环节点不一样:loop1继续向下走直到遇到loop2,如果没有遇到则是两个各自一个环。返回loop1或loop2。
Leetcode:面试题 02.07. 链表相交
两个都无环相交的情况:
思路:如果两个链表相交,那么末尾的节点一定是同一个,因为一个节点只有一个出度。假设长链表长len1,短链表长len2,长链表先走len1-len2步,短链表从回到起点跟着一起走,相遇点即交点。
1 public class Solution { 2 public ListNode getIntersectionNode(ListNode headA, ListNode headB) { 3 ListNode curA = headA; 4 ListNode curB = headB; 5 int lenA = 0, lenB = 0; 6 while(curA != null){ 7 curA = curA.next; 8 lenA ++; 9 } 10 while(curB != null){ 11 curB = curB.next; 12 lenB ++; 13 } 14 //A始终是长链表 15 curA = lenA > lenB ? headA:headB; 16 curB = curA == headA? headB:headA; 17 int del = Math.abs(lenA - lenB); 18 while(del > 0){ 19 curA = curA.next; 20 del--; 21 } 22 while(curA!=curB){ 23 if(curA.next == null || curB.next == null){ 24 return null; 25 } 26 curA = curA.next; 27 curB = curB.next; 28 } 29 return curA; 30 } 31 }
两个都有环相交的情况:
【待续】
以上是关于Leetcode287. 寻找重复数(数组模拟链表的快慢指针法)的主要内容,如果未能解决你的问题,请参考以下文章