5561. 获取生成数组中的最大值
问题描述:传送门
思路:
1、vector容器规划大小,通过与运算判断奇偶,递归,最后利用max函数求最值。
代码:
class Solution {
public:
int getMaximumGenerated(int n) {
vector<int> v;
v.resize(105);//根据题意,重新规划一下容器大小
v[0]=0;v[1]=1;//题意
for(int i=2;i<=n;i++){
if(i&1){
v[i]=v[i/2]+v[(i/2)+1];
}else{
v[i]=v[i/2];
}
}
int ans=-1;
for(int i=0;i<=n;i++){
ans=max(ans,v[i]);
}
return ans;
}
};
1647. 字符频次唯一的最小删除次数
问题描述:传送门
思路:
1、贪心算法+两个map
代码:
class Solution {
class Solution {
public:
int minDeletions(string s) {
map<char,int> cnt;//先把每个字母的频数记录一下,example: abbccddd
for(int i=0;i<s.size();i++){
cnt[s[i]]++;//遇到这个字符,频数就++
}
map<int,int> r;
for(auto j:cnt){
//j.first统计每个字母,有多少频次,如a=1、bb=2、cc=2,ddd=3;
//j.second,有多少个不同字母,符合这个次数,bbcc=2
r[j.second]++;//两个不同字母频数相同的+1,r[2]=2;
}
int ans =0;//统计删除的次数
int now=0;//扫数的时候,记录一下当前位置
while(r.size()>0){
//先保证频次不为null
if(r.rbegin()->second==1){
//频次为1,优先出图,如d[3]==1
now = r.rbegin()->first;
r.erase(r.find(now));//把当前位置,移出去
}else{
//now代表频次,r[now]代表的是相应频次的,不同字母,数量
now =r.rbegin()->first;
//形如bb,cc的数,频次now为2,两个频次为2的不同字母,r[2]=2
r[now]--;//假如去掉一个字母c,r[2]==1,即bbc
if(now!=1){
//c侵占了字母a的 r[1]=1;所以r[1]++=2;
r[now-1]++;
}
//直到当前位置频数只剩1时,ans才不用++。如去掉c,只剩a的时候,r[1]=1;
ans++;
}
}
return ans;
}
};
2、贪心算法+类似双指针
①先开vector统计每个字母,频数
②频数从大到小排序
③设置当前prt,指向cnt【0】。因为前面从大到小排列了,所以只统计整个字符串里从它往后比他大于等于的数
每次循环时,目前能保留的最大值max给ptr,那么ptr后面的字母,要删除的数,就只能是cnt[i]-ptr。
⑤如果后面的字母都比ptr的频数小,那就让ptr往后面走
代码:
class Solution {
public:
int minDeletions(string s) {
vector<int> cnt(26,0);//统计每个字符出现的次数
for(auto ch:s){
cnt[ch-'a']++;//统计频次
}
sort(cnt.begin(),cnt.end(),greater<int>());//从大到小排列
int ptr =cnt[0];
int ans=0;
for(int i=1;i<cnt.size()&&cnt[i]>0;i++){
//零个数最好不计算进去
if(ptr<=cnt[i]){
ptr=max(ptr-1,0);//排序到目前,能保留的最大数
ans+=cnt[i]-ptr;
}else if(ptr>cnt[i]){
ptr=cnt[i];//让当前数进位
}
}
return ans;
}
};