暑假在家划水半个月,也没有打周赛。回学校重操旧业,顺便写个笔记。
5173. 质数排列
https://leetcode-cn.com/contest/weekly-contest-152/problems/prime-arrangements/
请你帮忙给从
1
到n
的数设计排列方案,使得所有的「质数」都应该被放在「质数索引」(索引从 1 开始)上;你需要返回可能的方案总数。让我们一起来回顾一下「质数」:质数一定是大于 1 的,并且不能用两个小于它的正整数的乘积来表示。
由于答案可能会很大,所以请你返回答案 模 mod
10^9 + 7
之后的结果即可。示例 1:
输入:n = 5 输出:12 解释:举个例子,[1,2,5,4,3] 是一个有效的排列,但 [5,2,3,4,1] 不是,因为在第二种情况里质数 5 被错误地放在索引为 1 的位置上。
示例 2:
输入:n = 100 输出:682289015
提示:
1 <= n <= 100
思路:先求出n以内的质数个数,然后计算
,其中p为质数个数,n-p为合数个数,即为可能的方案总数
int mod = 1000000007;
public int numPrimeArrangements(int n) {
boolean[] flag = new boolean[n+1];
int size = 0;
flag[1] = true;
for(int k = 2;k <= n;k++) { //求n以内的质数
if(flag[k] == false) {
size++; //size为质数个数
for (int i = 2;i*k <= n;i++) {
flag[i*k] = true;
}
}
}
long res = 1;
for(int i = 1;i <= size;i++)
res = (long)res * i % mod;
for(int i = 1;i <= n - size;i++)
res = (long)res * i % mod;
return (int)res % mod;
}
5174. 健身计划评估
https://leetcode-cn.com/contest/weekly-contest-152/problems/diet-plan-performance/
你的好友是一位健身爱好者。前段日子,他给自己制定了一份健身计划。现在想请你帮他评估一下这份计划是否合理。
他会有一份计划消耗的卡路里表,其中
calories[i]
给出了你的这位好友在第i
天需要消耗的卡路里总量。为了更好地评估这份计划,对于卡路里表中的每一天,你都需要计算他 「这一天以及之后的连续几天」 (共
k
天)内消耗的总卡路里 T:
- 如果
T < lower
,那么这份计划相对糟糕,并失去 1 分;- 如果
T > upper
,那么这份计划相对优秀,并获得 1 分;- 否则,这份计划普普通通,分值不做变动。
请返回统计完所有
calories.length
天后得到的总分作为评估结果。注意:总分可能是负数。
示例 1:
输入:calories = [1,2,3,4,5], k = 1, lower = 3, upper = 3 输出:0 解释:calories[0], calories[1] < lower 而 calories[3], calories[4] > upper, 总分 = 0.
示例 2:
输入:calories = [3,2], k = 2, lower = 0, upper = 1 输出:1 解释:calories[0] + calories[1] > upper, 总分 = 1.
示例 3:
输入:calories = [6,5,0,0], k = 2, lower = 1, upper = 5 输出:0 解释:calories[0] + calories[1] > upper, calories[2] + calories[3] < lower, 总分 = 0.
提示:
1 <= k <= calories.length <= 10^5
0 <= calories[i] <= 20000
0 <= lower <= upper
题目比较绕,一开始没有理解清楚题意,可以用前缀和解决
public int dietPlanPerformance(int[] calories, int k, int lower, int upper) {
int up = 0,low = 0;
int[] sum = new int[calories.length + 1];
for (int i = 0;i < calories.length;i++) {
sum[i+1] = sum[i] + calories[i];
}
for (int i = 0;i + k <= calories.length;i++) {
if (sum[i+k] - sum[i] > upper) up++;
else if (sum[i+k] - sum[i] < lower) low++;
}
return up - low;
}
5175. 构建回文串检测
https://leetcode-cn.com/contest/weekly-contest-152/problems/can-make-palindrome-from-substring/
给你一个字符串
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
,可以认为每次检测都是独立的)示例:
输入:s = "abcda", queries = [[3,3,0],[1,2,0],[0,3,1],[0,3,2],[0,4,1]] 输出:[true,false,false,true,true] 解释: queries[0] : 子串 = "d",回文。 queries[1] : 子串 = "bc",不是回文。 queries[2] : 子串 = "abcd",只替换 1 个字符是变不成回文串的。 queries[3] : 子串 = "abcd",可以变成回文的 "abba"。 也可以变成 "baab",先重新排序变成 "bacd",然后把 "cd" 替换为 "ab"。 queries[4] : 子串 = "abcda",可以变成回文的 "abcba"。
提示:
1 <= s.length, queries.length <= 10^5
0 <= queries[i][0] <= queries[i][1] < s.length
0 <= queries[i][2] <= s.length
s
中只有小写英文字母思路:首先用计算字符串各个字符个数的前缀和。然后对于queries数组中的区间 [left,right],若某个字符在该区间 [left,right] 的个数为奇数,则需要更改的数目+1,最后判断
k是否大于等于需更改字符个数的一半。
public List<Boolean> canMakePaliQueries(String s, int[][] queries) {
List<Boolean> res = new ArrayList<Boolean>();
int len = s.length();
int[][] cnt = new int[len+1][26];
char[] chs = s.toCharArray();
for (int i = 0;i < len;i++) {
for (int j = 0;j < 26;j++) {
cnt[i+1][j] = cnt[i][j];
}
cnt[i+1][chs[i] - 'a']++;
}
for(int[] q : queries) {
int count = 0;
for (int k = 0;k < 26;k++) {
count += (cnt[q[1] + 1][k] - cnt[q[0]][k]) % 2;
}
res.add(q[2] >= count/2);
}
return res;
}