5693.字符串中第二大的数字
给你一个混合字符串 s ,请你返回 s 中 第二大 的数字,如果不存在第二大的数字,请你返回 -1 。
混合字符串 由小写英文字母和数字组成。
暴力,数据范围较小,利用isdigit()判断是否为数字,结合set来做即可。
(学会set的rbegin()的使用)
class Solution {
public:
int secondHighest(string s) {
set<int> st;
for(auto x :s){
if(isdigit(x)){
st.insert(x-'0');
}
}
if(st.empty()|| st.size()==1) return -1;
auto it = st.rbegin();
it++;
return *it;
}
};
5694. 设计一个验证系统
关于验证码规则的简单模拟,题意比较明朗,关键在于time变量和验证码vector数组的维护,代码量不多。
class AuthenticationManager {
public:
int time;
vector<pair<string,int> > v;
AuthenticationManager(int t) {
time = t;
}
void generate(string id, int c) {
v.push_back({id,c});
}
void renew(string id, int c) {
vector<pair<string, int> > nv;
for(int i=0;i<v.size();i++){
auto x = v[i];
if(id==x.first && x.second + time <= c){
continue;
}else if(id==x.first) {
nv.push_back({id,c});
}else {
nv.push_back(x);
}
}
v = nv;//新的vector替代旧的vector,少写for.
}
int countUnexpiredTokens(int c) {
int ans = 0;
for( auto x: v){
if(c-x.second<time) ans++;
}
return ans;
}
};
5712. 你能构造出连续值的最大数目
给你一个长度为 n 的整数数组 coins ,它代表你拥有的 n 个硬币。第 i 个硬币的值为 coins[i] 。如果你从这些硬币中选出一部分硬币,它们的和为 x ,那么称,你可以 构造 出 x 。
请返回从 0 开始(包括 0 ),你最多能 构造 出多少个连续整数。
你可能有多个相同值的硬币。
转换成求多个数字的最小不能凑出来整数,贪心思想,其实是比较coins[i]和sum[0…i-1]+1,如果前者大,sum[0…i-1]+1这个位置就是最小不能凑出来整数(可证明)。
(该题思维难度较高,脑筋急转弯,贪心思想不容易想到)
class Solution {
public:
int getMaximumConsecutive(vector<int>& coins) {
sort(coins.begin(),coins.end());
int sum = 0;
for(auto x:coins){
if(x>sum+1) return sum+1;
sum+=x;
}
return sum+1;
}
};
5695. N 次操作后的最大分数和
给你 nums ,它是一个大小为 2 * n 的正整数数组。你必须对这个数组执行 n 次操作。
在第 i 次操作时(操作编号从 1 开始),你需要:
选择两个元素 x 和 y 。
获得分数 i * gcd(x, y) 。
将 x 和 y 从 nums 中删除。
请你返回 n 次操作后你能获得的分数和最大为多少。
函数 gcd(x, y) 是 x 和 y 的最大公约数。
注意官网说的测试数据范围,因为比较小,可以想到dfs或者状态dp,dfs可能会存在大量重复计算,估计会tle,其实本题是一道经典的状态DP模板题。
class Solution {
public:
int gcd(int a,int b){
return b? gcd(b,a%b) :a;
}
int maxScore(vector<int>& nums) {
int mv = 0;
int n = nums.size();//注意数据范围 nums.size()
vector<int> f(1<<n);
for(int i=0;i< 1<<n;i++){
int cnt = 0;
for(int j=0;j<n;j++){
if(!(i>>j & 1)) //枚举i状态有多少个0
cnt++;
}
cnt = cnt/2+1;// cnt表示第几次,通过规律看i里面有多少个0得出第几次
for(int j=0;j<n;j++)
if(i>>j & 1)
for(int k=j+1;k<n;k++)
if(i>>k & 1)
f[i] = max(f[i],f[i-(1<<j)-(1<<k)]+cnt*gcd(nums[k],nums[j]));
//递增式DP,因此直接返回f[(1<<n)-1]也可以
mv = max(mv,f[i]);
}
return mv;
}
};