第十五周_A- 数组中的重复数字

63 阅读2分钟

力扣

这是 LeetCode 上面的剑指 Offer 的简单程度的题目。当我看见评论区的第一个评论,我就觉得不简单了。

于是我轻松实现前面两种。最后一个 原地排序 的参看了答案。

题目

在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。

数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

  • 示例 1:

  • 输入:

  • [2, 3, 1, 0, 2, 5, 3]

  • 输出:2 或 3

实现

暴力法

不知道什么时候起,我习惯做算法的时候,上来先整个暴力解法,几乎都能解开。特别是这种循环的。

时间复杂度:O(n的2次方)

public static void baoliDeal(int[] nums) {
    boolean is = false; //这里多加一个判断可以少循环,匹配出一个就直接返回/输出,不再执行后续的代码
    for (int i = 0; i < nums.length - 1; i++) {
        for (int j = i + 1; j < nums.length; j++) {
            if (nums[i] == nums[j]) {
                is = true;
                System.out.println("重复的数字是:" + nums[i]);
                break;
            }
        }
        if (is) {
            break;
        }
    }
    if (!is) {
        System.out.println("没有重复的数据");
    }
}

Map 法

利用 Java HashMap 只需要遍历一次即可解决

时间复杂度:O(n),因为 map 的操作是 O(1),所以只有循环费时。空间复杂度:O(n)【最坏的情况是没有匹配的,所有数据会放到 map 中】

public static void mapDeal(int[] nums) {
    Map map = new HashMap();
    boolean is = false;
    for (int i = 0; i < nums.length; i++) {
        if (map.containsKey(nums[i])) {
            System.out.println("重复的数字是:" + nums[i]);
            is = true;
            break;
        }
        map.put(nums[i], i);
    }
    if (!is) {
        System.out.println("没有重复的数据");
    }
}

原地解法

这是我在看评论区的时候,第一句话就是:这道题不止简单程度,更重要的是考察你的沟通能力,即是说:在做之前就要和面试官沟通,限定条件,比如时间/空间复杂度。

时间复杂度:O(n) ;空间复杂度:O(1)

需要充分利用题干的信息:一个索引与值是一对多的关系

 public static void yuandiDeal(int[] nums) {
        // {3, 5, 7, 8, 9, 0, 4, 3, 2, 1}
        int i = 0;//设置最开始的索引位置
        while (i < nums.length) {
            if (nums[i] == i) { //索引位置下标和值相等,跳过
                i++;
                continue;
            }
            if(nums[i]==nums[nums[i]]){   //表明有重复的元素
                System.out.println(nums[i]);
                break;
            }
            int tmp=nums[i];
            nums[i]=nums[tmp];
            nums[tmp]=tmp;
        }
    }