LeetCode刷题 | Day3 数组遍历

题目:645. 错误的集合

我的思路:先将数组排序,然后将nums[j]与该位置上正确的数i比较,如果nums[j]=i+1,则说明此处有个数字缺失(缺失的数为i),并立刻将i++;如果nums[j]=i-1,则说明此处是重复的数字(重复数为i-1),并立刻i--。

遍历后有两种特殊情况需要讨论:缺失值在最后(即缺失值undefined),1缺失2重复(即重复值undefined)。

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var findErrorNums = function(nums) {
    nums.sort( (a,b) => a-b );
    var a,b;
    for (let i=1,j=0; j<nums.length; i++,j++) {
        if(i == nums[j]){
            continue;
        }else if(i+1 == nums[j]){
            b=i;
            i++;
        }else if(i-1 == nums[j]){
            a=i-1;
            i--;
        }
    }
    if(b == undefined) b=nums.length;
    if(a == undefined) a=2;
    return [a,b];
};

题解的方法一:先排序,将数组前后两个数比较,相等为重复的数,相减大于1为缺失数。需要对缺失值为1和n进行讨论。

方法二:用哈希表记录元素出现的次数

var findErrorNums = function(nums) {
    const errorNums = new Array(2).fill(0);
    const n = nums.length;
    const map = new Map();
    for (const num of nums) {
        map.set(num, (map.get(num) || 0) + 1);
    }
    for (let i = 1; i <= n; i++) {
        const count = map.get(i) || 0;
        if (count === 2) {
            errorNums[0] = i;
        } else if (count === 0) {
            errorNums[1] = i;
        }
    }
    return errorNums;
};

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/set-mismatch/solution/cuo-wu-de-ji-he-by-leetcode-solution-1ea4/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

时间复杂度和空间复杂度都为O(n)

方法三:纯数学方法

class Solution:
    def findErrorNums(self, nums):
        ln, total = len(nums), sum(set(nums))
        return [sum(nums) - total, (1 + ln) * ln // 2 - total]

题目:697. 数组的度 

我的思路:容易想到,首先统计各个元素出现的频次,最短连续子数组必定一头一尾是频次最大的那个数,需要比较频次最大且相等的不同元素的子数组的长度。

但是,我将上面的步骤拆分了来做,复杂且没有结果。

看看官方题解:

在实际代码中,我们使用哈希表实现该功能,每一个数映射到一个长度为 3 的数组,数组中的三个元素分别代表这个数出现的次数、这个数在原数组中第一次出现的位置和这个数在原数组中最后一次出现的位置。当我们记录完所有信息后,我们需要遍历该哈希表,找到元素出现次数最多,且前后位置差最小的数。

var findShortestSubArray = function(nums) {
    const mp = {};

    for (const [i, num] of nums.entries()) {
        if (num in mp) {
            mp[num][0]++;
            mp[num][2] = i;
        } else {
            mp[num] = [1, i, i];
        }
    }
    
    let maxNum = 0, minLen = 0;
    for (const [count, left, right] of Object.values(mp)) {
        if (maxNum < count) {
            maxNum = count;
            minLen = right - left + 1;
        } else if (maxNum === count) {
            if (minLen > (right - left + 1)) {
                minLen = right - left + 1;
            }
        }
    }
    return minLen;
};

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/degree-of-an-array/solution/shu-zu-de-du-by-leetcode-solution-ig97/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

时间复杂度O(n)

空间复杂度O(n) 

滑窗解法:

//时间O(n)  空间O(n)
class Solution {
    public int findShortestSubArray(int[] nums) {
        int n = nums.length;
        int[] freq = new int[50000];//记录频数
        int degree = 0;//记录数组度
        for (int i = 0; i < n; i++) {
            degree = Math.max(++freq[nums[i]], degree);
        }
        Arrays.fill(freq, 0);
        int left = 0, right = 0, minSpan = Integer.MAX_VALUE;//窗口边界和最小跨度
        while (right < n) {
            freq[nums[right]]++;//右窗口划进一个数,其频数加一
            while (left <= right && degree == freq[nums[right]]) {//如果其频数等于度
                minSpan = Math.min(minSpan, right - left + 1);//记录最小窗口大小
                freq[nums[left++]]--;//收缩左窗口
            }
            ++right;//扩大右窗口
        }
        return minSpan;
    }
}

448. 找到所有数组中消失的数字

通过建立哈希表,再遍历的方法容易想到,但不满足原地算法

题解:

var findDisappearedNumbers = function(nums) {
    const n = nums.length;
    for (const num of nums) {
        const x = (num - 1) % n;
        nums[x] += n;
    }
    const ret = [];
    for (const [i, num] of nums.entries()) {
        if (num <= n) {
            ret.push(i + 1);
        }
    }
    return ret;
};

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/find-all-numbers-disappeared-in-an-array/solution/zhao-dao-suo-you-shu-zu-zhong-xiao-shi-d-mabl/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 442. 数组中重复的数据

 同样要求原地算法,可以用上一题的方法解(+n,%n)

方法二:将元素交换到对应的位置

方法三:用正负号标记

(三种原地方法都包含了对应关系:nums[i] - 1 -> 位置i )

41. 缺失的第一个正数

由上题方法二想到解法,将数组复原到元素拜访到对应位置的状态。但此题中需要注意:在完成交换后,新的 nums[i] 可能还在 [1,N] 的范围内,我们需要继续进行交换操作,所以需要使用while而不是if。

/**
 * @param {number[]} nums
 * @return {number}
 */
var firstMissingPositive = function(nums) {
    var temp;
    var swap = function(nums, a, b){
        temp = nums[a];
        nums[a] = nums[b];
        nums[b] = temp;
    }
    
    for(let i=0; i<nums.length; i++){
        while(nums[i]>0 && nums[i]<=nums.length && nums[i] != nums[nums[i]-1]){
            swap(nums, i, nums[i]-1);
        }
    }
    for(let i=0; i<nums.length; i++){
        if (nums[i] != i+1) return i+1;
    }
    return nums.length+1;
};

此题用正负号标记也可以完成:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值