Greedy Algorithm + Dynamic Programming|Different perspectives determine different depths

This article is participating in the "Golden Stone Project. Share 60,000 cash prize"

foreword

  • When I go to university, there will be a course called "Algorithm and Practice", and it will feel so cool if the algorithm is paired with C++it . In retrospect, algorithms are not limited to languages, but the syntax of each language is different, but the internal logic of the algorithm is the same. Today we use three cases to understand and analyze one of the algorithms [Greedy Algorithm].

Introduction

  • A greedy algorithm means that a local optimal solution can always be achieved. What do you mean? That is to say, the optimal solution is selected in each step of the scene, regardless of whether the global optimal solution can be achieved.
  • Greedy algorithms and dynamic programming have many similarities. The problem to which the greedy algorithm is applicable is also the optimal substructure. There is a significant difference between greedy algorithm and dynamic programming, that is, in greedy algorithm, the optimal substructure is used in a top-down manner. The greedy algorithm will make a choice first, which seems to be the optimal choice at the time, and then solve a result subproblem, instead of finding the optimal solution of the subproblem first, and then make a choice.
  • Next, let's experience the动态规划 difference between , and , through different scenarios. 贪心算法So as to have a deeper understanding of 贪心what is it? Why greed can only be achieved 局部最优解.

Scenes

change exchange

topic description

 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。
 ​
 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。
 ​
 你可以认为每种硬币的数量是无限的。
复制代码
  • The translation is: Suppose there are 1 yuan, 2 yuan, 5 yuan, 10 yuan, 20 yuan, 50 yuan, and 100 yuan respectively c0, c1, c2, c3, c4, c5, c6. Now to use these money to pay K yuan, at least how much change should be exchanged.

problem solving ideas

  • It is not difficult to find the best solution to this problem 动态规划. For a given array composing K elements since the elements in the array. S(K-1)=1+min(S(ki)).

image-20221115211416720.png

Example 1: Suppose

coins = [1, 2, 5], amount = 11, then, when i==0i==0 cannot be composed with coins, it is 0. When i<0i<0, ignore F(i)F(i)

F(i) 最小硬币数量 F(0) 0 //金额为0不能由硬币组成 F(1) 1 //F(1)=min(F(1-1),F(1-2),F(1-5))+1=1F(1)=min(F(1−1),F(1−2),F(1−5))+1=1 F(2) 1 //F(2)=min(F(2-1),F(2-2),F(2-5))+1=1F(2)=min(F(2−1),F(2−2),F(2−5))+1=1 F(3) 2 //F(3)=min(F(3-1),F(3-2),F(3-5))+1=2F(3)=min(F(3−1),F(3−2),F(3−5))+1=2 F(4) 2 //F(4)=min(F(4-1),F(4-2),F(4-5))+1=2F(4)=min(F(4−1),F(4−2),F(4−5))+1=2 ... ... F(11) 3 //F(11)=min(F(11-1),F(11-2),F(11-5))+1=3F(11)=min(F(11−1),F(11−2),F(11−5))+1=3 我们可以看到问题的答案是通过子问题的最优解得到的。

AC代码

 public class Solution {
     public int coinChange(int[] coins, int amount) {
         int max = amount + 1;
         int[] dp = new int[amount + 1];
         Arrays.fill(dp, max);
         dp[0] = 0;
         for (int i = 1; i <= amount; i++) {
             for (int j = 0; j < coins.length; j++) {
                 if (coins[j] <= i) {
                     dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
                 }
             }
         }
         return dp[amount] > amount ? -1 : dp[amount];
     }
 }
复制代码

玩筹码

题目描述

 有 n 个筹码。第 i 个筹码的位置是 position[i] 。
 ​
 我们需要把所有筹码移到同一个位置。在一步中,我们可以将第 i 个筹码的位置从 position[i] 改变为:
 ​
 position[i] + 2 或 position[i] - 2 ,此时 cost = 0
 position[i] + 1 或 position[i] - 1 ,此时 cost = 1
 返回将所有筹码移动到同一位置上所需要的 最小代价 。
复制代码

image-20221115162933576.png

