《剑指Offer》面试题3及LeetCode中相似题目

本文详述《剑指Offer》面试题3关于找数组中重复数字的解法,并结合LeetCode的287、442和448题,探讨不同解题策略。解法涵盖不修改原数组的O(n)时间复杂度解决方案,以及利用额外空间优化的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇博文总结了《剑指Offer》面试题3:数组中重复数字的几种解法,以及LeetCode中与之相似的题目,旨在举一反三能够很好地解决这一类问题。


面试题3: 数组中重复的数字

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

解法一: 创建一个长度为n的数组dup,记录每个数字出现的次数。时间复杂度为O(n),需要O(n)的额外空间。

def duplicate(self, numbers, duplication):
        # write code here
        n = len(numbers)
        dup = [0] * n
        for i in numbers:
            dup[i] += 1
        for x in range(n):
            if dup[x] > 1:
                duplication[0] = x
                return True
        return False

解法二:

def duplicate(self, numbers, duplication):
        # write code here
        i = 0
        while i < len(numbers):
            if numbers[i] != i:
                if numbers[numbers[i]] == numbers[i]:
                    duplication[0] = numbers[i]
                    return True
                else:
                    tmp = numbers[numbers[i]]
                    numbers[numbers[i]] = numbers[i]
                    numbers[i] = tmp
            i += 1
        return False

LeetCode 287 (同面试题3中的题目2): 不修改数组找出重复数字

Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.
Note:

  • You must not modify the array (assume the array is read only).
  • You must use only constant, O(1) extra space.
  • Your runtime complexity should be less than O(n2)
  • There is only one duplicate number in the array, but it could be repeated more than once
def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        lo = 1
        hi = len(nums)-1
        while lo < hi:
            count = 0
            mid = lo + (hi - lo)//2
            for i in nums:
                if i >= lo and i <= mid:
                    count += 1
            if count > mid - lo + 1:
                hi = mid
            else:
                lo = mid + 1
        return lo

LeetCode 442: 找出数组中所有的重复元素

Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements that appear twice in this array.
Could you do it without extra space and in O(n) runtime?

解法一: 与面试题3中的解法二类似,但res中可能保存了多次重复的元素,因此返回时利用了集合的属性。

def findDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        res = []
        i = 0
        while i < len(nums):
            if nums[i] == i + 1:
                i += 1
            else:
                if nums[i] == nums[nums[i]-1]:
                    res.append(nums[i])
                    i += 1
                else:
                    tmp = nums[nums[i]-1]
                    nums[nums[i]-1] = nums[i]
                    nums[i] = tmp
        return list(set(res))

解法二: 当扫描至数组中的元素i,若i为第一次出现,则将下标(i-1)处的元素变为负,即nums[i-1] = -nums[i-1],所以当扫描至i,而下标(i-1)处的元素为负时,i即为重复元素。

def findDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        res = []
        for i in nums:
            i = abs(i)
            if nums[i-1] < 0:
                res.append(i)
            else:
                nums[i-1] = -nums[i-1]
        return res

LeetCode 448: 找出数组中没有出现的元素

Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements of [1, n] inclusive that do not appear in this array.
Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.

解答: 同上题中的解法二类似,最后统计大于0的元素的下标。

def findDisappearedNumbers(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        res = []
        for i in nums:
            index = abs(i)-1
            if nums[index] > 0:
                nums[index] = -nums[index]
        for i in range(len(nums)):
            if nums[i] > 0:
                res.append(i+1)
        return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值