返回介绍

solution / 0200-0299 / 0287.Find the Duplicate Number / README

发布于 2024-06-17 01:04:02 字数 4458 浏览 0 评论 0 收藏 0

287. 寻找重复数

English Version

题目描述

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,返回 这个重复的数

你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。

 

示例 1:

输入:nums = [1,3,4,2,2]
输出:2

示例 2:

输入:nums = [3,1,3,4,2]
输出:3

示例 3 :

输入:nums = [3,3,3,3,3]
输出:3

 

 

提示:

  • 1 <= n <= 105
  • nums.length == n + 1
  • 1 <= nums[i] <= n
  • nums只有一个整数 出现 两次或多次 ,其余整数均只出现 一次

 

进阶:

  • 如何证明 nums 中至少存在一个重复的数字?
  • 你可以设计一个线性级时间复杂度 O(n) 的解决方案吗?

解法

方法一:二分查找

我们可以发现,如果 $[1,..x]$ 中的数字个数大于 $x$,那么重复的数字一定在 $[1,..x]$ 中,否则重复的数字一定在 $[x+1,..n]$ 中。

因此,我们可以二分枚举 $x$,每次判断 $[1,..x]$ 中的数字个数是否大于 $x$,从而确定重复的数字在哪个区间中,进而缩小区间范围,直到找到重复的数字。

时间复杂度 $O(n \times \log n)$,其中 $n$ 是数组 $nums$ 的长度。空间复杂度 $O(1)$。

class Solution:
  def findDuplicate(self, nums: List[int]) -> int:
    def f(x: int) -> bool:
      return sum(v <= x for v in nums) > x

    return bisect_left(range(len(nums)), True, key=f)
class Solution {
  public int findDuplicate(int[] nums) {
    int l = 0, r = nums.length - 1;
    while (l < r) {
      int mid = (l + r) >> 1;
      int cnt = 0;
      for (int v : nums) {
        if (v <= mid) {
          ++cnt;
        }
      }
      if (cnt > mid) {
        r = mid;
      } else {
        l = mid + 1;
      }
    }
    return l;
  }
}
class Solution {
public:
  int findDuplicate(vector<int>& nums) {
    int l = 0, r = nums.size() - 1;
    while (l < r) {
      int mid = (l + r) >> 1;
      int cnt = 0;
      for (int& v : nums) {
        cnt += v <= mid;
      }
      if (cnt > mid) {
        r = mid;
      } else {
        l = mid + 1;
      }
    }
    return l;
  }
};
func findDuplicate(nums []int) int {
  return sort.Search(len(nums), func(x int) bool {
    cnt := 0
    for _, v := range nums {
      if v <= x {
        cnt++
      }
    }
    return cnt > x
  })
}
function findDuplicate(nums: number[]): number {
  let l = 0;
  let r = nums.length - 1;
  while (l < r) {
    const mid = (l + r) >> 1;
    let cnt = 0;
    for (const v of nums) {
      if (v <= mid) {
        ++cnt;
      }
    }
    if (cnt > mid) {
      r = mid;
    } else {
      l = mid + 1;
    }
  }
  return l;
}
impl Solution {
  #[allow(dead_code)]
  pub fn find_duplicate(nums: Vec<i32>) -> i32 {
    let mut left = 0;
    let mut right = nums.len() - 1;

    while left < right {
      let mid = (left + right) >> 1;
      let cnt = nums
        .iter()
        .filter(|x| **x <= (mid as i32))
        .count();
      if cnt > mid {
        right = mid;
      } else {
        left = mid + 1;
      }
    }

    left as i32
  }
}
/**
 * @param {number[]} nums
 * @return {number}
 */
var findDuplicate = function (nums) {
  let l = 0;
  let r = nums.length - 1;
  while (l < r) {
    const mid = (l + r) >> 1;
    let cnt = 0;
    for (const v of nums) {
      if (v <= mid) {
        ++cnt;
      }
    }
    if (cnt > mid) {
      r = mid;
    } else {
      l = mid + 1;
    }
  }
  return l;
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文