这是 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;
}
}