
初篇我们介绍了贪心算法的相关背景知识,本篇我们将结合具体题目,进一步深化大家对于贪心算法的理解和运用。
需要找零的时候只有两种情况
根据贪心算法的思路,我们每次都需要求取最优解,并且推理可得,贪心解一定为最优解,因为5美元在该处相当于万能找零,而10美元只有在20美元这种特殊情况下才能派上用场。
class Solution {
public:
bool lemonadeChange(vector<int>& bills) {
int five=0,ten=0;//记录零钱
for(auto e:bills)
{
if(e==5)
{
five++;
}//5元时无需找零
else if(e==10)
{
if(five==0)
{
return false;
}//无可找零钱时则直接返回false
else
{
five--;
ten++;
}//能正常找零
}
else
{
if(five&&ten)
{
five--;
ten--;
}//最优情况,找一张10块,一张5块
else if(five>=3)
{
five=five-3;
}//次之,找3张5元
else
{
return false;
}//无法正常找零
}
}
return true;
}
};本题的贪心解很明显,每次减半时都选取当前数组的最大值进行减半操作,推理验证也可得贪心解即为最优解。
优先级队列的方式进行存储,这样每次top即可取出当前的最大值。class Solution {
public:
int halveArray(vector<int>& nums) {
priority_queue<double> heap;//创建大根堆
double sum=0;
int ret=0;//操作次数
for(auto e :nums)
{
heap.push(e);
sum+=e;
}
sum/=2;
while(sum>0)
{
double t=heap.top();
heap.pop();
t/=2;
sum-=t;
heap.push(t);
ret++;
}//每次令最大的数减半
return ret;
}
};将所有的数字当成字符串处理,那么两个数字之间的拼接操作以及⽐较操作就会很⽅便。 假设有两个字符串,10和2分别作为A和B 那么拼接后102<210,继续枚举即可发现规律
问题就转化为:重新定义⼀个新的排序规则,然后排序即可。
class Solution {
public:
string largestNumber(vector<int>& nums) {
vector<string> str;
for(auto e :nums)
{
str.push_back(to_string(e));
}
//排序
sort(str.begin(),str.end(),[](const string& s1,const string& s2)
{
return s1+s2>s2+s1;
});
string ret;
for(auto e:str)
{
ret+=e;
}
if(str[0]=="0") return "0";//处理前导0这种特殊情况
return ret;
}
};贪心策略
对于某⼀个位置来说: ◦ 如果接下来呈现上升趋势的话,我们让其上升到波峰的位置; ◦ 如果接下来呈现下降趋势的话,我们让其下降到波⾕的位置。 因此,如果把整个数组放在「折线图」中,我们统计出所有的波峰以及波⾕的个数即可。
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
int n=nums.size();
if(n<2) return n;//处理特殊情况
int ret=0,left=0;
for(int i=0;i<n-1;i++)
{
int right=nums[i+1]-nums[i];
if(right==0) continue;//直接跳过
else if(left*right<=0) ret++;//累加波峰或波谷
left=right;
}
return ret+1;
}
};本篇关于贪心算法的介绍就暂告段落啦,希望能对大家的学习产生帮助,欢迎各位佬前来支持斧正!!!