解题思路

  • 所谓算法其实也是前人总结出来的经验罢了。初看毫无头绪,再看仍无头绪这就是算法的魅力,当我们知道此题可以通过 贪心 来解决时就有了头绪了。

  • 首先通过题目描述我们能够得处一下结论:

    • 每次仅能移动一个筹码
    • 每次移动范围介于1~2之间
    • 移动2步长,无代价
    • 移动1步长,则付出1代价
  • 移动2步无需付出代价,意味着我们可以将筹码分成两组,组内成员所在位置索引差值皆为 2 。最终只需要考虑哪组需要合并即可。

image-20221115163927066.png

  • 因为移动两步时无需代价的,则按照上面分组后,组内合并则是无需付出代价的。合并后如下

image-20221115164121666.png

  • At this point we only need to Aconsider whether the group moves to the Bgroup or the Bgroup moves to the Agroup. The basis for this judgment is to see which of the two groups has the smallest number. Because we also have a limitation that only one chip can be moved at a time. So a group with a small number moves to a group with a large number. In other words, the number of a group with a small number is the overall moving cost.

AC code

 class Solution {
     public int minCostToMoveChips(int[] position) {
         int even = 0, odd = 0;
         for (int pos : position) {
             if ((pos & 1) != 0) {
                 odd++;
             } else {
                 even++;
             }
         }
         return Math.min(odd, even);
     }
 }
复制代码

upgrade extension

  • The above can already meet the needs. But as an enterprise developing for so many years, I have already become accustomed to reserved extension functions. After joining, we introduce a new strategy and move the three-step cost. At this time, we can modify the code like this
 ​
 public int minCostToMoveChips(int[] position) {
         int step = 2;
         int[] stepArr = new int[step];
         for (int pos : position) {
             int posIndex=pos%step;
             stepArr[posIndex]++;
         }
         int min = stepArr[0];
         for (int i = 1; i < stepArr.length; i++) {
             if (min > stepArr[i]) {
                 min = stepArr[i];
             }
         }
         return min;
     }
复制代码

image-20221115165216674.png

boxing

topic description

 请你将一些箱子装在 一辆卡车 上。给你一个二维数组 boxTypes ,其中 boxTypes[i] = [numberOfBoxesi, numberOfUnitsPerBoxi] :
 ​
 numberOfBoxesi 是类型 i 的箱子的数量。
 numberOfUnitsPerBoxi 是类型 i 每个箱子可以装载的单元数量。
 整数 truckSize 表示卡车上可以装载 箱子 的 最大数量 。只要箱子数量不超过 truckSize ,你就可以选择任意箱子装到卡车上。
 ​
 返回卡车可以装载 单元 的 最大 总数。
 ​
复制代码

problem solving ideas

  • 玩筹码The game can be said to be cleverly implemented using greedy, maybe we have not fully realized the role of greedy algorithm. And 装箱子is the idea of ​​a thorough greedy algorithm. 零钱兑换What I use is 动态规划that he is characterized by a bottom-up process. Upstream results depend on downstream results.
  • The 贪心算法middle is 自上而下, for example, in this question, we assume that Fx represents the maximum capacity after the car is filled with X boxes. Obviously we only need to choose the largest capacity among the remaining boxes every time.
  • It can also be seen from the selection strategy of the two that the greedy algorithm is only a local optimal solution. rather than the global optimal solution.

AC code

 class Solution {
     public int maximumUnits(int[][] boxTypes, int truckSize) {
         Arrays.sort(boxTypes, (a, b) -> b[1] - a[1]);
         int res = 0;
         for (int[] boxType : boxTypes) {
             int numberOfBoxes = boxType[0];
             int numberOfUnitsPerBox = boxType[1];
             if (numberOfBoxes < truckSize) {
                 res += numberOfBoxes * numberOfUnitsPerBox;
                 truckSize -= numberOfBoxes;
             } else {
                 res += truckSize * numberOfUnitsPerBox;
                 break;
             }
         }
         return res;
     }
 }
复制代码

Summarize

1. It cannot be guaranteed that the final solution obtained is the best 2. It cannot be used to find the maximum or minimum value 3. Only the range of feasible solutions that satisfy certain constraints can be found

This article is participating in the "Golden Stone Project. Share 60,000 cash prize"

Guess you like

Origin juejin.im/post/7166803488096124958