【前端er每日算法】贪心继续-1005/134/135

138 阅读1分钟

题目一 1005. K 次取反后最大化的数组和

思路

先把数组按照绝对值大小从大到小排列,然后遍历数组,如果k大于0,并且当前值小于0,则将该值进行取反,遍历完成后,如果k还大于0并且k是奇数,则取反最后一个数,否则不取反。

var largestSumAfterKNegations = function(nums, k) {
    let len = nums.length;
    let sum = 0;
    nums.sort((a, b) => Math.abs(b) - Math.abs(a));
    for (let i = 0; i < len; i++) {
        if (nums[i] < 0 && k > 0) {
            nums[i] = 0 - nums[i];
            k--;
        }
    }
    if (k > 0 && k % 2 === 1) {
        nums[len - 1] = 0 - nums[len - 1]; 
    }
    for (let i = 0; i < len; i++) {
        sum += nums[i];
    }
    return sum
};

题目二 134. 加油站

思路

计算gas和cost的差值数组,如果和小于0了,更新start,如果最后差值小于0,肯定不满足,否则返回start。

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

题目三 135. 分发糖果

思路

  • 第一遍遍历比较右边孩子和左边孩子的大小,如果右边比左边大,则加1,
  • 第二遍比较左边孩子和右边孩子的大小,但是从后向前遍历,这样可以用右边的结果,如果左边比右边大,则左边元素更新为当前元素的大小和右边元素+1的最大值
  • 最后candy结果相加就是耗费的糖果数。
var candy = function(ratings) {
    const len = ratings.length;
    const candyArr = new Array(len).fill(1);
    for (let i = 1; i < len; i++) {
        if (ratings[i] > ratings[i - 1]) {
            candyArr[i] = candyArr[i - 1] + 1;
        }
    }
    for (let i = len - 2; i >= 0; i--) {
        if (ratings[i] > ratings[i + 1]) {
            candyArr[i] = Math.max(candyArr[i], candyArr[i + 1] + 1);
        }
    }
    let sum = 0;
    for (let i = 0; i < len; i++) {
        sum += candyArr[i];
    }
    return sum;
};