【leetcode刷题】贪心算法-第1篇

每个人都有潜在的能量,只是很容易,被习惯所掩盖,被时间所迷离,被惰性所消磨。


文章目录

  • 第一题:买卖股票的最佳时机II
  • 第二题:分发饼干
  • 第三题:柠檬水找零
  • 第四题:无重叠区间
  • 第五题:用最少数量的箭引爆气球
  • 第六题:跳跃游戏
  • 第七题:跳跃游戏II
  • 第八题:合并区间
  • 第九题:加油站
  • 第十题:分发糖果


贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解贪心算法每一次都做出当前看起来最好的选择,而不用考虑其它可能的选择

贪心策略适用的前提是:局部最优策略能导致产生全局最优解

第一题:买卖股票的最佳时机II

  • 题目:
    在这里插入图片描述

解题思路:一有利润就卖出。

class Solution {
     
public:
    int maxProfit(vector<int>& prices) {
        
        int sum= 0;
        int n = prices.size();
        for (int i = 1; i < n; ++i) {
     
            sum += max(0, prices[i] - prices[i - 1]);//有利润就卖出
        }
        return sum;
    }
};

第二题:分发饼干

  • 题目:

在这里插入图片描述

解题思路:对g和s都进行排序,然后分配。也就是排序+贪心。贪心的策略:优先饭量小的人。

class Solution {
     
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
     
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        int sum = 0;
        int j = 0;//全局
        for(int i = 0; i < g.size(); i++)//人员遍历
            for(; j < s.size(); j++)//饼干遍历,或者用while
            {
     
                if(s[j] >= g[i]) {
     sum++;j++;break;}//可以分配
                else if(j == s.size() -1) return sum;//剩下的饼干都不满足条件
            }
            return sum;
    }
};

第三题:柠檬水找零

  • 题目:

【leetcode刷题】贪心算法-第1篇_第1张图片

解题思路:记录5、10、20元的数量,然后根据当前的数值计算它们的状态。贪心的策略:优先用掉10元的面额

class Solution {
     
public:
    bool lemonadeChange(vector<int>& bills) {
     
        int a = 0;//5元数量
        int b = 0;//10
        int c = 0;//20
        for(auto bill : bills)
        {
     
            if(bill == 5) a++;
            else if(bill == 10)
            {
     
                b++;
                a--;
            }
            else
            {
     
                c++;
                if(b > 0){
     b--;a--;}//先10元
                else{
     a -= 3;}//后3张5元
            }
            if(a < 0 || b < 0 || c < 0)return false;
        }
        return true;
    }
};

第四题:无重叠区间

  • 题目:

【leetcode刷题】贪心算法-第1篇_第2张图片

解题思路:先对空间进行排序,排序的条件为右区间的升序排列。然后依次判断左区间。

class Solution {
     
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
     
        if (intervals.empty()) {
     
            return 0;
        }
        
        sort(intervals.begin(), intervals.end(), [](const auto& u, const auto& v) {
     
            return u[1] < v[1];
        });//右区间排序

        int n = intervals.size();
        int right = intervals[0][1];
        int ans = 1;//包含的区间个数
        for (int i = 1; i < n; ++i) {
     //从下一个区间开始判断
            if (intervals[i][0] >= right) {
     //判断左边区间
                ++ans;
                right = intervals[i][1];//新的右边界
            }
        }
        return n - ans;
    }
};

第五题:用最少数量的箭引爆气球

  • 题目:

【leetcode刷题】贪心算法-第1篇_第3张图片

解题思路:沿着右边界射

class Solution {
     
public:
    int findMinArrowShots(vector<vector<int>>& points) {
     
        if(points.size() == 0) return 0;
        sort(points.begin(),points.end(),[](const auto& a, const auto& b){
     return a[1] < b[1];});
        int n = points.size();
        int ans = 0;//表示重叠
        int right = points[0][1];
        for(int i = 1; i < n; i++)
        {
     
            if(points[i][0] <= right)//有重叠,要沿着边缘,也就是right点进行射箭
            {
     
                ans++;
            }
            else//无重叠
            {
     
                right = points[i][1];
            }
        }
        return n - ans;
    }
};

