leetcode刷题贪心算法-第1篇

Posted 非晚非晚

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode刷题贪心算法-第1篇相关的知识,希望对你有一定的参考价值。

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



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

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

第一题:买卖股票的最佳时机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;
    }
};

第三题:柠檬水找零

  • 题目:

在这里插入图片描述

解题思路:记录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;
    }
};

第四题:无重叠区间

  • 题目:

在这里插入图片描述

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

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;
    }
};

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

  • 题目:

在这里插入图片描述

解题思路:沿着右边界射

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;
    }
};

第六题:跳跃游戏

  • 题目:

在这里插入图片描述

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

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

  • 题目:

在这里插入图片描述

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

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;
    }
};

第九题:加油站

  • 题目

在这里插入图片描述

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

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;
    }
};

第十题:分发糖果

  • 题目:

在这里插入图片描述

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

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刷题贪心算法-第1篇的主要内容,如果未能解决你的问题,请参考以下文章

leetcode之贪心算法刷题总结1

LeetCode 20天算法刷题计划第三天:双指针

leetcode之贪心算法刷题总结3

leetcode之贪心算法刷题总结2

leetcode之贪心算法刷题总结4

leetcode之贪心算法刷题总结5