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

195 阅读2分钟

找出数组中重复的数字。

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

示例 1:

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

限制: 2 <= n <= 100000

解法一:暴力解法

选定一个元素值,与该元素后面的值一一进行比较,有重复数据即返回。

时间复杂度:O(N²)

空间复杂度:O(1)

var findRepeatNumber = function(nums) {
    // 查空
    if(nums.length == 0)    return -1
    // 查非法数据
    for(var i = 0; i < nums.length; i++){
        if(nums[i] < 0 || nums[i] > nums.length-1)  return -1
    }
    // 暴力解法
    for(var i = 0; i < nums.length-1; i++){
        for(var j = i+1; j < nums.length; j++){
            if(nums[i] == nums[j]){
                return nums[i]
            }
        }
    }
    return -1
};		

4.2.png

解法二:建立一个新数组打卡标记

通过建立一个固定长度的全0数组temp,temp下标为原数组元素的值,temp元素的值用于计数。

遍历temp的值,当元素>1,即出现重复,返回索引。

时间复杂度:O(N)

空间复杂度:O(N) 开辟临时数组temp

var findRepeatNumber = function(nums) {
    // 定义临时数组temp
    var temp = new Array(nums.length).fill(0)
    // 检查原数组是否为空
    if(nums.length == 0)    return -1
    // 数组数据不符合题意
    for(var i = 0; i < nums.length; i++){
        if(nums[i] < 0 || nums[i] > nums.length-1)    return -1
    }
    // 遍历原数组数值,计数
    for(var i = 0; i < nums.length; i++){
        temp[nums[i]]++
    }
    // 存在重复则大于1
    for(var i = 0; i < temp.length; i++){
        if(temp[i] > 1){
            return i
        }
    }
    return -1
};

4.1.png

附:建立固定长度全0数组的方法

以建立数组长度为10,元素的值都为0为例。

1. for循环

var arr = []
for(var i = 0; i < 10; i++){
	arr[i] = 0
}

2. ES6的fill()方法

var arr = new Array(10).fill(0)

3. Uint8Array()方法 表示一个8位无符号整型数组,创建时内容被初始化为0。

var arr = new Uint8Array(10)

4. Array.join()、String.split() ①Array.prototype.join():将一个数组的所有元素连接成一个字符串并返回该字符串。 ②String.prototype.split():使用指定的分隔符字符串将字符串分割成子字符串数组。 注:生成的是"0"组成的数组

var arr = new Array(10+1).join('0').split('')	

解法三:移动元素让下标和值对应

将每个元素移动到与下标对应的地方。

如当i为0时,num[0] = 2,则找到nums[2]交换数据,直到num[0]=0

时间复杂度:O(N)
空间复杂度:O(1)

var findRepeatNumber = function(nums) {
    // 查空
    if(nums.length == 0)    return -1
    
    var temp
    for(var i = 0; i < nums.length; i++){
        while(nums[i] != i){    //当索引值为0,直到找到0结束while
            if(nums[i] == nums[nums[i]]){
                return nums[i]  //与排序好的数据比较,相同则重复
            }
            // 索引与值不相等,交换数据
            temp = nums[nums[i]]
            nums[nums[i]] = nums[i]
            nums[i] = temp
        }
    }

    return -1
};

4.3.png

解法四:将数组排序,判断相邻两个数是否相等

Array.sort():对数组的元素进行排序,并返回数组。
时间复杂度:O(NlogN),快速排序

	var arr = [1,21,65,88,91,15,16,3]
        arr.sort()
        console.log(arr);			// [1,15,16,21,3,65,88,91]
var findRepeatNumber = function(nums) {
    // 查空
    if(nums.length == 0)    return -1
    // 排序
    nums.sort()
    // 比较相邻数值
    for(var i = 1; i < nums.length; i++){
        if(nums[i] == nums[i-1]){
            return nums[i]
        }
    }
    return -1
};

4.4.png