《剑指Offer(第2版)》-03-数组中重复的数字

刚开始刷题,一定要先自己想,然后再看别人的题解思路,然后慢慢优化

方法一:哈希表(最自然,但是要额外空间)

最容易想到用哈希表判重,这种方法是最自然的。

特别地,在数组的长度不超过32的时候,使用位运算的技巧可以实现 O(1)空间复杂度判重,但是这道题不是回溯算法的问题,题目给出的测试用例的长度肯定不止32位,因此,不建议使用位运算的技巧。

分析:这种方法不修改原始数组,但是使用了O(N)空间,使用空间换时间,是最正常的思路,时间复杂度是 O(N)。

方法二:排序(也比较容易想到,但是要排序,复杂度高)

排序以后,再遍历一遍就知道哪个重复了。

分析:这个方法其实比较容易想到,但是时间复杂度是O(NlogN),同时也修改了原始数组。

方法三:把数组视为哈希表(有一类问题是这么做的,但是会修改数组)

由于数组元素的值都在指定的范围内,这个范围恰恰好与数组的下标可以一一对应;
因此看到数值,就可以知道它应该放在什么位置,这里数字nums[i] 应该放在下标为 i 的位置上,这就像是我们人为编写了哈希函数,这个哈希函数的规则还特别简单。

分析:这个思路利用到了数组的元素值的范围恰好和数组的长度是一样的,因此数组本身可以当做哈希表来用。遍历一遍就可以找到重复值,但是修改了原始数组。

class Solution {
    public int findRepeatNumber(int[] nums) {
        int len = nums.length;
        for(int i=0; i<len; i++){
			//不断循环,直到数组的位置有正确的值
            while(nums[i] != i){
            //替换之前先查看该位置上是否有属于该位置的数,如果有则重复值就是这个数,直接返回即可
                if(nums[i] == nums[nums[i]]){
                    return nums[i];
                }
                swap(nums, i, nums[i]);
            }
        }
        return -1;  //表示没有重复值
    }
    
    //用于交换数组中的两个值
    public void swap(int nums[], int index1, int index2){
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
}

原文链接:https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/solution/tong-de-si-xiang-by-liweiwei1419/

发布了39 篇原创文章 · 获赞 15 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/sinat_35667067/article/details/104609734
今日推荐