1. 455. 分发饼干

  1. class Solution {
  2. public:
  3. int findContentChildren(vector<int>& g, vector<int>& s) {
  4. //先排序
  5. sort(g.begin(),g.end());
  6. sort(s.begin(),s.end());
  7. //遍历s的index,饼干数组的下标
  8. int index=s.size()-1;
  9. //喂饱的小孩数
  10. int result=0;
  11. //大饼干喂给胃口大的-->局部最优
  12. for(int i=g.size()-1;i>=0;i--){
  13. //先判断index, 否则若index==0,则 s[index]越界报错
  14. if(index >= 0 && s[index] >= g[i]){
  15. result++;
  16. index--;
  17. }
  18. }
  19. return result;
  20. }
  21. };

2. 376. 摆动序列

  1. //贪心算法
  2. class Solution {
  3. public:
  4. int wiggleMaxLength(vector<int>& nums) {
  5. int n=nums.size();
  6. if(n<=1){
  7. return n;
  8. }
  9. //记录前一差值
  10. int preDiff=0;
  11. //记录当前差值
  12. int curDiff=0;
  13. // 记录峰值个数,序列默认序列最右边有一个峰值
  14. int result=1;
  15. for(int i=0;i<n-1;i++){
  16. curDiff=nums[i+1]-nums[i];
  17. //出现峰值
  18. if(( preDiff>=0 && curDiff<0 ) ||( preDiff<=0 && curDiff>0 ) ){
  19. result++;
  20. preDiff=curDiff;
  21. }
  22. }
  23. return result;
  24. }
  25. };
  26. //动态规划
  27. class Solution {
  28. public:
  29. int wiggleMaxLength(vector<int>& nums) {
  30. int n=nums.size();
  31. //status and define dp[][0]代表山峰,dp[][1]为山谷。
  32. vector<vector<int>> dp(n,vector<int>(2));
  33. if(n<2){
  34. return n;
  35. }
  36. //base case
  37. dp[0][0]=1;
  38. dp[0][1]=1;
  39. //transform
  40. for(int i=1;i<n;i++){
  41. dp[i][0]=1;
  42. dp[i][1]=1;
  43. //找山峰
  44. for(int j=0;j<i;j++){
  45. if(nums[i]>nums[j]){
  46. dp[i][0]=max(dp[j][1]+1,dp[i][0]);
  47. }
  48. }
  49. //找山谷
  50. for(int j=0;j<i;j++){
  51. if(nums[i]<nums[j]){
  52. dp[i][1]=max(dp[j][0]+1,dp[i][1]);
  53. }
  54. }
  55. }
  56. return max(dp[n-1][0],dp[n-1][1]);
  57. }
  58. };
  59. //另一种动态规划
  60. class Solution {
  61. public:
  62. int wiggleMaxLength(vector<int>& nums) {
  63. int n=nums.size();
  64. //status and define dp_up[]代表最后一个为上升的最长序列长度,dp_down[]为最后一个为下降的最长序列长度。
  65. vector<int> dp_up(n),dp_down(n);
  66. if(n<2){
  67. return n;
  68. }
  69. //base case
  70. dp_up[0]=1;
  71. dp_down[0]=1;
  72. //transform
  73. for(int i=1;i<n;i++){
  74. if(nums[i]>nums[i-1]){
  75. dp_up[i]=dp_up[i-1];
  76. dp_down[i]=max(dp_down[i-1],dp_up[i-1]+1);
  77. }else if(nums[i]<nums[i-1]){
  78. dp_up[i]=max(dp_up[i-1],dp_down[i-1]+1);
  79. dp_down[i]=dp_down[i-1];
  80. }else{
  81. dp_up[i]=dp_up[i-1];
  82. dp_down[i]=dp_down[i-1];
  83. }
  84. }
  85. return max(dp_up[n-1],dp_down[n-1]);
  86. }
  87. };
  88. //另一种动态规划的优化
  89. class Solution {
  90. public:
  91. int wiggleMaxLength(vector<int>& nums) {
  92. int n=nums.size();
  93. //status and define dp_up[]代表最后一个为上升的最长序列长度,dp_down[]为最后一个为下降的最长序列长度。
  94. if(n<2){
  95. return n;
  96. }
  97. //base case
  98. int dp_up=1;
  99. int dp_down=1;
  100. //transform
  101. for(int i=1;i<n;i++){
  102. if(nums[i]>nums[i-1]){
  103. // dp_up[i]=dp_up[i-1];
  104. // dp_up=dp_up;
  105. // dp_down[i]=max(dp_down[i-1],dp_up[i-1]+1);
  106. dp_down=max(dp_down,dp_up+1);
  107. }else if(nums[i]<nums[i-1]){
  108. // dp_up[i]=max(dp_up[i-1],dp_down[i-1]+1);
  109. dp_up=max(dp_up,dp_down+1);
  110. // dp_down=dp_down;
  111. // dp_down[i]=dp_down[i-1];
  112. }else{
  113. // dp_up[i]=dp_up[i-1];
  114. // dp_down[i]=dp_down[i-1];
  115. }
  116. }
  117. return max(dp_up,dp_down);
  118. }
  119. };

