剑指 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; } }