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

来源:互联网 发布:asp.net erp源码 编辑:程序博客网 时间:2024/06/03 19:23

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

    • 面试题3 数组中重复的数字
    • LeetCode 287 同面试题3中的题目2 不修改数组找出重复数字
    • LeetCode 442 找出数组中所有的重复元素
    • LeetCode 448 找出数组中没有出现的元素


面试题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
原创粉丝点击