Leetcode 数组篇

53. 最大子数组和https://leetcode.cn/problems/maximum-subarray/

        重刷出现的一些小问题:

        1、dp[i]的含义是什么:以i为下标的最大连续子数组的和

        所以我们需要找到dp中最大的值————用ans维护。

        2、ans的值定义为Number的最小值了,那当nums中只有一个数的时候,返回的是ans,就出

             错了。

    // 第一感觉:这肯定得用dp做
    // 时间复杂度:O(n)
    // 空间复杂度:O(n)
    const dp = new Array().fill(0);

    // 赋初值的一个问题:被一个值搞晕了,以为输出个数
    dp[0] = nums[0];
    let ans = dp[0];

    // dp数组就是存储以该下标结束的一个长度,所以最后当然需要去找出其中的最大值
    for(let i = 1;i<nums.length;i++){
        dp[i] = Math.max(dp[i-1]+nums[i], nums[i]);
        ans = Math.max(dp[i], ans);
    }

    return ans;

1. 两数之和https://leetcode.cn/problems/two-sum/

        容易题;

    // 是否存在某数——立马想到哈希法(数组,set, 哈希表)
    // 如果不要求O(n^2)的话 那就是两个for循环,那就太low了,所以肯定需要以空间去换时间

    // 时间复杂度:O(n)
    // 空间复杂度:O(n)
    const map = new Map();
    for(let i = 0;i<nums.length;i++){
        if(map.has(target - nums[i])){
            return [map.get(target - nums[i]), i];
        }
        map.set(nums[i], i);
    }

121. 买卖股票的最佳时机https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/

        1、重做一次还是用了双重循环n2的 时间复杂度,没有过;

        2、直觉用dp通过了;还是上面的问题,你不知道维护的最后的dp是不是最大值,是因为你没

             弄清楚dp[i]的含义到底是什么,好在你可以输出看看dp[i]的值你就明白了;

        3、实际上都用不上dp,直觉维护一个当前最小值,和当前利润的最大值

// 肯定得选当前最小的买,为什么不是全数字最小的?——因为不能保证最小的顺序一定在卖之后
    // 下面的超出时间限制了,那就想办法以空间换时间
    // let curMin = 0;
    // let ans = 0;
    // for(let i = 0;i<prices.length;i++){
    //     curMin = i;
    //     let sum = 0;
    //     for(let j = i+1;j<prices.length;j++){
    //         sum = prices[j] - prices[i];
    //         ans = Math.max(ans, sum);
    //     }
    // }
    // return ans;

    // 也没有用空间换时间
    // 其实就是一个关键点:每次都维护当前的一个最小值,然后维护都在当前卖出去的一个价格,找到其中最大值
    // 时间复杂度:O(n)
    // 空间复杂度:O(1)
    let curMin = prices[0];
    let ans = 0;
    for(let i = 0;i<prices.length;i++){
        curMin = Math.min(curMin, prices[i]);
        ans = Math.max(ans, prices[i] - curMin);

    }
    return ans;

169. 多数元素https://leetcode.cn/problems/majority-element/

// 一定要记住先排序,有个直接的切入口,既然多数元素的次数肯定大于n/2,那么在n/2个位置上肯定就是多数元素了
// 时间复杂度:O(nlgn) 排序的
// 空间复杂度: 看排序
    // nums.sort();
    // return nums[Math.floor(nums.length/2)];


    // 也可以尝试出现的值作为键,次数作为值,找出次数最大的
    // 时间复杂度:O(n) 
    // 空间复杂度: O(n)
    const map = new Map();
    for(let i = 0;i<nums.length;i++){
        if(map.has(nums[i])){
            map.set(nums[i], map.get(nums[i])+1);
        }else{
            map.set(nums[i], 1);
        }
    }
    let ans = -1;
    let res = 0;
    map.forEach(function(value, key){
        if(value > ans){
            res = key;
            ans = value;
        }
    })
    return res;

