【剑指 Offer 03】数组中重复的数字

找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

示例 1:

输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3 

限制:
2 <= n <= 100000

思路:

  • 一个简单的方法就是先排序,然后在排序数组中找就比较简单了。排序算法+从头扫描,这个算法的时间复杂度是O(nlogn)
  • 另一种方法是,创建一个hash表,用来存放数据,每扫描一个数字,就可以判断hash表里是否有该数字,没有就放进hash里,有的话就返回。这样的算法时间和空间复杂度都是O(n)
  • 第三种方法:
    • 我们注意到,数组里的元素都是0~n-1范围内的,如果这n个元素都不重复,那么排序之后,数字i将会出现在下标i这个位置上。因为数组里有重复的数字,会导致某些位置上有超过一个的数字,有些则没有。
    • 于是我们从头到尾开始扫描这个数组
    • 当我们扫描到第i个值时,先判断第i个数字m是否等于i,如果等于i,继续扫描,如果不等于i,就让数字m和第m个数值比较,如果相等,那就找到一个重复数字;如果不相等,那就把第i个数字m和第m个数字交换位置,让数字m在第m个位置,然后重新比较,交换。直到发现重复数字。
const findRepeatNumber = (nums: number[]): number => {
    const res = [];
    const n = nums.length;
    // 判断数组不为空,且数组的长度等于给出的长度
    if(!nums.length) return -1;
    
    // 判断数组内的每一个数字都在0~n-1的范围内
    for(let i = 0; i < n; ++i) {
        if(nums[i] < 0 || nums[i] > n -1 ) {
            return -1;
        }
    }
    
    //扫描,比较和交换
    for(let i = 0; i < n; ++i) {
        while(nums[i] !== i) {
            if(nums[i] === nums[nums[i]]) {
                res.push(nums[i]);
                return res[0];
            }else{
                let temp = nums[i];
                nums[i] = nums[temp];
                nums[temp] = temp;
            }
        }
    }
    return -1;
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章