LeetCode第 152 场周赛


暑假在家划水半个月,也没有打周赛。回学校重操旧业,顺便写个笔记。

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以内的质数个数,然后计算C_{n}^{p}*C_{n}^{n-p},其中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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值