算法修炼Day34|1005.K次取反后最大化的数组和 ● 134. 加油站 ● 135. 分发糖果

92 阅读2分钟

LeetCode:1005. K 次取反后最大化的数组和 - 力扣(LeetCode)

1.思路

对数组进行升序排序,当数组元素小于0且k大于0时,取绝对值进行加和,当k==0时,直接加上数组元素值即可。当遍历结束且k还大于0,取模==0,直接忽略,取模==1时就选择一个绝对值最小的元素进行减操作。

2.代码实现
class Solution {
    public int largestSumAfterKNegations(int[] nums, int k) {
        // 找到数值小于 0 的,优先绝对值大的加符号,排序
        Arrays.sort(nums);
        // 记录绝对值的最小值 value
        int value = Integer.MAX_VALUE;
        // 求和 sum
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            value = Math.min(Math.abs(nums[i]), value);
            if (nums[i] < 0) {
                if (k > 0) {
                    sum += Math.abs(nums[i]);
                    k--;
                } else {
                    sum += nums[i];
                }
            } else if (nums[i] >= 0) {
                sum += nums[i];
            }
        }
        if (k > 0 && k % 2 == 1) {
            sum -= 2 * value;
        }
        return sum;
    }
}
3.复杂度分析

时间复杂度:O(logn).

空间复杂度:O(1).

LeetCode:134. 加油站 - 力扣(LeetCode)

1.思路

双层for循环超时。采用贪心的思路,设置当前剩余油量和当前剩余总油量,如果当前剩余油量小于0,则标记从下一个索引位置进行加和,同时当前油量置为0。遍历结束之后,如果当前总剩余油量小于0,表示从任何一个位置都不能形成循环,反之,上面标记的下一个索引就是能走到循环末尾的索引。

2.代码实现
// 超时算法
class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        // 油剩余量 消耗量cost
        int restGas = 0;
        for (int i = 0; i < gas.length; i++) {
            // 剩余油量
            restGas += gas[i] - cost[i];
            int count = 0;
            int j = i;
            while (restGas >= 0) {
                j++;
                restGas += gas[j % gas.length] - cost[j % gas.length];
                count++;
                if (count == gas.length) {
                    return i;
                }
            }
            restGas = 0;
        }
        return -1;
    }
}

// 不太好想的思路
class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        // 当前油量
        int currentSum = 0;
        // 总油量
        int totalSum = 0;
        // 满足要求的索引下标index
        int index = 0;
        for (int i = 0; i < gas.length; i++) {
            currentSum += gas[i] - cost[i];
            totalSum += gas[i] - cost[i];
            if (currentSum < 0) { // 说明当前油量剩余量不足
                index = (i + 1) % gas.length; // 需要从下一个索引位置进行衡量
                currentSum = 0; // 可能存在连续不足的情况,故重置为0,循环执行
            }
        }
        if (totalSum < 0) {
            return -1;
        }
        return index;
    }
}
3.复杂度分析

时间复杂度:O(n).

空间复杂度:O(1).

LeetCode:135. 分发糖果 - 力扣(LeetCode)

1.思路

创建糖果数组,存放每个小孩得到的最少糖果数,根据规则分别从左右两侧进行遍历。

2.代码实现
class Solution {
    public int candy(int[] ratings) {
        if (ratings.length == 1) {
            return 1;
        }
        int[] candyCount = new int[ratings.length];
        candyCount[0] = 1;
        // 右边大于左边
        for (int i = 1; i < ratings.length; i++) {
            if (ratings[i] > ratings[i - 1]) {
                candyCount[i] = candyCount[i - 1] + 1;
            } else {
                candyCount[i] = 1; // 当右边小于左边时给个默认值1
            }
        }
        // 左边大于右边
        for (int i = ratings.length - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1]) {
                candyCount[i] = Math.max(candyCount[i], candyCount[i + 1] + 1);
            }
        }
        int sum = 0;
        for (int i = 0; i < candyCount.length; i++) {
            sum += candyCount[i];
        }
        return sum;
    }
}
3.复杂度分析

时间复杂度:O(n).

空间复杂度:O(n).