数组题目:645. 错误的集合、 697. 数组的度、 448. 找到所有数组中消失的数字、442. 数组中重复的数据 、41. 缺失的第一个正数

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]);
                //出现次数+1
                cur[0] += 1;
                //如果出现的次数比max大,或者次数相同,但是数组长度更小,就更新max
                if(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;
    }
    
}

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值