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