剑指 Offer 03. 数组中重复的数字

题目:

思路:

【1】使用set的额外辅助空间记录,已经出现的数字,遇到重复的直接输出即可。

【2】不使用额外空间的话可以考虑先排序,再遍历,虽说也是一种解决的办法,但是一边在面试中别人不大愿意给你使用排序

【3】利用本身的限制采用hsah的方式映射到原本的数组上

代码展示:

hash的方式处理:

//时间0 ms击败100%
//内存49 MB击败60.22%
//时间:O(n)
//空间:O(1)
class Solution {
    public int findRepeatNumber(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            int num = nums[i];
            if (num == i) continue;
            if (nums[num] == num) return num;

            // 循环置位:
            // 将当前i位置上的数放置到它应该去的位置,置换出来的数,换回到i位置,盯住i位置不动,继续循环置位。
            // 期间如果发现应该去的位置上躺着的已经是正确的数字了,则发现重复,return
            while (nums[i] != i) { // 在一次置位循环中,始终盯住i位置不动,以i位置为发货地,不断向外发送数字。
                // i位置上数应该发往nums[i]位置,置换出num这个数:
                num = nums[nums[i]];
                if (num == nums[i]) return num; // 发现重复
                nums[nums[i]] = nums[i];
                nums[i] = num;
            }
        }
        return -1;
    }
}

 

使用set额外空间:

//时间4 ms击败56.89%
//内存51.3 MB击败5.75%
//时间复杂度:O(n)。遍历数组一遍。使用哈希集合(HashSet),添加元素的时间复杂度为 O(1),故总的时间复杂度是 O(n)。
//空间复杂度:O(n)。不重复的每个元素都可能存入集合,因此占用 O(n) 额外空间。
class Solution {
    public int findRepeatNumber(int[] nums) {
        Set<Integer> set = new HashSet<Integer>();
        int res = -1;
        for (int num : nums) {
            if (!set.add(num)) {
                res = num;
                break;
            }
        }
        return res;
    }
}

不使用额外空间,先将数组排好序,再通过遍历进行比对拿出重复的数字:

//时间4 ms击败56.89%
//内存49.1 MB击败56.37%
//时间复杂度O(nlogn),排序中最优的其实也就是O(nlogn),而遍历数组为O(n),实际上为O(nlogn+n)=O(nlogn)
//空间复杂度O(1)
class Solution {
    public int findRepeatNumber(int[] nums) {
        Arrays.sort(nums);
        int p = 0;
        while (p < nums.length) {
            if (nums[p] == nums[p + 1]) {
                return nums[p];
            }
            p++;
        }
        return 0;
    }
}

 

posted @ 2023-02-10 11:42  忧愁的chafry  阅读(11)  评论(0编辑  收藏  举报