2021-06-08 数组中重复的数字

本文探讨了两种在数组中找出重复数字的方法。方法一是使用哈希表,通过遍历数组并检查元素是否已存在于表中来找到重复项。方法二是通过下标定位法,不断比较数组元素与其下标,交换不正确位置的元素,最终找到重复数字。此外,还介绍了避免修改数组的解决方案,通过不断划分数组区间来定位重复数字,类似于二分查找。
摘要由CSDN通过智能技术生成

问题一:找出数组中重复的数字

描述

在一个长度为 n 的数组里的所有数字都在 0 到 n-1 的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为 7 的数组 [2,3,1,0,2,5,3] ,那么对应的输出是 2 或者 3 。存在不合法的输入的话输出 -1 。

实例

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

返回值:2

说明:2 或 3 都是对的

方法1:利用字典(哈希表)。从头到尾扫描数组的每个数字,每扫描到一个数字时,都可以用 O(1) 的时间判断字典中是否已经包含了该数字。如果没有,就把它加入到字典中;否则,就找到了一个重复数字。时间复杂度为 O(n) ,空间复杂度为 O(n) 。

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param numbers int整型一维数组 
# @return int整型
#
class Solution:
    def duplicate(self , numbers ):
        # write code here
        dict1 = {}
        if not numbers:
            return -1
        for i in numbers:
            if dict1.get(i) == i:
                return i
            else:
                dict1[i] = i

方法2:下标定位法。由于数组中的数字都在 0 到 n-1 的范围内,如果这个数组中没有重复的数字,那么当数组排序后数字 i 将出现在下标为 i 的位置。首先从头到尾扫描这个数组中的每个数字,当扫描到下标为 i 的数字时,首先比较这个数字即 numbers[i] 与 i 是否相等,如果是,则接着扫描下一个数字;如果不是,再拿 numbers[i] 和 numbers[numbers[i]] 进行比较,若相等,则找到了一个重复的数字(该数字在下标为 i 和 numbers[i] 的位置都出现了);否则,就把第 i 个数字和第 numbers[i] 个数字交换,把 numbers[i] 放在属于他的位置上(即numbers[numbers[i]])。时间复杂度为 O(n) ,空间复杂度为 O(1) 。

class Solution:
    def duplicate(self , numbers ):
        # write code here
        if not numbers:
            return -1
        i = 0
        while i < len(numbers):
            if i == numbers[i]:
                i += 1
            else:
                if numbers[i] == numbers[numbers[i]]:
                    return numbers[i]
                else:
                    temp = numbers[i]
                    numbers[i] = numbers[temp]
                    numbers[temp] = temp

问题二:不修改数组找出重复的数字

描述

在一个长度为 n+1 的数组里的所有数字都在 1 到 n 的范围内,所以数组中至少有一个数字时重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。 例如,如果输入长度为 8 的数组 [2,3,5,4,3,2,6,7] ,那么对应的输出是 2 或者 3 。

实例

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

返回值:2

说明:2 或 3 都是对的

方法1:利用字典,与问题一一样。

方法2:为了避免 O(n) 的辅助空间。数字在 1 到 n 的范围内只有 n 个数字,但数组包含了 n+1 个数字,因此肯定有重复的数字。将数组按中位数划分为两组进行个数统计,小于或小于等于中位数的数字统计为一组,大于中位数的统计为一组,两组中,若有数字个数大于中位数,则说明该组中存在重复的数字,然后将该组视为新的数组,重新计算中位数并统计,直至找到一个重复的数字。类似于二分查找算法。时间复杂度为 O(nlogn) ,空间复杂度为 O(1)。

class Solution:
    def duplicate(self, numbers):
        length = len(numbers)
        if not numbers and length < 2:
            return -1
        left = 1
        right = length - 1
        while left < right:
            mid = (left+right) //2
            count = 0
            for i in numbers:
                if i <= mid:
                    count += 1
            if count > mid-left+1:    
                right = mid
            else:
                left = mid + 1
        return left

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值