3.力扣-数组-统计数组中的元素1
错误的集合(LeetCode645)
- 题目概述:集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。
给定一个数组 nums 代表了集合 S 发生错误后的结果。
请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。 - 题目示例:
- 方法一:排序
1.寻找重复的数字:如果相邻的两个元素相等,则该元素为重复的数字
2.寻找丢失的数字:
·如果丢失的数字大于 1 且小于 n,则一定存在相邻的两个元素的差等于
3.这两个元素之间的值即为丢失的数字;
·如果丢失的数字是 1或 n,则需要另外判断。
java代码
class Solution {
public int[] findErrorNums(int[] nums) {
int[] arr = new int[2];
int n = nums.length;
Arrays.sort(nums);
int prev = 0;//设为0即可判断第一位
for (int i = 0; i < n; i++) {
int curr = nums[i];
if (curr == prev) {//寻找重复的一位
arr[0] = prev;
} else if (curr - prev > 1) {//寻找丢失的一位(不包括最后一位)
arr[1] = prev + 1;
}
prev = curr;
}
//判断最后一位
if (nums[n - 1] != n) {
arr[1] = n;
}
return arr;
}
}
JS代码
/**
* @param {number[]} nums
* @return {number[]}
*/
var findErrorNums = function(nums) {
let n=nums.length
nums.sort((a,b)=>a-b)
//0放重复元素,1放丢失元素
let arr=[0,0]
//官方构造数组
//const errorNums = new Array(2).fill(0);
let prev=0
nums.forEach((num)=>{
if(num==prev) {
arr[0]=num
}else if(num-prev>1) {
arr[1]=prev+1
}
prev=num
})
if(nums[n-1]!=n) {
arr[1]=n
}
return arr
};
- 方法二:哈希表
重复的数字在数组中出现 2 次,丢失的数字在数组中出现 0次,其余的每个数字在数组中出现 1次。因此可以使用哈希表记录每个元素在数组中出现的次数,然后遍历从 1到 n的每个数字,分别找到出现 2次和出现 0次的数字,即为重复的数字和丢失的数字。
class Solution {
public int[] findErrorNums(int[] nums) {
int[] errorNums = new int[2];
int n = nums.length;
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
for (int i = 1; i <= n; i++) {
int count = map.getOrDefault(i, 0);
if (count == 2) {
errorNums[0] = i;
} else if (count == 0) {
errorNums[1] = i;
}
}
return errorNums;
}
}
数组的度(LeetCode 697)
- 题目概述:给定一个非空且只包含非负数的整数数组 nums,数组的度的定义是指数组里任一元素出现频数的最大值。
你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度。 - 题目示例:
示例 1:
输入:[1, 2, 2, 3, 1]
输出:2
解释:
输入数组的度是2,因为元素1和2的出现频数最大,均为2.
连续子数组里面拥有相同度的有如下所示:
[1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2]
最短连续子数组[2, 2]的长度为2,所以返回2. - 方法:哈希表
注意点:
1.思路要放置于值可以为数组
2.在最后返回数组长度时要考虑到数组可能中有多个出现频率最大的值,要进行长度比较
java代码
class Solution {
public int findShortestSubArray(int[] nums) {
//键是数组中对应的值,值是一个数组,数组的第一个值是出现的次数,第二个值是第一次出现的位置,第三个值是最后一次出现的位置
Map<Integer,int[]> map=new HashMap<Integer,int[]>();
int n=nums.length;
for(int i=0;i<n;i++) {
if(map.containsKey(nums[i])) {
map.get(nums[i])[0]++;
map.get(nums[i])[2]=i;
}else {
map.put(nums[i],new int[]{1,i,i});
}
}
int maxNum=0,minLen=0;
for(Map.Entry<Integer,int[]> entry:map.entrySet()) {
int[] arr=entry.getValue();
if(maxNum<arr[0]) {
maxNum=arr[0];
minLen=arr[2]-arr[1]+1;
}else if(maxNum==arr[0]) {//度相同时,选择长度最短的
if(minLen>arr[2]-arr[1]+1) {
minLen=arr[2]-arr[1]+1;
}
}
}
return minLen;
}
}
JS代码
/**
* @param {number[]} nums
* @return {number}
*/
var findShortestSubArray = function(nums) {
let map=new Map()
let n=nums.length;
for(let i=0;i<n;i++) {
if(map.has(nums[i])) {
map.get(nums[i])[0]++;
map.get(nums[i])[2]=i;
}else {
let arr=[1,i,i];
map.set(nums[i],arr);
}
}
let maxNum=0,minLen=0;
for(const [count,left,right] of map.values()) {
if(maxNum<count) {
maxNum=count;
minLen=right-left+1;
}else if(maxNum===count) {
if(minLen>right-left+1) {
minLen=right-left+1;
}
}
}
return minLen;
};
找到所有数组中消失的数字(LeetCode448)
给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。
- 方法:原地修改
在自身代码上加以修改,利用所有元素值均位于1-n之间,所以加上n一定会大于n,所以小于等于n的则是消失的那个数字
java代码
class Solution {
public List<Integer> findDisappearedNumbers(int[] nums) {
int n = nums.length;
for (int num : nums) {
int x = (num - 1) % n;
nums[x] += n;
}
List<Integer> ret = new ArrayList<Integer>();
for (int i = 0; i < n; i++) {
if (nums[i] <= n) {
ret.add(i + 1);
}
}
return ret;
}
}
JS代码
/**
* @param {number[]} nums
* @return {number[]}
*/
var findDisappearedNumbers = function(nums) {
let arr=new Array()
let n=nums.length
nums.forEach((num)=> {
let x=(num-1)%n
nums[x]+=n
})
for(let i=0;i<n;i++) {
if(nums[i]<=n) {
arr[arr.length]=(i+1)
}
}
return arr
};