剑指 Offer 03. 数组中重复的数字

202 阅读2分钟

算法: 剑指 Offer 03. 数组中重复的数字

题目

要求: 找出数组中重复的数字。

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

示例 1:

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

限制:

2 <= n <= 100000

来源:力扣(LeetCode)链接:剑指 Offer 03. 数组中重复的数字

解题思路

方法一 : 排序数组

  • 将输入的数组排序
  • 从头到尾扫描排序后的数组,找出重复的数组
  • Time: O(nlogn)
  • Space: O(1)

方法二 : 哈希表

  • 从头到尾按顺序扫描数组每个数组,每扫描一个数字的时候,都可以用O(1)的瞬间来判断哈希是否包含此数字。
  • 如果哈希表没有这数字,则加入哈希表。如果有,则找到了重复的数字。
  • Time:O(1)
  • Space: O(n)

方法三: 比较 - 交换

  • 判断i对应值与下标是否不相同,相同则下一个元素。不同则将值作为下标m,找到下标m对应的值。
  • 判断m对应值与i对应的值是否相等,不相等则交换
  • 直到当前i位置的值等于下标值

代码

/**
 * @param {number[]} nums
 * @return {number}
 */
/**
 * 思路: 
 *  1. 判断i对应值与下标是否相同,相同则继续。不同则将值作为下标m,找到m对应的值。
 *  2. 判断此时m下标对应值与i对应值是否相等,不相等则交换。
 * 
 *  Time: 尽管两重循环,但每个数字最多只要交换两次就能找到属于它自己的位置,总的Time: O(n)
 *  Space: 不需要分配额外空间, space: O(1)
 */

var findRepeatNumber = function(nums) {
    let len = nums.length;
    if(nums == null || len <= 0){
        return -1;
    }

    for(let i = 0;i < len; ++i){
        if(nums[i] < 0 || nums[i] > len - 1){
            return false
        }
    }

    const swap = (nums,index1,index2) => {
        [nums[index1],nums[index2]] = [nums[index2],nums[index1]];
    }

    for(let i = 0; i < len; ++i){
        while(nums[i] != i){
            if(nums[i] == nums[nums[i]]){
                // i.value = m.value
                return nums[i];
            }

            swap(nums,i,nums[i]);
        }
    }
    return nums[i];
};