645.
集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。
给定一个数组 nums 代表了集合 S 发生错误后的结果。
请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
示例 1:
输入:nums = [1,2,2,4]
输出:[2,3]
示例 2:输入:nums = [1,1]
输出:[1,2]来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/set-mismatch
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:想到了最笨的数学方法,即先找出那个重复的数字,再通过数学方法计算本该有的和,再与现在的和进行做差运算,最后就可以得到那个丢失的整数。
class Solution {
public int[] findErrorNums(int[] nums) {
Arrays.sort(nums);
int sum = nums[0];
int[] newNums=new int[2];
for(int a=1;a<=nums.length-1;a++){
sum+=nums[a];
if(nums[a]==nums[a-1]){
newNums[0]=nums[a];
}
}
int b =nums.length*(1+nums.length)/2;
newNums[1]= newNums[0]+(b-sum);
return newNums;
}
}
其他方法:位运算和哈希表(暂时还没有做,等到学到哈希表再做。)
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.
示例 2:输入:[1,2,2,3,1,4,2]
输出:6来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/degree-of-an-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
用hash表存储键对,用数组作为value值,含有三个值
【1.第一次出现的地方。2.次数。3.最后出现的地方。】
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;
}
}
448.
给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。
示例 1:
输入:nums = [4,3,2,7,8,2,3,1]
输出:[5,6]
示例 2:输入:nums = [1,1]
输出:[2]来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
1.创建一个新数组
2.nums【】进行for each循环,每次循环给新数组对应的赋值
3.对新数组进行遍历,没有值的就是缺失的数字
class Solution {
public List<Integer> findDisappearedNumbers(int[] nums) {
List<Integer> list = new ArrayList<>();
int[] help = new int[nums.length+1];
for(int num : nums) {
help[num] = 1;
}
for(int i = 1; i < help.length;i++) {
if (help[i] == 0) {
list.add(i);
}
}
return list;
}
}
442.
给定一个整数数组 a,其中1 ≤ a[i] ≤ n (n为数组长度), 其中有些元素出现两次而其他元素出现一次。
找到所有出现两次的元素。
你可以不用到任何额外空间并在O(n)时间复杂度内解决这个问题吗?
示例:
输入:
[4,3,2,7,8,2,3,1]输出:
[2,3]来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-all-duplicates-in-an-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
不占用任何额外空间的话,我们需要把数组本身看成是一个哈希表,利用取余的运算方式,做成一个哈希表。
public List<Integer> findDuplicates(int[] nums) {
List<Integer> ret = new ArrayList<>();
int n = nums.length;
for(int i = 0; i < n; i++){
nums[(nums[i] - 1) % n] += n;
}
for(int i = 0; i < n; i++){
if(nums[i] > 2 * n) ret.add(i+1);
}
return ret;
}
41.
给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。
请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。
示例 1:
输入:nums = [1,2,0]
输出:3
示例 2:输入:nums = [3,4,-1,1]
输出:2
示例 3:输入:nums = [7,8,9,11,12]
输出:1来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/first-missing-positive
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
做的第一道困难题,虽然遭遇困难,但也算是通过理解把这道题做出来了。
class Solution {
public int firstMissingPositive(int[] nums) {
int len =0;
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+1){
nums[(num - 1) % n] = -Math.abs(nums[(num - 1) % n]);
}
}
for (int i = 0; i < n; ++i) {
if (nums[i] > 0) {
return i+1;
}
}
return n+1;
}
}
和442题思路有点像,都是把数组当成是一个哈希表来解答,规避非正数就可以
1.将数组所有的非正数都转化成N+1
2.利用绝对值,为所有存在的数打上一个标记:负数(为什么要用绝对值,因为如果不是绝对值的话,如果出现两个一样的数,就会发生一个数被负数两次而导致负负得正的情况。)
3.如果每一个数都是负数,那么差的最小的正整数就是N+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 temp=nums[nums[i]-1];
nums[nums[i]-1]=nums[i];
nums[i]=temp;
}
}
for(int i=0;i<n;i++){
if(nums[i]!=i+1) return i+1;
}
return n+1;
}
}
置换法!
274.
给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。
h 指数的定义:h 代表“高引用次数”(high citations),一名科研人员的 h 指数是指他(她)的 (n 篇论文中)总共有 h 篇论文分别被引用了至少 h 次。且其余的 n - h 篇论文每篇被引用次数 不超过 h 次。
例如:某人的 h 指数是 20,这表示他已发表的论文中,每篇被引用了至少 20 次的论文总共有 20 篇。
提示:如果 h 有多种可能的值,h 指数 是其中最大的那个。
示例 1:
输入:citations = [3,0,6,1,5]
输出:3
解释:给定数组表示研究者总共有 5 篇论文,每篇论文相应的被引用了 3, 0, 6, 1, 5 次。
由于研究者有 3 篇论文每篇 至少 被引用了 3 次,其余两篇论文每篇被引用 不多于 3 次,所以她的 h 指数是 3。
示例 2:输入:citations = [1,3,1]
输出:1来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/h-index
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
1.h的值一定是在【1,n】中的一个正整数,因此可以对【1,n】进行二分查找。
2.对每个可能性的值进行判断:即一次for循环的遍历,看是否有足够可能性的值符合。
class Solution {
public int hIndex(int[] citations) {
int n=citations.length;
int l=0,r=n;
//二分引用次数
while(l<=r){
int mid = l + (r-l)/2;
if(check(citations,mid)){
l=mid+1;
}else{
r=mid-1;
}
}
return r;
}
public boolean check(int[] citations, int mid) {
int count=0;
for (int citation : citations) {
//如果论文引用次数 >= 当前引用次数,符合要求的篇数+1
if(citation>=mid){
count++;
}
}
//如果符合要求篇数>=引用次数,则当前值可以为H指数
return count>=mid;
}
}
leetcode评论中发现的巧妙的方法:
1.首先排序数组,把数组按顺序排列。
2.默认h为数组的长度,即满的,然后遍历数组。
3.如果数组中该index的元素小于当前h,那么h--。
4.最后返回h。
class Solution {
public int hIndex(int[] citations) {
//[3,0,6,1,5] - >[0,1,3,5,6]
Arrays.sort(citations);
//默认这5篇被引用了5次
int h = citations.length;
for(int i=0;i<citations.length;i++){
//比较小于则 h-1
if(citations[i] < h){
h--;
}
}
return h;
}
}