Leetcode面试题3-面试题数组中重复的数字

mhxin

题目描述

找出数组中重复的数字。

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

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

该题目的难度级别为Easy。

思路1

最直观的方式可能就是排序+遍历的方式, 根据这个思路可以很容易的写出代码

def findRepeatNumber(nums: List[int]) -> int:
    if nums == None or len(nums) < 2:
        return 
    nums.sort()
    
    for i in range(1, len(nums)):
        # 只要找到就可以返回
        if nums[i] == nums[i-1]:
            return nums[i]

排序的时间复杂度为$O(nlogn)$,遍历的时间复杂度为$O(n)$,即算法的时间复杂度为$O(nlogn)$,空间复杂度为$O(1)$。

思路2

使用字典作为计数器,只要某个元素的已经存在于字典中就可以直接返回。按照这个思路可以写出如下代码

def findRepeatNumber(nums: List[int]) -> int:
    if nums == None or len(nums) < 2:
        return 
    dicts = {}
    
    for i in nums:
        # 只要找到就可以返回
        if i in dicts:
            return i
        dicts[i] = 1

相比于第一种算法,该算法以空间换时间。因为只有一次循环,时间复杂度为$O(n)$,空间复杂度为$O(n)$。

优化算法

上面2中思路都是比较容易想到的,那么有没有不使用额外空间,并且时间复杂度为$O(n)$的算法呢。

每次换一种思路时,我们需要重新去思考题目,而不是在已有的思路上纠结。
如果数组nums没有重复,那么nums的索引所构成的集合和nums中的元素构成的集合是相等的(从集合的角度上来看,不考虑顺序)。即对于任意一个索引,都有唯一的元素与它相等,相对应

但如果nums包含重复元素,那么对于部分索引,将会对应多个相同元素,比如nums = [2, 3, 1, 0, 2, 5, 3]

索引为2的对应数组中的2个2,索引为3的对应数组中的2个3。我们可以依次的将每个元素放到它对应的索引位置,而如果该元素和它对应索引位置的元素相等,说明该元素重复。

image.png
按照这个思路, 可以写出如下的代码

def findRepeatNumber(nums: List[int]) -> int:
    if nums == None or len(nums) < 2:
        return 
    for i in range(len(nums)):
        # 索引和对应元素不一致,调整元素位置,直至索引与元素匹配或者找到重复元素
        while i != nums[i]:
        
            # 如果当前元素对应的索引位置的值与当前元素相等
            if nums[i] == nums[nums[i]]:
                return nums[i]
                
            # 交换nums[i]和i位置的值
            temp = nums[i]
            nums[i], nums[temp] = nums[temp], nums[i]

上述代码虽然包含了2次循环,但每个位置都可以在有限次内结束。因此总的时间复杂度为$O(n)$,并不需要使用额外的空间,空间复杂度为$O(1)$。

总结

经历了惨痛的教训,终于决定要开始认真刷题了。之前一直是处于间歇期放弃的状态,导致现在基本上是从零开始了。
我会尽可能把自己做过的题目进行一些总结,由于本人对于数据结构和算法的学习有限,大佬勿喷。

阅读 1.1k
82 声望
12 粉丝
0 条评论
82 声望
12 粉丝
文章目录
宣传栏