Greedy in "Algorithm Series"

Introduction

  If the core of the backtracking algorithm is the backtracking template, then the core of the greedy algorithm is one sentence: local optimum, so as to achieve global optimum . The problem that can satisfy this sentence can be solved by greedy algorithm. In fact, the greedy algorithm does not have a fixed way of writing . In my opinion, the shadow of a certain template can be found in the questions of dynamic planning, but not greedy. There are various ways of writing. Just like Zhang Wuji learning Tai Chi, forgetting as he learns, remembering a word of heart, you can see the tricks, and there are tricks to win without tricks .

theoretical basis

  Greedy algorithm (greedy algorithm) means that when solving a problem, always make the best choice at present, and then you can get the answer to the problem. The greedy algorithm needs to fully explore the conditions in the topic, and there is no fixed pattern . Solving the greedy algorithm requires a certain amount of intuition and experience. The greedy algorithm does not get the overall optimal solution for all problems. Problems that can be solved using a greedy algorithm have a greedy choice property . The greedy choice property strictly requires a mathematical proof. The problems that can be solved using the greedy algorithm must have no aftereffect , that is, the previous process of a certain state will not affect the future state, but only related to the current state, that is, the global optimum can be deduced from the local optimum.
  Just like the previous introduction, there is no fixed writing method for the code implementation of the greedy algorithm. There are all kinds of writing methods in the questions I have done. If I have to say one, it should be used more often. Greedy algorithm questions are often difficult to think about , that is, we don't know that we should use greedy algorithms to do it, but it is generally not difficult to write . One thing to note here is that some questions cannot derive the global optimum from the local optimum. At this time, it is not suitable to use the greedy algorithm. We should not fall into the trap of the greedy algorithm . Exit in time and choose another solution.

Problem solving experience

  • The core of greedy algorithm: local optimum, so as to achieve global optimum.
  • The greedy algorithm can be used to satisfy the derivation of the global best quality from the local optimum.
  • The greedy algorithm writing method needs to fully explore the conditions in the topic, and there is no fixed pattern.
  • Because there are no fixed moves, greedy algorithm questions require certain intuition and experience.
  • Greedy algorithm questions are often difficult to think about, that is, we don't know that we should use greedy algorithms to solve problems, but the writing method is generally not difficult.
  • Local optimum does not necessarily lead to overall optimum, so don't fall into the trap of greedy algorithm.

algorithm topic

12. Integer to Roman Numeral

insert image description here
Topic analysis: Greedy algorithm to solve, choose a larger number each time.
code show as below:

/**
 * 贪心算法
 */
class Solution {
    int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
    String[] symbols = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};

    public String intToRoman(int num) {
        StringBuffer roman = new StringBuffer();
        // 从1000依次选择至1
        for (int i = 0; i < values.length; i++) {
            int value = values[i];
            String symbol = symbols[i];
            while (num >= value) {
                num -= value;
                roman.append(symbol);
            }
            if (num == 0) {
                break;
            }
        }
        return roman.toString();
    }
}

45. Jumping Game II

insert image description here
Topic analysis: This question needs to find the index of the longest position in the passing path, and use it as the next position to take off.
code show as below:

/**
 * 贪心算法
 */
class Solution {
    public int jump(int[] nums) {
        if (nums == null || nums.length == 0 || nums.length == 1) {
            return 0;
        }
        //记录跳跃的次数
        int count=0;
        //当前的覆盖最大区域
        int curDistance = 0;
        //最大的覆盖区域
        int maxDistance = 0;
        for (int i = 0; i < nums.length; i++) {
            //在可覆盖区域内更新最大的覆盖区域
            maxDistance = Math.max(maxDistance,i+nums[i]);
            //说明当前一步,再跳一步就到达了末尾
            if (maxDistance>=nums.length-1){
                count++;
                break;
            }
            //走到当前覆盖的最大区域时,更新下一步可达的最大区域
            if (i==curDistance){
                curDistance = maxDistance;
                count++;
            }
        }
        return count;
    }
} 

55. Jumping Game

insert image description here
Topic Analysis: Greedy algorithm, each step requires the largest number.
code show as below:

