贪心算法学习过程合集

172 阅读2分钟

知识结构及部分解题思路来自代码随想录。

作者网站: 代码随想录

简单

455. 分发饼干

int findContentChildren(vector<int>& g, vector<int>& s) {
        /*按小孩分 大饼干先满足大胃口*/
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        int index = s.size()-1;
        int res = 0;
        for(int i = g.size()-1; i >= 0; i--)
        {
            if(index >= 0 && s[index] >= g[i])
            {
                res++;
                index--;
            }
        }
        return res;

        /*按饼干分,小饼干先分给小胃口*/
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        int index = 0;
        int count = 0;
        for(int i = 0; i < s.size(); i++)
        {
            if(index < g.size() && g[index] <= s[i])
            {
                count++;
                index++;
            }
        }
        return count;
    }

409. 最长回文串

int longestPalindrome(string s) {
        if(!s.size()) return 0;
        unordered_map<char,int> um;
        for(char ch:s){
            um[ch]++;
        }
        int ans = 0;
        for(auto it = um.begin(); it != um.end(); it++)
        {
            int step =  it->second;
            ans += step / 2 * 2;
            if(step % 2 == 1 && ans % 2 == 0) ans++;
        }
        return ans;
    }

key point

  1. 注意题目中是“构成”不是“查找”

  2. 当出现频率为奇数,比如说9时,可以选择8个字母加入序列。整数除法有向下取整的作用

  3. 只对第一个奇数操作: if(step % 2 ==1 && ans % 2 == 0),当ans为奇数时,加任意偶数都不会变成偶数

561. 数组拆分 I

int arrayPairSum(vector<int>& nums) {
       sort(nums.begin(),nums.end());
       int res = 0;
       for(int i = nums.size() -1 ; i >= 0; i -= 2)
       {
           res += min(nums[i], nums[i-1]);
       }
       return res;
   }

605. 种花问题

bool canPlaceFlowers(vector<int>& flowerbed, int n) {
        for(auto i = 0; i < flowerbed.size(); i += 2){
            if(flowerbed[i] == 0){
                if(i == flowerbed.size()-1 || flowerbed[i+1] == 0) n--;
                // 两个条件不能前后置换,否则会出现数组越界报错
                else i++;
            }
        }
        return n <= 0;
    }

key point

  1. 跳格子法

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

    /*from big to little*/
    static bool cmp(int a, int b){
        return abs(a) > abs(b);
    }
    int largestSumAfterKNegations(vector<int>& nums, int k) {
        sort(nums.begin(),nums.end(),cmp);
        for(int i = 0; i < nums.size(); i++){
            if(nums[i] < 0 && k > 0){
                k--;
                nums[i] *= -1;
            }
        }
        if(k % 2 == 1) nums[nums.size()-1] *= -1;

        int res = 0;
        for(int i:nums) res += i;
        return res;
    }

key point

  1. static bool cmp:定义sort()函数的固定搭配

  2. for(int i : nums) nums[nums.size()-1] *= -1for(int i:nums)i不是下标,是数值

  3. 同一数字翻转两次为原来数值,因此,只有k为奇数时才会改变数组值

860. 柠檬水找零

bool lemonadeChange(vector<int>& bills) {
        int five = 0, ten = 0, twenty = 0;
        for(int pay : bills){
            if(pay == 5) five++;
            else if(pay == 10){
                ten++;
                if(five) five--;
                else return false;
            }
            else if(pay == 20){
                twenty++;
                if(ten){
                    ten--;
                    if(five) five--;
                    else return false;
                }
                else{
                    if(five >= 3){
                        five = five -3;
                    }
                    else return false;
                }
            }
        }
        return true;
    }

key point

  1. 找零20时优先考虑找10+5

976. 三角形的最大周长

int largestPerimeter(vector<int>& nums) {
        /*三角形边长关系: a+b>c
          =>满足该关系的能构成三角形
          =>三角形面积一定不为0
        */
        sort(nums.begin(), nums.end());
        for(int i = nums.size()-1; i >= 2; i--){
            if(nums[i] < nums[i-1] + nums[i-2]) return nums[i] + nums[i-1] + nums[i-2];
        }
        return 0;
    }

中等

376. 摆动序列

序列问题

股票问题

两个维度权衡问题