剑指offer面试题3:数组中重复的数字 python解

数组中重复的数字

题目一描述

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

解题思路

思路一

排序

  • 给定的数组是乱序的,我们首先对数组排序,然后遍历数组对比一下就可以找到重复的那个数字了。
  • 时间复杂度O(nlogn)

python实现代码

class Solution:
    # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
    # 函数返回True/False
    def duplicate(self, numbers, duplication):
        # write code here
        if numbers is None or len(numbers) == 0:
            return False
        for i in numbers:
            if i < 0 or i >= len(numbers):
                return False
        numbers.sort()
        for i in range(len(numbers)-1):
            if numbers[i+1] == numbers[i]:
                duplication[0] = numbers[i]
                return True
        return False

思路二

哈希表

  • 上述算法在时间上还可以进行优化,空间换时间。我们另外采用一个哈希表来保存数字和其出现的次数。
  • 时间复杂度O(n),空间复杂度o(n)

python实现代码

class Solution:
    # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
    # 函数返回True/False
    def duplicate(self, numbers, duplication):
        # write code here
        if numbers is None or len(numbers) == 0:
            return False
        for i in numbers:
            if i < 0 or i >= len(numbers):
                return False
        lookup = {}
        for num in numbers:
            if num in lookup:
                duplication[0] = num
                return True
            lookup[num] = 1
        return False

思路三

哈希表

  • 继续优化,能不能找到不需要额外空间的算法?
  • 我们注意到,如果数组中的元素没有重复的,那么排序之后数字i会出现在数组下标为i的位置。现在我们有重复的数组,所以有些位置可能存在多个数字,有一些位置可能没有数字。
  • 首先从头至尾扫描数组,当扫描到位置i时,比较这个数字(m)是不是等于i,如果是,则接着扫描下一位;如果不是,则再拿它和第m个数字进行比较,如果相等,就找到了重复的数字;如果不相等,就交换两个数字,把m放到属于它的位置。接下来重复这个过程直到发现第一个重复的数字
  • 时间复杂度O(n),空间复杂度o(1)

python实现代码

class Solution:
    # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
    # 函数返回True/False
    def duplicate(self, numbers, duplication):
        # write code here
        if numbers is None or len(numbers) == 0:
            return False
        for i in numbers:
            if i < 0 or i >= len(numbers):
                return False
        for i in range(len(numbers)):
            while numbers[i] != i:
                if numbers[i] == numbers[numbers[i]]:
                    duplication[0] = numbers[i]
                    return True
                # swap
                tmp = numbers[numbers[i]]
                numbers[numbers[i]] = numbers[i]
                numbers[i] = tmp
        return False

题目二描述

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

解题思路

思路一

二分查找

  • n+1长度的数组中有1n的数,所以至少有一个数是重复的。要找出那个数字,我们可以按照二分查找的思路,将1n分成1m和m+1n两部分。如果1~m的数字的数目超过m,那么这一半区间一定包含了重复数字;反之则在另外一半。
  • 如果输入长度为n的数组,函数countNum将被调用Logn次,每次需要O(n)时间,因此总的时间复杂度O(nlogn),空间复杂度O(1)。

python实现代码

class Solution:
    # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
    # 函数返回True/False
    def duplicate(self, numbers):
        # write code here
        if numbers is None or len(numbers) == 0:
            return False
        length = len(numbers)
        l, r = 0, length-1
        while l <= r:
            mid = (l +r) // 2
            count = countNum(numbers, length, l, mid)
            if l == r:
                if counr > 1:
                    return True
                else:
                    break
            if count > mid - l + 1:
                r = mid
            else:
                l = mid + 1
        return False
        
    def countNum(numbers, length, l, r):
        if numbers is None:
            return 0
        count = 0
        for i in range(length):
            if l <= numbers[i] <= r:
                count += 1
        return count

猜你喜欢

转载自blog.csdn.net/Kaiyuan_sjtu/article/details/87867267