回顾了一下遍历map的方法:

(1)map.forEach(function(value, key){}) //第一个是值, 第二个是键

(2)for(let item of map){}

        for(let key of map.keys()){}

        for(let value of map.values()){}

(3)entries遍历,和forEach一样

        for(let item of map.entries())

 for(let item in xx):遍历的是下标:

283. 移动零https://leetcode.cn/problems/move-zeroes/

哎~~这道题在我找实习的第一个面试中出现,超简单呀,但是我还以为前端不考算法题,我也没刷题,而且很久很久很久很久没刷题了,手生的一批啊,挂了应该的,活该~继续努力!

// 这不就是双指针吗,哼
    // 时间复杂度: O(n)
    // 空间复杂度: O(1)
    // j维持非0元素下标, i遍历所有元素,找到非0元素就放到j的位置上,完了之后填充j之后到数组长度之间的数都为0;
    let j = 0;
    for(let i = 0;i<nums.length;i++){
        if(nums[i]!==0){
            nums[j] = nums[i];
            j++;
        }
    }
    //填充0
    for(let k = j;k<nums.length;k++){
        nums[k] = 0;
    }
    return nums;

581. 最短无序连续子数组https://leetcode.cn/problems/shortest-unsorted-continuous-subarray/

        思路是正确的,但是需要更加细心呀; 

// 最开始没想法呀,后面试了一下自己的想法有一半案列没过。
// 就去看了官方的解答,就是将原数组与有序后的数组进行比较,找到不相同的左右边界即可。
// 时间复杂度:O(nlgn) 排序
// 空间复杂度:O(n)
const isSorted = (nums)=>{
    for(let i = 0; i<nums.length;i++){
        if(nums[i] < nums[i-1]){
            return false;
        }
    }
    return true;
}

if(isSorted(nums) || nums.length <2){
    return 0;
}
// 拷贝该数组,变成有序的数组,且不会改变原先的数组
// 单纯的把数组复制 是浅拷贝,会影响原数组
let sortedNums = [...nums].sort((a,b)=>{
    return a-b;
});
let left = 0, right=0;
for(let i = 0; i<nums.length;i++){
    if(nums[i] !== sortedNums[i]){
        left = i;
        break;
    }
}
for(let j = nums.length-1; j>=0;j--){
    if(nums[j] !== sortedNums[j]){
        right = j;
        break;
    }
}


return right - left + 1;

知识点回顾: 深浅拷贝

首先回顾一下扩展运算符... 学习参考JS中的扩展运算符(...)和剩余运算符(...)_webchang的博客-CSDN博客

非常清晰!

关于深浅拷贝的学习参考

JS之深浅拷贝详解_前端菜菜DayDayUp的博客-CSDN博客

非常清晰+1!

常用方法:新创建一个空数组,一个一个加进去;扩展运算符(这个更好用);一维的话slice()也可以

多维的一定要用JSON.parse(JSON.stringify(obj));

448. 找到所有数组中消失的数字https://leetcode.cn/problems/find-all-numbers-disappeared-in-an-array/

        第二次我用了map,还不如用array嘞; 

  // 用一个数组记录,出现过的值为数组值为其本身的值,没有出现过的值对应的数组值为0
    // 时间复杂度:O(n)
    // 空间复杂度:O(n)
    let n = nums.length;
    let ans = new Array(n+1).fill(0);
    for(let i = 0;i<n;i++){
        ans[nums[i]] = nums[i];
    }
    let count = [];
    console.log(ans);
    for(let i =1;i<=n;i++){
        if(ans[i]===0){
            count.push(i);
        }
    }
    return count;

数组篇结束啦, 多去思考一下问题,还有小错误注意避免,切记不能死记硬背!加油;

还是要更加细心一点,现在思路都大概有了,一是个别地方的小错误要注意,二是怎么实现好也要动动脑子,不行就感觉换一个方法;总之数组吗,排个序啊,双指针遍历啊,用array、map,不外乎这些方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值