找出数组中的重复数字--解题总结

题目

数组长度为n + 1,数组中的数大小均在1~n的范围内,则数组中至少会存在一个重复数字。要求找出其中一个重复数组。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出重复的数字是2或者3,输出其中一个即可。

思路1:可直接将数组排序,遍历数组,找到其中一个重复数字即可。时间复杂度是O(nlogn)。

def findDuplicates(nums):
    if not nums: return None
    nums = sorted(nums)
    for i in range(len(nums) - 1):
        if nums[i] == nums[i + 1]: 
            return nums[i]

思路2:引入集合,集合中是数组中所有出现过的数字,遍历集合,若集合中的该元素出现在数组中,则在数组中移除该元素(重复的元素只会移除第一个该元素)。则数组中剩下的数均为重复的数。时间复杂度是O(n^2),空间复杂度是O(n)。

def findDuplicates(nums):
    if not nums: return None
    numset = set(num)
    for x in numset:
        if x in nums: nums.remove(x)
    if not nums: return None
    return nums[0]

思路3:开辟一个长为n的数组count,用于标记数字出现的次数,若count[n]>1,说明出现次数大于1.时间复杂度为O(n),空间复杂度也为O(n)。

def findDuplicates(nums):
    if not nums: return None
    count = [0] * (len(nums))
    for x in nums:
        count[x] += 1
    for x in count:
        if x > 1: return x
    return None

思路4:可采用二分的方式,遍历数组,统计小于n/2的值的个数,若个数大于n/2,说明重复的数出现在1~n/2里,否则出现在n/2~n里。以此继续二分下去,直至找到一个重复的数。时间复杂度O(nlogn),空间复杂度O(1)。

def findDuplicates(nums):
    if not nums: return None
    left, right = 1, len(nums) - 1
    while left < right:
        mid = left + (right - left) // 2
        for x in nums:
            if x <= mid: count += 1
        if mid < count: right = mid
        else: left = mid + 1
    return left    
        

 思路5:重排数组的方式,使得nums[i] = i,遍历数组,如果nums[i] == i说明nums[i]的位置正确,继续遍历,否则,把nums[i]放到正确的位置上,若该位置上的值已有nums[i]了,说明nums[i]为重复元素。时间复杂度O(n),空间复杂度O(1)。

def findduplicates(nums):
    if not nums: return None
    for i in range(len(nums)):
        while nums[i] != i:
            if nums[nums[i]] == nums[i]: returnn nums[i]
            else: nums[nums[i]], nums[i] = nums[i], nums[nums[i]]
    return None

题目另一版:长度为n+1的数组,每个数字的范围在0~n,数组中可能会存在重复数字,若存在,找出其中一个重复数字。

数字范围在0~n,此时数组中可能不存在重复数字,因此可以采用思路5数组重排的方式来解决。

def findduplicates(nums):
    if not nums: return None
    for i in range(len(nums)):
        while nums[i] != i:
            if nums[nums[i]] == nums[i]: returnn nums[i]
            else: nums[nums[i]], nums[i] = nums[i], nums[nums[i]]
    return None
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值