【每日刷题】238. 除自身以外数组的乘积-134.加油站

67 阅读2分钟

本来前段时间打算每天刷2道题,后来不想刷了,出现了刷题厌恶症,经过一番斗争,就打算随意刷了,隔两天会刷刷题,今天终于刷了2道,可喜可贺,再记录下:

题目一 238. 除自身以外数组的乘积

这个题一看,好像不难,主要是题目限制不能用除法,还要求O(n),想了一会,无解,就看题解了,

题解是用两个数组,分别记录当前位置的左乘积和、右乘积和,然后再遍历一遍就出来了,看了之后还是挺简单的,这道题无痛刷题,还好还好。

var productExceptSelf = function(nums) {
    const len = nums.length;
    const left = [1];
    for (let i = 1; i < len; i++) {
        left[i] = left[i - 1] * nums[i - 1];
    }
    const right = [];
    right[len - 1] = 1;
    for (let i = len - 2; i >= 0; i--) {
        right[i] = right[i + 1] * nums[i + 1];
    }
    
    const result = [];
    for (let i = 0; i < len; i++) {
        result[i] = left[i] * right[i];
    }
    return result;
};

题目二 134. 加油站

写了个暴力算法,超时了,看题解是贪心算法,算法思路,不断计算gas[j] - cost[j]的和,如果和小于0了,则说明无法到达j,则从之前的所有节点出发都无法到达j,需要更新出发点和当前的和。

为什么小于0就说明前面的节点都不能到达了呢?假如中间某个k可以到达j,则说明该段累加和大于0,这将路程分为2段,从开始i到k,从k到j,从i到j的累加和小于0,而k到j大于0,则肯定i到k小于0,那就矛盾了,应该从k开始了。

var canCompleteCircuit = function(gas, cost) {
    let curSum = 0;
    let totalSum = 0;
    let start = 0;
    for (let i = 0; i < gas.length; i++) {
        curSum += gas[i] - cost[i];
        totalSum += gas[i] - cost[i];
        if (curSum < 0) {
            start = i + 1;
            curSum = 0;
        }
    }
    if (totalSum < 0) {
        return -1;
    }
    return start;
};

ps: 算法还是难啊!!

题目三、135. 分发糖果

困难题,之前好像看过解法,又忘了,说明木有掌握。。。这次又直接看答案,看了答案倒是不难,但是自己想确实想不出来。

如果在考虑局部的时候想两边兼顾,就会顾此失彼。

那么本题采用了两次贪心的策略:

  • 一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
  • 一次是从右到左遍历,只比较左边孩子评分比右边大的情况。

这样从局部最优推出了全局最优,即:相邻的孩子中,评分高的孩子获得更多的糖果。

但其实我在想,这种思路到底是怎么想出来的?为什么是这样的思路?

#

var candy = function(ratings) {
    const len = ratings.length;
    const left = [1];
    for (let i = 1; i < len; i++) {
        if (ratings[i] > ratings[i - 1]) {
            left[i] = left[i - 1] + 1;
        } else {
            left[i] = 1;
        }
    }
    let right = 0, ret = 0;
    for (let i = len - 1; i >= 0; i--) {
        if (i < len - 1 && ratings[i] > ratings[i + 1]) {
            right++;
        } else {
            right = 1;
        }
        ret += Math.max(left[i], right);
    }
    return ret;
};