[LEETCODE] 287. Find the Duplicate Number

来源:互联网 发布:电气原理图软件 编辑:程序博客网 时间:2024/04/28 16:18

[LEETCODE] 287. Find the Duplicate Number

Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.

Note:
You must not modify the array (assume the array is read only).
You must use only constant, O(1) extra space.
Your runtime complexity should be less than O(n2).
There is only one duplicate number in the array, but it could be repeated more than once.

这道题刚读题的时候觉得不应该是hard 难度的题。但是看了note 之后想了很久。。。。

一开始先用hash,因为有重复,所以直接把数存到对应的hash数组里面就很快可以找到,但是题目规定要O(1) ,所以不能使用额外的数组。。。

然后就想sort,结果题目又说不能修改array。。。

最后想用暴力遍历两次数组的方法,但是题目要求时间复杂度低于O(n2)。

最后发现可以用两种方法解决。
第一种是对暴力法的优化。就是使用2分的方法。根据抽屉原理,我们可以知道duplicate number 是在mid 的左边还是右边,以此类推,我们可以逐渐缩小范围,直至最后找到该duplicate number。

public class Solution {    public int findDuplicate(int[] nums) {        int min = 0, max = nums.length - 1;        while(min <= max){            int mid = min + (max - min) / 2;            int cnt = 0;            for(int i = 0; i < nums.length; i++){                if(nums[i] <= mid){                    cnt++;                }            }            if(cnt > mid){                max = mid - 1;            } else {                min = mid + 1;            }        }        return min;    }}

第二种是找环。如果array 中所有的数都是不同的话,那么下标和数是一一对应的关系,否则,下标和数就是多对一的关系。这样的话,如果我们每次都把下标对应的那个数作为新的下标,那么它最后会变成一个环。根据这个环我们就可以找到重复的那个数。

class Solution {public:    int findDuplicate(vector<int>& nums) {        int slow = 0;        int fast = 0;        do {            slow = nums[slow];            fast = nums[nums[fast]];        } while(slow != fast);        int find = 0;        while (find != slow) {            find = nums[find];            slow = nums[slow];        }        return find;    }};
0 0
原创粉丝点击