day34 ● 1005.K次取反后最大化的数组和 ● 134. 加油站 ● 135. 分发糖果

贪心算法是一种常用的算法设计技巧,通常用来解决最优化问题。它的基本思想是,每一步选择最优的解决方案,最终得到全局最优解。

在本文中,我们将介绍三道使用贪心算法解决的题目,分别是1005.K次取反后最大化的数组和、134. 加油站、135. 分发糖果。

  1. 1005.K次取反后最大化的数组和

题目描述:给定一个长度为 n 的整数数组 A,每次操作可以将 A 中任意一个数取反,最多进行 K 次操作,求通过操作能够得到的最大数组和。

解题思路:根据题目要求,我们需要最大化数组和,因此可以考虑让大的数尽可能地保持正数,小的数尽可能地变成负数。具体的,我们可以先将数组 A 中的所有数按照绝对值从大到小排序,然后从前往后遍历数组,如果当前数为负数且还剩余 K 次操作,就将其取反,同时将 K 减一。最终得到的数组和就是最大的。

代码实现:

public int largestSumAfterKNegations(int[] A, int K) {
    Arrays.sort(A);
    int i = 0;
    while (K > 0 && i < A.length && A[i] < 0) {
        A[i] = -A[i];
        K--;
        i++;
    }
    int sum = 0;
    for (int j = 0; j < A.length; j++) {
        sum += A[j];
    }
    if (K % 2 == 1) {
        sum -= 2*A[0];
    }
    return sum;
}
    1. 加油站

题目描述:给定一个环形的公路上有 N 个加油站,第 i 个加油站的油量是 gas[i],从第 i 个加油站到第 i+1 个加油站需要消耗 cost[i] 的油量,求从哪个加油站出发可以绕一圈回到该加油站。

解题思路:根据题目要求,我们需要找到一个起点,从该起点出发可以绕一圈回到该起点。考虑使用贪心算法,我们可以从第一个加油站开始遍历,每次记录当前剩余的油量,如果当前油量不足以到达下一个加油站,就说明前面的所有加油站都不是起点,因为从这些加油站出发都无法绕一圈回到该起点。因此,我们可以将起点设为下一个加油站,同时将剩余油量清零,重新开始计算剩余油量。最终,如果剩余油量大于等于 0,说明存在一个起点可以绕一圈回到该起点。

代码实现:

public int canCompleteCircuit(int[] gas, int[] cost) {
    int n = gas.length;
    int start = 0;
    int sum = 0;
    int total = 0;
    for (int i = 0; i < n; i++) {
        sum += gas[i] - cost[i];
        total += gas[i] - cost[i];
        if (sum < 0) {
            start = i + 1;
            sum = 0;
        }
    }
    return total >= 0 ? start : -1;
}
    1. 分发糖果

题目描述:给定一个数组 ratings,其中 ratings[i] 表示第 i 个孩子的评分。现在你需要给这些孩子发糖果,每个孩子至少分配到一个糖果,相邻的孩子评分高的必须获得更多的糖果,问最少需要分配多少个糖果。

解题思路:根据题目要求,相邻的孩子评分高的必须获得更多的糖果,因此我们可以先将所有孩子的糖果数量都设为 1,然后从左往右遍历一遍数组,如果当前孩子的评分比前一个孩子高,就将其糖果数量设为前一个孩子的糖果数量加一。然后再从右往左遍历一遍数组,如果当前孩子的评分比后一个孩子高,就将其糖果数量设为后一个孩子的糖果数量加一。最终,所有孩子的糖果数量之和就是最少需要分配的糖果数量。

代码实现:

public int candy(int[] ratings) {
    int n = ratings.length;
    int[] candies = new int[n];
    Arrays.fill(candies, 1);
    for (int i = 1; i < n; i++) {
        if (ratings[i] > ratings[i-1]) {
            candies[i] = candies[i-1] + 1;
        }
    }
    for (int i = n-2; i >= 0; i--) {
        if (ratings[i] > ratings[i+1]) {
            candies[i] = Math.max(candies[i], candies[i+1] + 1);
        }
    }
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += candies[i];
    }
    return sum;
}

以上三道题目都是典型的使用贪心算法解决的问题,在实际应用中也有很多类似的问题可以使用贪心算法解决。需要注意的是,贪心算法通常只能得到局部最优解而不一定是全局最优解,因此在实际应用中需要仔细分析问题,判断贪心算法能否得到正确的解。

你可能感兴趣的:(刷题,算法,数据结构,leetcode)