leetcode 152周赛
1.质数排列
请你帮忙给从 1 到 n 的数设计排列方案,使得所有的「质数」都应该被放在「质数索引」(索引从 1 开始)上;你需要返回可能的方案总数。
让我们一起来回顾一下「质数」:质数一定是大于 1 的,并且不能用两个小于它的正整数的乘积来表示。
由于答案可能会很大,所以请你返回答案 模 mod 10^9 + 7 之后的结果即可。
1 <= n <= 100
链接:https://leetcode-cn.com/contest/weekly-contest-152/problems/prime-arrangements/
思路:这道题考察了筛素数,另外可以分析出题目让求是素数个数的排列和非素数个数的排列的乘积。
class Solution {
public:
int mod=1e9+7;
vector<bool> st;
vector<int> primers;
int numPrimeArrangements(int n) {
st=vector<bool>(n+1,false);
int num=get_primers(n);
long long int ans=1;
long long int c1=1;
long long int c2=1;
for(int i=1;i<=num;++i){
c1=1ll*c1*i%mod;
}
for(int i=1;i<=n-num;++i){
c2=1ll*c2*i%mod;
}
ans=1ll*c1*c2%mod;
return ans;
}
int get_primers(int n){
for(int i=2;i<=n;++i){
if(!st[i])primers.push_back(i);
for(int j=0;j<primers.size()&&primers[j]<=n/i;++j){
st[primers[j]*i]=true;
if(i%primers[j]==0)
break;
}
}
return primers.size();
}
};
2.健身计划评估
你的好友是一位健身爱好者。前段日子,他给自己制定了一份健身计划。现在想请你帮他评估一下这份计划是否合理。
他会有一份计划消耗的卡路里表,其中 calories[i] 给出了你的这位好友在第 i 天需要消耗的卡路里总量。
为了更好地评估这份计划,对于卡路里表中的每一天,你都需要计算他 「这一天以及之后的连续几天」 (共 k 天)内消耗的总卡路里 T:
如果 T < lower,那么这份计划相对糟糕,并失去 1 分;
如果 T > upper,那么这份计划相对优秀,并获得 1 分;
否则,这份计划普普通通,分值不做变动。
请返回统计完所有 calories.length 天后得到的总分作为评估结果。
注意:总分可能是负数。
链接:https://leetcode-cn.com/contest/weekly-contest-152/problems/diet-plan-performance/
思路:前缀和算法
class Solution {
public:
int dietPlanPerformance(vector<int>& calories, int k, int lower, int upper) {
vector<int> q(calories.size()+1,0);
q[0]=0;
int n=calories.size();
for(int i=1;i<=n;++i){
q[i]=q[i-1]+calories[i-1];
}
int cot=0;
for(int i=1;i<=n-k+1;i++){
int l=i-1;
int r=i+k-1;
int num=q[r]-q[l];
if(num>upper)cot++;
if(num<lower)cot--;
}
return cot;
}
};
给你一个字符串 s,请你对 s 的子串进行检测。
每次检测,待检子串都可以表示为 queries[i] = [left, right, k]。我们可以 重新排列 子串 s[left], ..., s[right],并从中选择 最多 k 项替换成任何小写英文字母。
如果在上述检测过程中,子串可以变成回文形式的字符串,那么检测结果为 true,否则结果为 false。
返回答案数组 answer[],其中 answer[i] 是第 i 个待检子串 queries[i] 的检测结果。
注意:在替换时,子串中的每个字母都必须作为 独立的 项进行计数,也就是说,如果 s[left..right] = "aaa" 且 k = 2,我们只能替换其中的两个字母。(另外,任何检测都不会修改原始字符串 s,可以认为每次检测都是独立的)
链接:https://leetcode-cn.com/contest/weekly-contest-152/problems/can-make-palindrome-from-substring/
思路:
1.对于每一个子字符串,统计奇数字母的个数cot,若k>=cot/2,则true
2.每次统计可以用前缀和来优化,二维循环更新q,如果当前的字符s[i]-'a'等于j那麽q[i][j]=q[i-1][j]+1,否则就等于q[i-1][j]
class Solution {
public:
vector<bool> canMakePaliQueries(string s, vector<vector<int>>& queries) {
vector<bool> ans;
vector<vector<int>> q(s.size()+1,vector<int>(30));
for(int i=1;i<=s.size();++i){
for(int j=0;j<26;++j){
if(s[i-1]-'a'==j){
q[i][j]=q[i-1][j]+1;
}
else{
q[i][j]=q[i-1][j];
}
}
}
for(auto t:queries){
int cot=0;
int l=t[0]+1,r=t[1]+1,k=t[2];
for(int i=0;i<26;++i){
int num=q[r][i]-q[l-1][i];
if(num>0&&num%2)cot++;
}
if(k>=cot/2)ans.push_back(true);
else ans.push_back(false);
}
return ans;
}
};
外国友人仿照中国字谜设计了一个英文版猜字谜小游戏,请你来猜猜看吧。
字谜的迷面 puzzle 按字符串形式给出,如果一个单词 word 符合下面两个条件,那么它就可以算作谜底:
单词 word 中包含谜面 puzzle 的第一个字母。
单词 word 中的每一个字母都可以在谜面 puzzle 中找到。
例如,如果字谜的谜面是 "abcdefg",那么可以作为谜底的单词有 "faced", "cabbage", 和 "baggage";而 "beefed"(不含字母 "a")以及 "based"(其中的 "s" 没有出现在谜面中)。
返回一个答案数组 answer,数组中的每个元素 answer[i] 是在给出的单词列表 words 中可以作为字谜迷面 puzzles[i] 所对应的谜底的单词数目。
链接:https://leetcode-cn.com/contest/weekly-contest-152/problems/number-of-valid-words-for-each-puzzle/
思路:
1.将字符串哈希成整数,存在哈希表里。
2.对于每个谜面也哈希成整数,然后枚举谜面可能的字母组合方式即可
class Solution {
public:
vector<int> findNumOfValidWords(vector<string>& words, vector<string>& puzzles) {
vector<int> ans;
unordered_map<int,int> hash;
for(auto t:words){
int bit=0;
for(int i=0;i<t.size();++i){
int j=t[i]-'a';
bit=bit|(1<<j);
}
hash[bit]++;
}
for(auto t:puzzles){
int first=1<<(t[0]-'a');
int bit=0;
int cot=0;
for(int i=0;i<t.size();++i){
int j=t[i]-'a';
bit=bit|(1<<j);
}
for(int k=bit,j=bit;j;j=(j-1)&k)//这里枚举可能的组合情况,每次减1但是还要处理一下
if((j&first)==first)
cot+=hash[j];
ans.push_back(cot);
}
return ans;
}
};