/**
 * 贪心算法
 */
class Solution {
    public boolean canJump(int[] nums) {
        int index = 0;
        while (true) {
            int temp = helper(nums, index);
            // 如果下标没变,说明己到最远处,结束循环
            if (index == temp) {
                break;
            } else {
                // 更新下标
                index = temp;
            }
        }

        if (index == nums.length - 1) {
            return true;
        } else {
            return false;
        }

    }

    // 选取每一步最大值的下标
    public int helper(int[] nums, int index) {
        int max = nums[index];
        int len = nums.length;
        for (int i = index; i < i + nums[index]; i++) {
            // 到底直接返回
            if (i == len - 1) {
                return i;
            }
            // 更新下标
            if (i + nums[i] >= index + max) {
                max = nums[i];
                index = i;
            }
        }
        return index;
    }
}

122. Best Time to Buy and Sell Stocks II

insert image description here
Topic Analysis: As long as the current day is bigger than the previous day, you can sell it. Note: According to the topic, you can buy it after selling it on the same day.
code show as below:

/**
 * 贪心算法
 */
class Solution {
    public int maxProfit(int[] prices) {
        int res = 0;
        for (int i = 1; i < prices.length; i++) {
            if (prices[i] > prices[i - 1]) {
                res += prices[i] - prices[i - 1];
            }
        }
        return res;
    }
}

134. Gas station

insert image description here
Topic analysis: Greedy algorithm, traverse each gas station from beginning to end, and check whether the gas station can be used as the starting point to drive for a week in the end.
code show as below:

/**
 * 贪心算法
 */
class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        // 剩余油量
        int total = 0;
        // 假设起始点
        int index = 0;
        // 从假设起始点的剩余油量之和
        int sum = 0;
        for (int i = 0; i < gas.length; i++) {
            int temp = gas[i] - cost[i];
            // 计算所有剩余油量
            total += temp;
            // 计算从假设起始点的剩余油量
            sum += temp;
            // 如果当前 sum 值为负数,则到目前为此的加油站点都不适合做起点
            if (sum < 0) {
                index = i + 1;
                sum = 0;
            }
        }
        // 如果gas[] < cost[] 总量,则一定不可行驶一周,直接返回 -1
        if (total < 0) {
            return -1;
        }
        return index;
    }
}

135. Handing out candy

insert image description here
Topic analysis: Two traversals, the first time from left to right, the left side is larger than the right side, and the number of candies on the right side is increased by 1. The second time from right to left, the right side is larger than the left side, and the left side chooses max (the number on the right + 1, the current number), because it does not say that the same score, the number of candies must be the same.
code show as below:

/**
 * 贪心算法 
 */
class Solution {

    public int candy(int[] ratings) {
        
        int[] candyVec = new int[ratings.length];
        candyVec[0] = 1;

        // 默认糖数都为1,从左往右遍历
        for (int i = 1; i < ratings.length; i++) {
            if (ratings[i] > ratings[i - 1]) {
                candyVec[i] = candyVec[i - 1] + 1;
            } else {
                candyVec[i] = 1;
            }
        }

        // 从右往左遍历
        for (int i = ratings.length - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1]) {
                candyVec[i] = Math.max(candyVec[i], candyVec[i + 1] + 1);
            }
        }

        int res = 0;
        for (int s : candyVec) {
            res += s;
        }
        return res;
    }
}

179. Maximum number

insert image description here
Topic Analysis: Customize a sorting method to compare s1 + s2 and s2 + s1.
code show as below:

/**
 * 贪心算法
 */
class Solution {
    public String largestNumber(int[] nums) {
        PriorityQueue<String> heap = new PriorityQueue<>((x, y) -> (y + x).compareTo(x + y));
        for(int x: nums) heap.offer(String.valueOf(x));
        String res = "";
        while(heap.size() > 0) res += heap.poll();
        if(res.charAt(0) == '0') return "0";
        return res;
    }
}

back to the homepage

Some feelings about brushing Leetcode 500+ questions

Next

Dynamic Programming of "Algorithm Series"

Guess you like

Origin blog.csdn.net/qq_22136439/article/details/126683850