3. 53. 最大子数组和

  1. class Solution {
  2. public:
  3. int maxSubArray(vector<int>& nums) {
  4. int n=nums.size();
  5. int result=0; //记录累计结果
  6. int m_max=INT_MIN; //最大和
  7. for(int i=0;i<n;i++){
  8. result+=nums[i];
  9. if(m_max<result){
  10. m_max=result;
  11. }
  12. if(result<=0){ //结果为负数 重新计数
  13. result=0;
  14. }
  15. }
  16. return m_max;
  17. }
  18. };

4. 122. 买卖股票的最佳时机 II

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int result=0;
        //局部最优,每天的利润最大化
        for(int i=1;i<prices.size();i++){
            result+=max(prices[i]-prices[i-1],0);
        }
        return result;
    }
};

5. 55. 跳跃游戏

class Solution {
public:
    bool canJump(vector<int>& nums) {
        //跳跃可覆盖的最大距离到终点时为整体最优,每个位置跳跃最大距离为局部最优
        int cover=0;  //当前下标

        //只有1个元素时,肯定可达
        if(nums.size()==1){
            return true;
        }
        for(int i=0;i<=cover;i++){
            //max(此位置上可覆盖的最大距离,之前的cover)
            cover=max(nums[i]+i,cover);
            //可以覆盖
            if(cover>=nums.size()-1){
                return true;
            }
        }
        return false;
    }
};

6. 45. 跳跃游戏 II

class Solution {
public:
    int jump(vector<int>& nums) {
        //局部最优:每次走最远
        if(nums.size()==1){
            return 0;
        }

        int step=0;
        for(int i=0;i<nums.size();i++){

            //在此位置最大覆盖距离可以到达最后一个位置
            if(i+nums[i]>=nums.size()-1){
                step++;
                return step;
            }
            //不能到达时
            //记录每个元素跳跃后可再次可跳跃的最大位置
            int pos_max=0;
            //记录此次跳跃步数下标
            int pos=i+1;
            for(int j=i+1;j<i+1+nums[i];j++){
                //找跳跃到下一个格子的最大距离
                if(j+nums[j]>=pos_max){
                    pos_max=j+nums[j];
                    //下标减1
                    pos=j-1;
                }
            }
            i=pos;
            step++;
        }
        return step;
    }
};

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

class Solution {
public:
    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(k>0&&nums[i]<0){
                nums[i]=-nums[i];
                k--;
            }
        }
        //K还没用完,反复转换最后一个负数
        if(k%2==1) nums[nums.size()-1]*=-1;
        return accumulate(nums.begin(),nums.end(),0);
    }
};

8. 134. 加油站

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        //先看总油量和总耗量
        int sum=0;
        //油箱剩余的油最小值
        int min_rest=INT_MAX;

        for(int i=0;i<gas.size();i++){
            sum+=gas[i]-cost[i];
            min_rest=min(sum,min_rest);
        }
        //总油量<总耗量,不可能跑完
        if(sum<0){
            return -1;
        }
        //油箱剩余的油每次都够,从0出发就可以
        if(min_rest>=0){
            return 0;
        }
        //都不行,那就先找油,找最先让油箱有min_rest的油,要从后往前找
        for(int i=gas.size()-1;i>=0;i--){
            min_rest+=gas[i]-cost[i];
            if(min_rest>=0){
                return i;
            }
        }
        return -1;
    }
};

//第二种贪心
//局部最优:当前累加rest[j]的和curSum一旦小于0,起始位置至少要是j+1,因为从j开始一定不行。
//全局最优:找到可以跑一圈的起始位置。

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int start=0;
        int today_sum=0;
        int sum=0;
        for(int i=0;i<gas.size();i++){
            today_sum+=gas[i]-cost[i];
            sum+=gas[i]-cost[i];
            //第i天出现负油量,重新开始计算,从i+1开始
            if(today_sum<0){
                start=i+1;
                today_sum=0;
            }
        }
        if(sum<0){
            return -1;
        }
        return start;
    }
};

9. 738. 单调递增的数字

class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        string strNum=to_string(n);
        int flag=strNum.size();
        for(int i=strNum.size()-1;i>0;i--){
            if(strNum[i]<strNum[i-1]){
                strNum[i-1]--;
                flag=i;
            }
        }   
        for(int i=flag;i<strNum.size();i++){
            strNum[i]='9';
        }
        return stoi(strNum);

    }
};