• 贪心法


    拆解为子问题最优

    局部最优导致全局最优

    严格证明可行:数学归纳法,反证法证明贪心可行,一般举反例就行

     排序!!!

    举简单例子,看看怎么解,能不能推导出一般解法,也就是局部推整体

    455. 分发饼干 - 力扣(LeetCode) (leetcode-cn.com)

     1 class Solution {
     2 public:
     3     int findContentChildren(vector<int>& g, vector<int>& s) {
     4         sort(g.begin(),g.end());
     5         sort(s.begin(),s.end());
     6         int num = 0;
     7         for(int i=0,j=0;i<g.size()&&j<s.size();i++,j++){
     8             if(g[i]<=s[j])
     9                 num++;
    10             else 
    11                 i--;
    12         }
    13         return num;
    14     }
    15 };
    View Code

     376. 摆动序列 - 力扣(LeetCode) (leetcode-cn.com)

     1 class Solution {
     2 public:
     3     int wiggleMaxLength(vector<int>& nums) {//初始化难
     4         if(nums.size()==0)
     5             return 0;
     6         if(nums.size()==1)
     7             return 1;
     8         int startIndex = 0;
     9         int temp = nums[startIndex]-nums[startIndex+1];
    10         while(temp==0&&startIndex+1+1<nums.size()){//找到第一个不为0的差值
    11             startIndex++;
    12             temp = nums[startIndex]-nums[startIndex+1];
    13         }
    14         int num = 1;
    15         temp*=-1;//自己造一个temp,找到第一个不为0的差值,取他相反数
    16         for(int i=startIndex;i+1<nums.size();i++){
    17             if(temp*( nums[i]-nums[i+1])>=0)//逻辑前后就是乘机应当<0
    18                 continue;
    19             temp =  nums[i]-nums[i+1];
    20             num++;
    21 
    22         }
    23         return  num;
    24     }
    25 };
    View Code

     53. 最大子数组和 - 力扣(LeetCode) (leetcode-cn.com)

     1 class Solution {
     2 public:
     3     int maxSubArray(vector<int>& nums) {
     4         int sum = 0,ans = -1e4;
     5         for(int i=0;i<nums.size();i++){
     6             sum+=nums[i];
     7             ans = max(ans,sum);
     8             if(sum<0)
     9                 sum = 0;
    10         }
    11         return ans;
    12     }
    13 };
    View Code

     122. 买卖股票的最佳时机 II - 力扣(LeetCode) (leetcode-cn.com)

     1 class Solution {
     2 public:
     3     int maxProfit(vector<int>& prices) {//示例一二,共同计算方法,第二天卖就行
     4         int ans = 0;
     5         for(int i=1;i<prices.size();i++){
     6             if(prices[i]-prices[i-1]>0)
     7                 ans+=prices[i]-prices[i-1];
     8         }
     9         return ans;
    10     }
    11 };
    View Code

     55. 跳跃游戏 - 力扣(LeetCode) (leetcode-cn.com)

     1 class Solution {
     2 public:
     3     bool canJump(vector<int>& nums) {
     4         int mx = 0;
     5         for(int i=0;i<nums.size()&&i<=mx;i++){
     6              mx = max(mx,nums[i]+i);
     7         }
     8         if(mx>=nums.size()-1)
     9             return true;
    10         return false;
    11     }
    12 };
    View Code

     45. 跳跃游戏 II - 力扣(LeetCode) (leetcode-cn.com)

     1 class Solution {
     2 public:
     3     int jump(vector<int>& nums) {
     4         int mx = 0,mxx = 0;
     5         int ans = 0;
     6         for(int i=0;i<nums.size()&&mx<nums.size()-1;i++){//位置下标
     7             for(;i<=mx&&mx<nums.size()-1;i++){
     8                 if(mxx<i+nums[i]){
     9                     mxx = max(mxx,i + nums[i]);
    10                 }
    11             }
    12             if(mx<=mxx){
    13                 mx = mxx;
    14                 ans++;
    15             }
    16         }
    17         return ans;
    18     }
    19 };
    View Code

     134. 加油站 - 力扣(LeetCode) (leetcode-cn.com)

    我自己的想法,类似最大连续区间和

    **其实我不认为这种方式是贪心算法,因为没有找出局部最优,而是直接从全局最优的角度上思考问题**。

    但这种解法又说不出是什么方法,这就是一个从全局角度选取最优解的模拟操作。

     1 class Solution {
     2 public:
     3     int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
     4         int n = cost.size(),nums[100000] = {0};//差值数组
     5         int startindex=-1;//初始化,用于第一位就是大于0,往后sum一直大于0,那么最大连续区间和前一位就是-1
     6         for(int i=0;i<cost.size();i++){
     7            nums[i] = gas[i]-cost[i];
     8         }
     9         int sum = 0;
    10         for(int i=0;i<n;i++){//类似连续区间和最大,找到起始坐标的前一位很快,+1就是起始
    11             sum+=nums[i];
    12             if(sum<0){
    13                 sum = 0;
    14                 startindex = i;
    15             }
    16         }
    17         //找到起始位置后还得验证是不是能走完
    18         sum=0;
    19         int size = 0;//结束for循环用
    20         for(int i=startindex+1;size<n;i++){
    21             sum+=nums[i%n];
    22             if(sum<0){
    23                 return -1;
    24             }
    25             size++;
    26         }
    27         return startindex+1;
    28     }
    29 };
    View Code

     贪心答案

     1 class Solution {
     2 public:
     3     int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
     4         int curSum = 0;
     5         int totalSum = 0;
     6         int start = 0;
     7         for (int i = 0; i < gas.size(); i++) {
     8             curSum += gas[i] - cost[i];
     9             totalSum += gas[i] - cost[i];
    10             if (curSum < 0) {   // 当前累加rest[i]和 curSum一旦小于0
    11                 start = i + 1;  // 起始位置更新为i+1
    12                 curSum = 0;     // curSum从0开始
    13             }
    14         }
    15         if (totalSum < 0) return -1; // 说明怎么走都不可能跑一圈了
    16         return start;
    17     }
    18 };
    View Code

     135. 分发糖果 - 力扣(LeetCode) (leetcode-cn.com)

     1 class Solution {
     2 public:
     3     int candy(vector<int>& ratings) {
     4         vector<int>ans(20000,1);
     5         int sum = 0;
     6         for(int i=0;i<ratings.size();i++){
     7             if(i-1>=0&&ratings[i]>ratings[i-1]){
     8                 ans[i] = max(ans[i],ans[i-1]+1);
     9             }
    10         }
    11         for(int i=ratings.size()-1;i>=0;i--){
    12             if(i+1<ratings.size()&&ratings[i]>ratings[i+1]){
    13                 ans[i] = max(ans[i],ans[i+1]+1);
    14             }
    15         }
    16         for(int i=0;i<ratings.size();i++)
    17             sum+=ans[i];
    18         return sum;
    19     }
    20 };
    View Code

     860. 柠檬水找零 - 力扣(LeetCode) (leetcode-cn.com)

     1 class Solution {
     2 public:
     3     bool lemonadeChange(vector<int>& bills) {
     4         vector<int> a(21,0);
     5         for(int i=0;i<bills.size();i++){
     6             if(bills[i]==5)
     7                 a[5]++;
     8             else if(bills[i]==10){
     9                 if(a[5]==0)
    10                     return false;
    11                 a[5]--;
    12                 a[10]++;
    13             }else if(bills[i]==20){
    14                 if(a[10]>=1&&a[5]>=1){
    15                     a[10]--;
    16                     a[5]--;
    17                     a[20]++;
    18                 }else if(a[5]>=3){
    19                     a[5]-=3;
    20                     a[20]++;
    21                 }else
    22                     return false;
    23             }
    24                 
    25         }
    26         return true;
    27     }
    28 };
    View Code

     452. 用最少数量的箭引爆气球 - 力扣(LeetCode) (leetcode-cn.com)

     1 class Solution {// static bool cmp(const vector<int>& a, const vector<int>& b) {return a[0] < b[0]; }
     2 public:
     3     int findMinArrowShots(vector<vector<int>>& points) {//思路混乱,化整体为局部,就看第一个先。无序的一定排序看看
     4         sort(points.begin(),points.end());//排序啊我是傻逼
     5         int ans = 0;
     6         long long end = -2147489999;
     7         for(int i=0;i<points.size();i++){
     8             if(end>=points[i][0]){
     9                 end = min(end,(long long)points[i][1]);
    10             }else {
    11                 end = points[i][1];
    12                 ans++;
    13             }
    14         }
    15         return ans;
    16     }
    17 };
    View Code

     56. 合并区间 - 力扣(LeetCode) (leetcode-cn.com)

     1 class Solution {
     2 public:
     3     vector<vector<int>> merge(vector<vector<int>>& intervals) {
     4         vector<vector<int>> ans;
     5         vector<int> path(2);//老忘记加大小
     6         if(intervals.size()==0)
     7             return ans;
     8         sort(intervals.begin(),intervals.end());
     9         path[0] = intervals[0][0];
    10         path[1] = intervals[0][1];
    11         for(int i=1;i<intervals.size();i++){
    12             if(path[1]>=intervals[i][0]){
    13                 path[1] = max(path[1],intervals[i][1]);
    14             }else{
    15                 ans.push_back(path);
    16                 path[0] = intervals[i][0];
    17                 path[1] = intervals[i][1];
    18             }
    19         }
    20         ans.push_back(path);
    21         return ans;
    22     }
    23 };
    View Code

     738. 单调递增的数字 - 力扣(LeetCode) (leetcode-cn.com)

     1 class Solution {
     2 public:
     3     int monotoneIncreasingDigits(int n) {
     4         string strNum = to_string(n);
     5         int startIndex = strNum.size();
     6         for(int i = strNum.size()-1;i>0;i--){
     7             if(strNum[i-1]>strNum[i]){
     8                 strNum[i-1]--;
     9                 startIndex = i;
    10             }
    11         }
    12         for(int i=startIndex;i<strNum.size();i++){
    13             strNum[i] = '9';
    14         }
    15         return stoi(strNum);
    16     }
    17 };
    View Code
  • 相关阅读:
    [USACO08FEB]酒店Hotel 线段树 BZOJ 1593
    有趣的数 zoj 月赛
    [ZJOI2008]生日聚会 BZOJ1037 dp
    借教室 差分+二分答案
    HackerRank
    旅行计划 记忆化搜索
    灾后重建 Floyd
    [USACO10OCT]湖计数Lake Counting 联通块
    [TJOI2013]循环格 费用流 BZOJ3171
    高斯消元
  • 原文地址:https://www.cnblogs.com/hcl6/p/15864132.html
Copyright © 2020-2023  润新知