第六题:跳跃游戏

  • 题目:

【leetcode刷题】贪心算法-第1篇_第4张图片

题目解析:判断最远点与当前点之间的关系。

class Solution {
     
public:
    bool canJump(vector<int>& nums) {
     
        int n = nums.size();
        int rightPos = 0;//下一步的最远点
        for (int i = 0; i < n; ++i) {
     
            if (i <= rightPos ) {
     //判断当前点与最远点之间的关系
                rightPos = max(rightPos , i + nums[i]);//看看能否到更远的距离
                if (rightPos >= n - 1) {
     
                    return true;
                }
            }
            else break;//已经不满足条件了,可以退出
        }
        return false;
    }
};

第七题:跳跃游戏II

  • 题目:

【leetcode刷题】贪心算法-第1篇_第5张图片

解题思路:计算每一步所能到达的最大距离。

class Solution {
     
public:
    int jump(vector<int>& nums) {
     
        if(nums.size() <= 1)return 0;
        int count = 1;//跳跃次数,预先跳一次
        int curPos = 0;
        int nextPos = nums[curPos];//下一步
        int maxPos = 0;
        int target = nums.size() -1;
        while(nextPos < target)//只要没到目标
        {
     
            for(int i = curPos + 1; i <= nextPos;i++)//计算下一步的位置
            {
     
                maxPos = max(maxPos, nums[i] + i);//计算下一步
            }
            curPos = nextPos;
            nextPos = maxPos;
            maxPos = 0;
            count++;
        }
        return count;
    }
};

第八题:合并区间

  • 题目:

在这里插入图片描述

解题思路:先以左区间进行排序,然后根据右区间进行判断。(此思路必须以左区间排序)

class Solution {
     
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
     
        if(intervals.size() <= 1)return intervals;
        sort(intervals.begin(), intervals.end(), [](const auto& a, const auto& b){
     return a[0] < b[0];});
         
        vector<vector<int>> ans;
        for(int i = 0; i < intervals.size(); i++)
        {
     
            int L = intervals[i][0]; int R = intervals[i][1];
            if( ans.size() == 0 || (ans.back()[1] < L))//区间不重叠
            {
     
                ans.push_back(intervals[i]);
            }
            else//区间拼接或者有重叠
            {
     
                ans.back()[1] = max(ans.back()[1], R);
            }
        }
        return ans;
    }
};

第九题:加油站

  • 题目

【leetcode刷题】贪心算法-第1篇_第6张图片

题目解析:一次循环判断,暴力求解法。

class Solution {
     
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
     
        int n = cost.size();
        int gasPlus = 0;
        for(int i = 0; i < n; i++)
        {
     
            int nowPos = i;
            int j = (nowPos + 1) % n;
            gasPlus = gas[i] - cost[i];
            if(gasPlus < 0) continue;
            while(j!= nowPos)
            {
     
                gasPlus += gas[j] - cost[j];
                if(gasPlus < 0)break;
                j = (j + 1)%n;
            }
            if(j == nowPos) return nowPos;
        }
        return -1;
    }
};

第十题:分发糖果

  • 题目:

【leetcode刷题】贪心算法-第1篇_第7张图片

解题思路:两次遍历,计算

class Solution {
     
public:
    int candy(vector<int>& ratings) {
     
        int n = ratings.size();
        vector<int> arr(n);//都是0
        for (int i = 0; i < n; i++) {
     //左遍历
            if (i > 0 && ratings[i] > ratings[i - 1]) {
     
                arr[i] = arr[i - 1] + 1;
            } else {
     
                arr[i] = 1;
            }
        }
        int ans = 0;
        for (int i = n - 1; i >= 0; i--) {
     //右遍历
            if (i < n - 1 && ratings[i] > ratings[i + 1]) {
     
                arr[i] = max(arr[i + 1] + 1, arr[i]);
            } else {
     
                arr[i] = max(arr[i], 1);
            }
            ans +=arr[i];
        }
        return ans;
    }
};

你可能感兴趣的:(leetcode,leetcode,贪心算法,分发饼干,跳跃游戏,C++)