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) 。 数组中只有一个重复的数字,但它可能不止重复出现一次。

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/find-the-duplicate-number 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解:

思路一:

  • 遍历数组,使用Hashset存储遍历过的元素
  • 当遍历当前元素时
    • 如果set中包含,则为重复元素,返回当前元素
    • 如果set中不包含, 则将当前元素加入set中
  • 遍历完这边链表,都没发现重复时,return -1
  • 时间复杂度 : O(N)
  • 空间复杂度 : O(N)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    /**
     *
     *
     * 解法一:
     * 遍历数组,使用set存放遍历过的值
     * 遍历时,如果set中包含, 则返回 当前元素
     * 如果不包含,加入set中
     *
     * 时间复杂度 : O(N)
     * 空间复杂度 : O(N)
     *
     */

    public int findRepeatNumber1(int[] nums) {

        HashSet<Integer> set = new HashSet<>();
        for (int i = 0; i < nums.length; i++) {
            if (set.contains(nums[i])) return nums[i];
            set.add(nums[i]);
        }
        return -1;
    }

思路二:

  • 上述解题中发现,我们完全没有用到此条件:
    • 长度为 n, 且所有数字都在 [1, n]范围内
  • 所以,如果没有重复元素,则所有元素在排序后,都应该 == 下标index + 1
  • 那么,空间复杂度O(1), 时间复杂度 O(N)的解法就来了
    • 遍历数组,当 下标+1 != 当前元素 时,将当前元素交换至正确的位置
    • 交换过程中
      • 如果当前元素 == 正确位置上的元素, 则重复, return 当前元素
      • 如果当前元素 != 正确位置上的元素, 则依次将元素交换至正确的位置
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
 *
 * 解法二:
 * 上述题解发现,我们完全没有用到数组中这个条件:
 * 长度为n, 且所有数字都在 [1, n]范围内
 *
 * 所以,如果没有重复元素, 则所有元素在排序后,都应该与 下标index一致
 *
 * 那么,空间复杂度O(1),时间复杂度O(n)的解法就来了
 *  1,遍历数组, 当 下标 + 1!= 当前元素时,将当前元素交换至正确的位置。
 *  2,交换过程中,如果 当前元素 == 正确位置上的元素, 则重复,return当前元素
 *  3,交换过程中,如果 当前元素 != 正确位置上的元素, 则依次将正确位置上的元素,移动位置
 *
 *
 * */
     // 每个元素跟其下标对比 + 1,若不相同, 则交换元素至正确索引
    //https://www.toutiao.com/i6761686631729594894
    public static int findDuplicate1(int[] nums) {

        for (int i = 0; i < nums.length; i++) {
            // 这里需要注意,一定不要 先取出来 int num = nums[i]
            // 因为 nums[i] 在每一轮 while循环,是变化的。所以每一轮都取
            while (nums[i] != i + 1) {
                if (nums[i] == nums[nums[i] - 1]) return nums[i];
                swap(nums,i,nums[i] - 1);
            }
        }

        return -1;
    }

优化后的效果

<>屏幕快照 2020-06-05 下午12.54.01

u