/*645、错误的集合*/
/*思路一:
* 创建hash表,如果hash元素为1说明此元素重复,最后遍历一遍hash表,值为0说明缺少此元素
* */
/*通过*/
public int[] findErrorNums(int[] nums) {
int n = nums.length;
int[] hash = new int[n + 1];
int[] res = new int[2];
for (int num : nums) {
if (hash[num] == 1) res[0] = num;
hash[num]++;
}
for (int i = 1; i < n + 1; i++) {
if (hash[i] == 0) {
res[1] = i;
return res;
}
}
return res;
}
/*697、数组的度*/
/*
* 思路一:
* 哈希表,需要用到map,键为nums中出现过的元素,值为一个三个元素空间的数组
* 0索引为当前值出现过的次数,1、2索引分别为此元素第一次出现和最后一次出现的位置
* 第一次遍历数组,如果map中没有此元素,添加进去,并且创建数组为1、i、i
* 如果有此元素,将数组更新为+1、i、i+1
* 第二次要遍历map,如果次数比最大次数小,跳过,如果等于,判断最短位置,如果大于,更新位置
* */
/*注意度为两个位置索引的差+1*/
/*通过*/
public int findShortestSubArray(int[] nums) {
HashMap<Integer, int[]> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(nums[i])) {
int[] arr = map.get(nums[i]);
arr[0]++;
arr[2] = i;
} else {
int[] arr = {1, i, i};
map.put(nums[i], arr);
}
}
int d = 0, size = 0;
for (Map.Entry<Integer, int[]> entry : map.entrySet()) {
int[] value = entry.getValue();
if (value[0] == d) {
size = Math.min(size, value[2] - value[1] + 1);
} else if (value[0] > d) {
d = value[0];
size = value[2] - value[1] + 1;
}
}
return size;
}
/*448、找到所有数组中消失的数字*/
/*
* 思路一:
* 哈希表,遍历数组,将当前元素索引位置的元素值改为负数,这样一来所有出现过的数字的对应位置上的值都为负数
* 那么还是正数的位置对应索引是没有出现过的数
* */
/*注意因为是1-n,所以对应索引要减一,*/
/*通过*/
public List<Integer> findDisappearedNumbers(int[] nums) {
for (int i = 0; i < nums.length; i++) {
nums[Math.abs(nums[i]) - 1] = -Math.abs(nums[Math.abs(nums[i]) - 1]);
}
List<Integer> list = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0) list.add(i + 1);
}
return list;
}
/*442、数组中重复的数据*/
/*
* 思路一:
* 遍历数组,得到当前元素对应索引位置的元素,判断其是否为负数,不是将其改为负数
* 如果是说明此前已经有另一个一样的数字来修改过,那么将当前元素添加
* */
/*注意,因为最多只可能出现两个相同的数字,所以取反可以直接乘以负一*/
/*通过*/
public List<Integer> findDuplicates(int[] nums) {
List<Integer> res = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
if (nums[Math.abs(nums[i]) - 1] < 0) {
res.add(Math.abs(nums[i]));
} else {
nums[Math.abs(nums[i]) - 1] *= -1;
}
}
return res;
}
/*41、缺少的第一个正数*/
/*
* 思路一:创建相同大小的hash表,遍历数组,将hash表对应位置修改为1
* 然后遍历hash表,将第一个为0的索引返回(0除外)
* */
/*通过,但是空间复杂度为o(n)*/
public int firstMissingPositive(int[] nums) {
int n = nums.length;
int[] hash = new int[n + 1];
for (int num : nums) {
if (num >= 0 && num <= n) {
hash[num] = 1;
}
}
for (int i = 1; i < n + 1; i++) {
if (hash[i] == 0) return i;
}
return n + 1;
}
/*空间复杂度O(1)做法*/
/*思路:
* 不难看出返回的结果肯定是介于1~n+1之间的
* 将出现过的数字对应位置的元素在原数组上标记出来,这样就可以遍历原数组没有标记的就是最小正数
* 关键点就是如何做标记,强调一点就是做标记后一定要还能看出原数字的值
* 首先解决负数超出长度的数,负数是不做成分的,所以将所有负数都改为n+1
* 然后是做标记,把对应位置的数改为负数,前提是原本为正数,这样只有有用并且没有出现过的数对应位置的数为正数
* 如果都为正数说明都出现了,返回n+1
* */
/*通过*/
public int firstMissingPositive2(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 num = Math.abs(nums[i]);
if (num <= n) {
nums[num - 1] = -Math.abs(nums[num - 1]);
}
}
for (int i = 0; i < n; i++) {
if (nums[i] > 0) return i + 1;
}
return n + 1;
}
/*274、H指数*/
/*题意分析:其实就是找出数组中x个数,这x个数每个都要大于等于x,并且剩下的数都要小于x
比如第一个数要大于等于1,第二个数要大于等于2...
* */
/*思路一:
* 将数组排序,逆序遍历,判断当前数是否大于等于正序索引索引,是的话就继续遍历,否则退出
* 遍历的个数就是H指数
* */
/*通过*/
public int hIndex(int[] citations) {
Arrays.sort(citations);
int x = 1;
for (int i = citations.length - 1; i >= 0; i--, x++) {
if (citations[i] < x) {
break;
}
}
return x - 1;
}