442. 数组中重复的数据

150 阅读1分钟

题目描述

image.png

思路:原地hash

  • 和287不同的是,这个题有多个重复元素,需要全部找出并返回
  • 需要避免重复添加,去重不能用Set,因为要求O(1)空间。
    • 遇到重复后,把其中一个置为相反数,再遍历的时候不遍历负数即可。
class Solution {
    public List<Integer> findDuplicates(int[] nums) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < nums.length; i++) {
            while (nums[i] > 0 && nums[i] != i + 1) {//nums[i] > 0表示如果遇到了负数,跳过,因为这个负数是重复的数字。
                if (nums[i] == nums[nums[i] - 1]) {
                    nums[nums[i] - 1] *= -1;//遇到了重复的数字,把其中一个置为相反数,这样就避免了重复遍历
                    list.add(nums[i]);//把重复数字添加到list中
                } else {
                    swap(nums, i, nums[i] - 1);//正常归位
                }
            }
        }
        return list;

    }

    public void swap(int[] nums, int m, int n) {
        int tmp = nums[m];
        nums[m] = nums[n];
        nums[n] = tmp;
    }
}