Leetcode力扣秋招刷题路-剑指 Offer 03

从0开始的秋招刷题路,记录下所刷每道题的题解,帮助自己回顾总结

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

题目描述: 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

示例 1:

输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3

解法一:排序,比较相邻数字时间复杂度O(NlogN),空间复杂度O(1)。

class Solution {
    public int findRepeatNumber(int[] nums) {
        Arrays.sort(nums);
        for(int i = 0; i < nums.length - 1; ++i){
            if(nums[i] == nums[i + 1])
                return nums[i];
        }
        return -1;
    }
}

解法二:哈希。时间复杂度O(N),空间复杂度O(N)。

class Solution {
    public int findRepeatNumber(int[] nums) {
        int[] ans = new int[100001];
        for(int num: nums){
            if(ans[num] == 1)
                return num;
            else
                ans[num] = 1;
        }
        return -1;
    }
}

解法三:注意到题干中说明了数组长度为n并且数组中的数字范围都在0到n-1中,因此整个数组中若无重复数字,则下标为i的数字一定等于i;如果有重复的数字,则在某些位置上的数字定会重复。根据此规律,我们可以遍历整个数组,如果下标为i的数字等于i,那么继续比较下一个数字;如果下标为i的数字不等于i,则互换下标为nums[i]和i的数字,再继续比较。时间复杂度O(N),空间复杂度O(1)。

class Solution {
    public int findRepeatNumber(int[] nums) {
        int temp;
        int i = 0;
        while(i < nums.length){
            if(nums[i] == i){
                i++;
                continue;
            }
            else{
                if(nums[i] == nums[nums[i]])
                    return nums[i];
                else{
                  // 交换顺序不能错
                    temp = nums[nums[i]];
                    nums[nums[i]] = nums[i];
                    nums[i] = temp;
                }
            }
        }
        return -1;
    }
}


  • 解法四:空间复杂度O(1),且不能修改原数组
    • 将数组0~n-1一分为2,分别统计这两个区间内的数字个数,如果哪一边多了再一分为二查找
    • 二分的意义在于比按顺序计算个数少了遍历次数

你可能感兴趣的:(Leetcode,leetcode,算法,数据结构)