645. 错误的集合
思路:
我们定义一个数组cnt,记录每个数出现的次数。然后我们遍历数组,从1开始,如果cnt[i] == 0 那就说明这个是错误的数,如果 cnt[i] == 2,那就说明是重复的数。
代码:
class Solution {public int[] findErrorNums(int[] nums) {int n = nums.length;int[] cnts = new int[n + 1];for(int i : nums) cnts[i] ++;int[] ans = new int[2];for(int i = 1;i <= n; i++){if(cnts[i] == 0) ans[1] = i;if(cnts[i] == 2) ans[0] = i;}return ans;}
}
697. 数组的度
思路:
题目说的度,是说元素出现的次数的最大值。但是又说最短连续子数组,那么我们就要知道数组的长度。我们定义一个Map,key 是数组里的数,value是一个数组,value[0]是指出现的次数,value[1]是指出现的第一次坐标,求数组的长度就用最后一次坐标减去第一次出现的坐标。
因为题目说nums.length 从1 开始,所以我们定义int[] Max = {1, 1}。然后遍历数组,如果MAP里没有记录,就存下对应的参数,如果出现过,就把value[0] + 1,然后和max数组对比。
- 如果说value[0] > max[0],那就把value的信息更新到max
- 如果说value[0] == max[0],那么就要看数组的长度
代码:
class Solution {public int findShortestSubArray(int[] nums) {// 1、我们需要知道某个数的出现次数// 2、要求最短连续数组,所以我们需要知道数组的长度// 3、需要记录的:次数、长度和数字本身// 4、长度可以由下表计算,保存初始下标// key :数, value[0] :出现的次数, value[1] :第一次下表Map<Integer, Integer[]> map = new HashMap<>();int[] max = {1, 1};for(int i = 0; i < nums.length; i++){if(!map.containsKey(nums[i])){map.put(nums[i],new Integer[] {1, i});}else{Integer[] cur = map.get(nums[i]);//出现次数+1cur[0] += 1;//如果出现的次数比max大,或者次数相同,但是数组长度更小,就更新maxif(cur[0] > max[0] || cur[0] == max[0] && i - cur[1] + 1 < max[1]){max = new int[] {cur[0], i - cur[1] + 1};}}}return max[1];}
}
448. 找到所有数组中消失的数字
思路:
我们先遍历nums,如果 nums[i] == i + 1,那就说明该位置就是对应的数字。
然后遍历nums,如果nums[nums[i] - 1] == nums[i] ,那就说明他不是消失的数字。
如果我们遍历到有重复的数字,比如上面的3,而且nums[2] == 3,那我们就往后遍历。
遍历之后的结果:
nums:[1,2,3,4,3,2,7,8](注意题目中的2, 3)
然后我们再遍历一次nums,如果nums[i] != i + 1,那就说明他们是消失的数字
代码:
class Solution {public List<Integer> findDisappearedNumbers(int[] nums) {List<Integer> res = new ArrayList<>();int i = 0;while(i < nums.length){if(nums[i] == i + 1){i ++;continue;}int index = nums[i] - 1;if(nums[index] == nums[i]){i++;continue;}int tmp = nums[i];nums[i] = nums[index];nums[index] = tmp;}for(int j = 0; j < nums.length; j++){if(nums[j] != j + 1){res.add(j + 1);}}return res;}
}
442. 数组中重复的数据
思路:
我们遍历nums,遍历的每一个元素都变成|x|,然后把nums[|x| - 1]的数乘上-1。
再遍历一遍原数组,如果当前遍历的元素是负的,就说明他是重复的,那就说明|x|是重复的。
代码:
class Solution {public List<Integer> findDuplicates(int[] nums) {int n = nums.length;List<Integer> ans = new ArrayList<>();for(int i = 0; i < n; i++){int x = Math.abs(nums[i]);if(nums[x - 1] > 0){nums[x - 1] = -nums[x - 1];}else{ans.add(x);}}return ans;}
}
41. 缺失的第一个正数
思路:
方法1:
对于一个长度为 N 的数组,其中没有出现的最小正整数只能在 [1,N+1] 中。如果再[1,N]中没有出现,那就说明是第N+1。
我们遍历数组,如果当前的数小于或者等于0,那就让他变成N+1,定义int x = nums[i],让nums[x - 1]乘上-1。
然后我们遍历数组,如果在[1,N]中有没有正数,那就说明是N+1, 如果有那就是第一个正数的坐标+1。
代码:
class Solution {public int firstMissingPositive(int[] nums) {int n = nums.length;for(int i = 0; i < n; i++){if(nums[i] <= 0) nums[i] = n + 1;}for(int i = 0; i < n; i++){int x = Math.abs(nums[i]);if(x <= n){nums[x - 1] = -Math.abs(nums[x - 1]);}}for(int i = 0; i < n; i++){if(nums[i] > 0){return i + 1;}}return n + 1;}}
方式2:
通过置换,把对应的数字放到对应的坐标,如果当前的数nums[i] != i + 1,那就说明i+1是缺失的第一个。
class Solution {public int firstMissingPositive(int[] nums) {int n = nums.length;for(int i = 0; i < n; i++){while(nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]){int tmp = nums[nums[i] - 1];nums[nums[i] - 1] = nums[i];nums[i] = tmp;}}for(int i = 0; i < n; i++){if(nums[i] != i + 1){return i + 1;}}return n + 1;}}