Greedy Algorithm
Greedy algorithm (greedy algorithm) refers to the algorithm that takes the best or optimal (i.e. the most favorable) choice in each step when solving the problem, so as to lead to the best or optimal result
The results obtained by greedy algorithm are not necessarily the optimal results (sometimes the optimal solution), but they are relatively approximate (close) to the optimal solution
Greedy strategy: Generally speaking, the problems suitable for solving greedy strategy have the following characteristics: greedy selection property and optimal substructure property.
① greedy selection property: the global optimal solution of the problem can be achieved through local greedy selection. Using greedy strategy to solve problems generally requires many greedy choices step by step. After a greedy choice, the original problem will become a similar but smaller problem, and then each step is the seemingly best choice at present, and each choice is made only once.
② optimal substructure property: the optimal solution of the original problem includes the optimal solution of the subproblem, that is, the problem has the property of optimal substructure. In the knapsack problem, the first choice of goods with the largest unit mass is the optimal solution of the first sub problem, the second choice of goods with the largest unit weight value among the remaining goods is also the optimal solution of the second sub problem, and so on
Greedy algorithm usage scenario
When we see this kind of problem, we should first associate it with greedy algorithm: for a group of data, we define the limit value and expected value, and hope to select several data from them. When the limit value is met, the expected value is the largest
2. Let's try to see if this problem can be solved by greedy algorithm: each time, select the data that contributes the most to the expected value under the current situation and the same contribution to the limit value
3 whether the result of greedy algorithm is optimal.
Differences among dynamic programming, backtracking and greedy algorithms
The models of the three algorithms to solve problems can be abstracted into the multistage decisionmaking optimal solution model we are talking about today. Although most of the problems solved by divide and conquer algorithm are also optimal solution problems, most of them can not be abstracted into multistage decisionmaking models.
Backtracking algorithm is a "panacea". Basically, we can use backtracking algorithm to solve the problems that can be solved by dynamic programming and greed. Backtracking algorithm is equivalent to exhaustive search. All cases are enumerated, and then the optimal solution is obtained by comparison. However, the time complexity of backtracking algorithm is very high, which is exponential and can only be used to solve the problem of smallscale data. For the problem of largescale data, the execution efficiency of backtracking algorithm is very low. Although dynamic programming is more efficient than backtracking algorithm, not all problems can be solved by dynamic programming. The problem that can be solved by dynamic programming needs to meet three characteristics: optimal substructure, no aftereffect and repeated subproblem. On the point of repeated subproblem, the distinction between dynamic programming and divide and conquer algorithm is very obvious. Divide and conquer algorithm requires that the sub problems divided into cannot have repeated sub problems. On the contrary, dynamic programming is efficient because there are a large number of repeated sub problems in the implementation of backtracking algorithm. Greedy algorithm is actually a special case of dynamic programming algorithm. It is more efficient to solve problems, and the code implementation is more concise. However, it can solve more limited problems. The problems it can solve need to meet three conditions: optimal substructure, no aftereffect and greedy selectivity (we don't emphasize the repeated subproblem here). Among them, the optimal substructure and no aftereffect are the same as those in dynamic programming. "Greedy selectivity" means that the global optimal choice can be generated through the local optimal choice. At each stage, we choose the decision that seems to be the best at present. After the decision at all stages is completed, the global optimal solution is finally composed of these local optimal solutions.
Problems in greedy algorithm

1. There is no guarantee that the final solution obtained is the best;

2 can not be used to find the maximum or minimum solution;

3. We can only find the range of feasible solutions that meet some constraints
Greedy algorithm to solve the coin change problem
Coin change problem
Suppose there are C0, C1, C2, C3, C4, C5 and C6 notes for 1 yuan, 2 yuan, 5 yuan, 10 yuan, 20 yuan, 50 yuan and 100 yuan respectively. How many banknotes should I use to pay K yuan now?
The idea of greedy algorithm: use paper money with large face Value as much as possible at each step. We naturally do the same in our daily life. In the program, the values have been arranged from small to large in advance.
The code is simple
private static void getNum(int price , int[] values, int[] counts){ int [] nums = new int[counts.length]; for(int j = values.length1;j>= 0;j){ int c= Math.min(price/values[j],counts[j]); price = price  c*values[j]; nums[j] = c; } for (int i = 0; i < values.length; i++) { if (nums[i] != 0) { System.out.println("The denomination required is" + values[i] + "RMB" + nums[i] + "Zhang"); } } }
Separable knapsack problem
For the 01 knapsack problem, the reason why greedy selection can not get the optimal solution is that it can not guarantee that the knapsack can be filled in the end. Part of the idle knapsack space reduces the value of each kilogram of knapsack space
In fact, when considering the 01 knapsack problem, we should compare the final scheme caused by choosing the item and not choosing the item, and then make the best choice. Therefore, many overlapping subproblems are derived. This is another important feature that the problem can be solved by dynamic programming algorithm.
However, the problem of detachable knapsack can be solved by greedy algorithm. We just choose to load items, and split them if we can't load them
 Calculate the value per unit weight of each item
 Pack as many items with the highest value per unit weight as possible into the backpack.
 If the total weight of the items in the backpack does not exceed the upper limit of the backpack after all such items are loaded into the backpack, select the items with the second highest value per unit weight and load as many items into the backpack as possible.
 Follow this strategy until the backpack is full.
private static void knapsack(float[] goodsWeight, float[] goodValues, int knapsackMaxWeight) { float[] goodsX = new float[goodsWeight.length]; Arrays.sort(goodsWeight); int weight = knapsackMaxWeight; float allPrice = 0; int i = 0; for (; i < goodsWeight.length; i++) { if (goodsWeight[i] <= weight) { goodsX[i] = 1; weight = goodsWeight[i]; allPrice += goodValues[i]; } else break; } //If it can be loaded, but not the whole load if (i < goodsWeight.length) { goodsX[i] = weight / goodsWeight[i]; //At this time, goodsX[i] is followed by goodsX[i] above allPrice = goodsX[i] * goodValues[i]; } for (i = 0; i < goodsWeight.length; i++) { if (goodsX[i] < 1) { break; } else { System.out.println("The loaded weight is:" + goodsWeight[i] + "\t The value is:" + goodValues[i]); } } if (goodsX[i] > 0 && goodsX[i] < 1) { //It can be loaded, but not the whole System.out.println("The loaded weight is:" + goodsX[i] * goodsWeight[i] + "\t The benefits are:" + goodValues[i] * goodsX[i] + "It's the original" + goodsX[i]); } System.out.println("Total loading weight" + knapsackMaxWeight + "\t The total revenue is" + allPrice); }
Radio coverage problem
It is assumed that there are broadcasting stations that need to pay and areas that can be covered by broadcasting station signals in the following table. How to select the least number of broadcasting stations so that all regions can receive signals
Radio station Coverage area K1 "Beijing", "Shanghai", "Tianjin" K2 "Guangzhou", "Beijing", "Shenzhen" K3 "Chengdu", "Shanghai", "Hangzhou" K4 "Shanghai", "Tianjin" K5 "Hangzhou", "Dalian"
Analysis using greedy algorithm:
1 find the maximum coverage area, that is, remove the duplicate and put it into the coverage set
2 traverse the coverage set (as long as it is not empty), solve the intersection between the coverage area of each radio station and the coverage set, and put it into the radiosNum map, where key is the number of radio stations and value is the number of coverage areas
3. According to the greedy strategy, select the radio station number with the maximum number of coverage areas from the radiosNum and put it into the result set, remove the selected radio station from the radiosNum and delete all the coverage areas of the selected radio station from the coverage
4 repeat 2  3 until the coverage set is empty
private static ArrayList<String> minimumRadioCoverage (HashMap<String, HashSet<String>> radiosMap){ HashSet<String> coverage = new HashSet<>(); HashMap<String,Integer> radiosNum = new HashMap<>(); radiosMap.forEach((key,value)> coverage.addAll(value)); ArrayList<String> result = new ArrayList<>(); while (!coverage.isEmpty()){ radiosMap.forEach((key,value)>{ value.retainAll(coverage); radiosNum.put(key, value.size());//Put the number of covered stations and areas into the collection }); //The idea of greedy algorithm selects the largest radio coverage area each time Optional<Map.Entry<String, Integer>> maxRadios = radiosNum.entrySet().stream().max(Comparator.comparingInt(Map.Entry::getValue)).stream().findFirst(); if (maxRadios.isPresent()) { String key = maxRadios.get().getKey(); result.add(key); radiosNum.remove(key); coverage.removeAll(radiosMap.remove(key)); } } return result; }