leetcode(287):Find the Duplicate Number

1.题目


给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

示例 1:

输入: [1,3,4,2,2]
输出: 2
1
2
示例 2:

输入: [3,1,3,4,2]
输出: 3
1
2
说明:

不能更改原数组(假设数组是只读的)。
只能使用额外的 O(1) 的空间。
时间复杂度小于 O(n2) 。
数组中只有一个重复的数字,但它可能不止重复出现一次。

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.

Example 1:

Input: [1,3,4,2,2]
Output: 2
Example 2:

Input: [3,1,3,4,2]
Output: 3
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.

2.1二分法思路

我们首先想到的解法就是先将数组nums排序,建立pre和cur两个指针,分别指向前面一个元素和当前元素,然后对于排序好的nums从头到尾的遍历,判断nums[pre]==nums[cur],如果成立,返回nums[pre]即可,否则的话继续遍历。

class Solution:
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums.sort()
        for i in range(len(nums)-1):
            if nums[i] == nums[i+1]:
                return nums[i]

但是我们这种做法改变了原有的数组,所以这种做法就被我们排除了。由于是查找问题,我们不难想到通过二分搜索法,但是这里我们要将原来的二分搜索法做一些调整。我们首先计算mid,然后我们统计数组中小于等于mid元素的个数k,如果k<=mid的话,那么说明重复值在[mid+1,n]之间,否则的话重复值在[1,mid]之间。为什么这样子做是合理的呢?实际上这个问题的思想来源于抽屉原理,我们将包含重复元素的所有数放到一个可以容纳所有数的数组中去,如下

class Solution:
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        low, high = 1, len(nums)-1
        while low < high:
            mid = low + (high-low)//2       #防止溢出
            count = sum(num <= mid for num in nums)
            if count <= mid:
                low = mid+1
            else:
                high = mid
        return low

2.2指针法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值