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

98 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

一、题目内容

二、解题方法

(一)暴力循环

最简单的方法就是暴力循环,使用双重循环遍历数组,即遍历数组的每个元素,然后看该元素是否与后面的元素相等,若相等就返回该元素(重复的元素)。这种方法最简单就不展示代码了。

  • 时间复杂度:O(n2)O(n^2)
  • 空间复杂度:O(1)O(1)

(二)哈希表解法

  • 由于数组中的元素值小于数组长度,因此可以利用哈希表对元素解析判重
  1. 使用数组创建一个哈希表bucket,并将它的元素值都初始化为-1;
  2. 遍历数组元素,如果哈希表中该元素值位置的值等于-1,就将该元素值赋给哈希表中该元素值位置,即bucket[nums[i]] = i;
  3. 如果不等于-1,就表明当前遍历的元素,在前面的遍历中出现过,即为重复元素,直接返回即可。 image.png
  • 解题代码如下:
    • 时间复杂度:O(n)O(n)
    • 空间复杂度:O(n)O(n)
/**
 * @param {number[]} nums
 * @return {number}
 */
var findRepeatNumber = function(nums) {
    let hashs = Array(nums.length).fill(-1);
    for(let i = 0;i<nums.length;i++){
        if(hashs[nums[i]]===-1){
            hashs[nums[i]] = i;
        } else{
            return nums[i]
        }
    }
};
  • 数组快速填充方法fill():用一个固定值填充一个数组中从起始索引到终止索引内的全部元素(不包括终止索引),使用示例如下: image.png

(三)原地交换解法(最优解法)

  • 该方法就是查找某个元素是否在两个位置出现
  1. 遍历数组,如果当前元素值等于当前索引值,则往下遍历;
  2. 如果当前元素值不等于当前索引值,就判断数组索引值为当前元素值位置的元素值是否等于当前元素值,即 if(nums[nums[i]]===nums[i])
    • 如果不等于,就交换两个元素位置,即将元素值i放到数组中索引值为i的位置;
    • 如果等于,就说明该元素在两个位置,即为重复元素,直接返回。
  • 解题代码如下:
    • 时间复杂度:O(n)O(n)
    • 空间复杂度:O(1)O(1)
/**
 * @param {number[]} nums
 * @return {number}
 */
var findRepeatNumber = function(nums) {
 
    for(let i = 0;i<nums.length;i++){
        if(nums[i]===i){
            continue;
        }else{
            if(nums[nums[i]]===nums[i]){
                return nums[i]
            }else{
                let temp =nums[nums[i]];
                nums[nums[i]] = nums[i]
                nums[i] =temp;
            }
        }
    }
};