287、寻找重复数

  1. 287、寻找重复数
    1. 示例 1:
    2. 示例 2:
  2. 题解
    1. 暴力枚举
    2. 二分查找
    3. 二进制
    4. 快慢指针

287、寻找重复数

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

示例 1:

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

示例 2:

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

说明:

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

题解

暴力枚举

class Solution {
    public int findDuplicate(int[] nums) {
        int res = 0;
        for (int i = 0;i < nums.length;i++) {
            for (int j = i+1;j < nums.length;j++) {
                if (nums[i] == nums[j] ){
                    res = nums[i];
                    break;
                }
            }
            if (res != 0) {
                break;
            }
        }
        return res;
    }
}

二分查找

cnt[i] 表示小于等于i的元素个数, 根据题意,cnt[i]一定是一个随着i单调递增的序列.
二分规则:对于每一个mid,统计小于等于mid的元素数量cnt:

  • cnt <= mid : 在有半部分
  • cnt > mid : 在左半部分
class Solution {
    public int findDuplicate(int[] nums) {
        int ans = 0;
        int l = 1, r = nums.length - 1;
        while (l <= r) {
            int mid = (l+r)>>1;
            int cnt = 0;
            // 统计目标小于等于mid的数量
            for (int i = 0;i < nums.length;i++) {
                if (nums[i] <= mid) {
                    cnt++;
                }
            }
            if (cnt <= mid) {
                l = mid+1;
            } else {
                r = mid-1;
                ans = mid;
            }
        }
        return ans;
    }
}

二进制

统计每一个数字的二进制,第i位的为1的个数。

class Solution {
    public int findDuplicate(int[] nums) {
        int n = nums.length, ans = 0;
        int bit_max = 31;
        // 求出n-1的二进制有多少位
        while (((n - 1) >> bit_max) == 0) {
            bit_max -= 1;
        }
        for(int bit = 0; bit <= bit_max; ++bit) {
            // 统计第bit的位的个数
            int x = 0,y = 0;
            for (int i = 0;i < n;++i) {
                // 数组中的信息
                if ((nums[i] ^ (1 << bit>>)) ! = 0) {
                    x += 1;
                }
                // 1~(n - 1) 的统计
                if (i > 1 && ((i & (1 << bit)) != 0) {
                    y += 1;
                }
            }
            // 还原二进制的每一位
            if (x > y) {
                ans |= 1 << bit;
            }
        }
        return ans;
    }
}

快慢指针

Floyd判圈法。

长度为n的质保函1~n-1的数组,一定存在环!!!!!

https://leetcode-cn.com/problems/find-the-duplicate-number/solution/xun-zhao-zhong-fu-shu-by-leetcode-solution/

class Solution {
    public int findDuplicate(int[] nums) {
        int slow = 0,fast = 0;
        // 第一次相遇
        do {
            slow = nums[slow];
            fast = nums[nums[fast]];
        } while(slow != fast);
        // 慢指针从头开始
        slow = 0;
        while (slow != fast) {
            slow = nums[slow];
            fast = nums[fast];
        }
        return slow;
    }
}

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 1056615746@qq.com

💰

Title:287、寻找重复数

Count:647

Author:攀登

Created At:2020-07-26, 00:19:44

Updated At:2024-06-15, 15:52:32

Url:http://jiafeimao-gjf.github.io/2020/07/26/287%E3%80%81%E5%AF%BB%E6%89%BE%E9%87%8D%E5%A4%8D%E6%95%B0/

Copyright: 'Attribution-non-commercial-shared in the same way 4.0' Reprint please keep the original link and author.

×

Help us with donation