leetcode 287 寻找重复数

先写下自己的做法吧,虽然违规了。首先是对数组排序,让所有元素按升序排列。之后使用二分法查找,判断的依据是当前节点的索引值+1与当前节点值的大小关系。可以考虑如果不存在重复数,完成排序后的数组,某一节点的值与当前索引值+1应当是保持一致。当数组中出现重复数,该重复数会将大于自己的数的索引向后挤压。通过这一原理可以实现查找,贴代码

 1 class Solution {
 2 public:
 3     int findDuplicate(vector<int>& nums) 
 4     {
 5         vector<int> newNums = nums;
 6         sort(newNums.begin(),newNums.end());
 7         int p = 0;
 8         int q = newNums.size()-1;
 9         while(p<q)
10         {
11             int indexMid = (p+q)/2;
12             //如果当前索引值+1小于等于节点值,则表示当前节点前方不存在重复值,即便当前值就是重复值,也一定是第一个重复值,p向后并不影响结果
13             if(indexMid+1<=newNums[indexMid])
14             p = indexMid+1;
15             //else if(indexMid+1>newNums[indexMid])
16             //q = indexMid;
17             else
18             q = indexMid;
19             //return newNums[indexMid];
20         }
21         return newNums[q];
22     }
23 };

官方题解第一种做法,同样是二分查找,不过是统计对于某一值而言,该数组中小于等于该数的个数应当小于等于该值。该例的二分查找是对值的查找,而不是对索引的查找。代码不贴了,要看上leetcode看解析吧。

另外一种做法是龟兔赛跑的做法,把数组索引至节点值的映射看作一条边,该数组构成的图中一定存在环,因为有不止一个索引值指向同一个元素。设定快慢指针,两个指针相遇之后,将慢节点调整至0索引处,之后每次快慢指针只移动一步,下次相遇的位置就是答案。至于解释,可以想象快指针走的路程是两倍的慢指针走的路,可以假设成快指针先走到相遇处,然后慢指针与快指针一起走,直到相遇。现在想象快指针已经到了相遇点,而满指针正好从起始点出发,双方会在首先在环的起点相遇,并且相伴走到相遇点,所以,第一个相遇的点就是环的起始点。贴代码

leetcode 287 寻找重复数
 1 class Solution {
 2 public:
 3     int findDuplicate(vector<int>& nums) 
 4     {
 5         int slow = 0, fast = 0;
 6         do {
 7             slow = nums[slow];
 8             fast = nums[nums[fast]];
 9         } while (slow != fast);
10         slow = 0;
11         while (slow != fast) {
12             slow = nums[slow];
13             fast = nums[fast];
14         }
15         return slow;
16     }
17 };
View Code

 

上一篇:2_26.删除有序数组中的重复项


下一篇:链表有环知多少~