0%

LeetCode 周赛

第335场周赛

题目一:递枕头

递枕头

标签

数学模拟

思路

以n为4为例,

1
2
3
step: 1 2 3 4 5 6
n: 2 3 4 3 2 1
每组数以 2 * (n - 1) 进行循环

然后使用time对2 * (n - 1)进行取余运算结果为y:

  • 若结果y大于 n - 1:则对应的值应为n - (y - (n - 1))
  • 若结果y小于 n - 1:则对应的值应为n - ((n - 1) - y)
  • 最后合并一下即为:n - Math.max(y - (n - 1))

题解

1
2
3
4
5
6
7
8
9
10
11
class Solution {
public int passThePillow(int n, int time) {
int res = 1;
int x = n x- 1;
int s = time / x; // 判断是走完一组数的次数
int y = time % x; // 取余数
if(s % 2 != 0) res = n - y; // 如果是奇数,则当前是从后往前走的
else res = 1 + y; // 如果是偶数,则是从后往前走的
return res;
}
}
1
2
3
4
5
6
7
class Solution {
public int passThePillow(int n, int time) {
int x = 2 * (n - 1); // 在后面添加数
int y = time % x; // 取余
return n - Math.abs(y - (n - 1));
}
}

题目二:二叉树中的第 K 大层和

二叉树中的第 K 大层和

标签

二叉树层次遍历队列

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public long kthLargestLevelSum(TreeNode root, int k) {
long[] arr = new long[100010];
int npc = 0;
Queue<TreeNode> que = new LinkedList<>();
que.add(root);
int count = 1; // 记录队列上层加入的元素个数
long value = 0; // 保存每层节点的值
int sum = 0; // 记录当前层加入队列的节点个数
while(!que.isEmpty()) {
TreeNode top = que.remove();
value += top.val;
count --;

if(top.left != null) {
que.add(top.left);
sum ++;
}
if(top.right != null) {
que.add(top.right);
sum ++;
}

if(count == 0) {
arr[npc ++] = value;
count = sum;
sum = 0;
value = 0;
}
}
System.out.println(npc);
Arrays.sort(arr, 0, npc);
if(k > npc) return -1;
return arr[npc - k];

}
}

题目三:分割数组使乘积互质❗

分割数组使乘积互质

标签

质数

思路

题解

题目四:获得分数的方法数

获得分数的方法数

标签

动态规划DP多重背包问题

思路

状态表示dp[i][j]表示前i个作业中恰好是j分的方法数。

状态方程

  • 不是使用第i个作业,则:dp[i][j] = dp[i - 1][j]
  • 使用第i个作业,需要遍历使用的次数 k,则有dp[i][j] += dp[i - 1][j - k * type[i - 1][1]]

注意

  • 前i个作业对应的最后一个作业的下标为 i - 1
  • 在遍历当前作业使用次数时,需要限制 k <= type[i - 1][0] && k * type[i - 1][1] <= j

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public int waysToReachTarget(int target, int[][] types) {
// types[i][0] 对应的物品个数,types[i][1]对应的是物品的价值
int[][] dp = new int[55][1010]; // dp[i][j] 表示前i中作业恰好是j分的方法数
int n = types.length;
for(int i = 0; i <= n; i ++) dp[i][0] = 1; // dp 初始化

for(int i = 1; i <= n; i ++) { // 遍历题目
for(int j = 1; j <= target; j ++) { // 遍历需要的分数
int num = types[i - 1][0];
int score = types[i - 1][1];
for(int k = 0; k <= num && k * score <= j; k ++) { // 遍历可以做第i个题的个数
dp[i][j] = (dp[i][j] + dp[i - 1][j - k * types[i - 1][1]]) % 1000000007;
}
}
}
return dp[n][target];
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
const int MOD = 1000000007;
int waysToReachTarget(int target, vector<vector<int>>& types) {
int dp[55][1010]{0};
int n = types.size();
for(int i = 0; i <= n; i ++) dp[i][0] = 1;

for(int i = 1; i <= n; i ++){
for(int j = 1; j <= target; j ++) {
int count = types[i - 1][0];
int mark = types[i - 1][1];
for(int k = 0; k <= count && k * mark <= j; k ++) {
dp[i][j] = (dp[i][j] + dp[i - 1][j - k * mark]) % MOD;
}
}
}

return dp[n][target];
}
};

第336场周赛

题目一:统计范围内的元音字符串数

统计范围内的元音字符串数

标签

字符串

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public int vowelStrings(String[] words, int left, int right) {
String str = "aeiou"; // 元音
int res = 0;
for(int i = left; i <= right; i++) {
String s = words[i];
char front = s.charAt(0);
char tail = s.charAt(s.length() - 1);
if(str.contains(front + "") && str.contains(tail + "")) res ++;
}
return res;
}
}

题目二:重排数组以得到最大前缀分数

重排数组以得到最大前缀分数

标签

数组前缀和

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public int maxScore(int[] nums) {
Arrays.sort(nums); // 从小到大排序
for(int l = 0, r = nums.length - 1; l < r; l ++, r --) { // 倒置为从大到小排序
int tmp = nums[l];
nums[l] = nums[r];
nums[r] = tmp;
}
long sum = 0;
int res = 0;
for(int i = 0; i < nums.length; i ++) {
sum += nums[i];
if(sum > 0) res ++;
else break;
}
return res;
}
}

题目三:统计美丽子数组数目

统计美丽子数组数目

标签

数组前缀和哈希表

思路

求数组的前缀异或,当出现某个位置的前缀异或值在前面存在过,则是一次美丽子数组。

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public long beautifulSubarrays(int[] nums) {
long res = 0;
int n = nums.length;
int[] sum = new int[n + 1];
sum[0] = 0;
for(int i = 0; i < n; i ++ ){
sum[i + 1] = sum[i] ^ nums[i];
// System.out.println(sum[i + 1]);
}
Map<Integer, Integer> hsp = new HashMap<>();
for(int i = 0; i < n + 1; i ++) {
if(!hsp.containsKey(sum[i])) hsp.put(sum[i], 1);
else {
res += hsp.get(sum[i]);
hsp.put(sum[i], hsp.get(sum[i]) + 1);
}
}
return res;
}
}

题目四:完成所有任务的最少时间💡

完成所有任务的最少时间

标签

数组排序贪心

思路

核心思路是贪心。首先需要将所有的tasks[i]按照有边界从小到大进行排序,然后每次选取时刻的时候都从当前边界的右侧开始选取。

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
private boolean[] st; // st[i] == true 则表示第i时刻已经选取了。
public int findMinimumTime(int[][] tasks) {
st = new boolean[2010];
// 按右边界从小到大进行排序。
Arrays.sort(tasks, (a, b) -> {
if(a[1] == b[1]) return a[0] - b[0];
return a[1] - b[1];
});

for(int i = 0; i < tasks.length; i ++) {
int cnt = tasks[i][2] - (count(tasks[i][0], tasks[i][1])); // 计算已经完成了几次任务了
int end = tasks[i][1];
while(cnt > 0) { // 还有任务没有完成
while(st[end]) { // 从后往前找,找到第一个没有被用过的时刻。
end --;
}
st[end] = true;
cnt --;
}
}
return count(0, 2009);
}

// 计算在[start, end]之间有几个时刻被使用了。
public int count(int start, int end) {
int res = 0;
for(int i = start; i <= end; i ++) {
if(st[i]) res ++;
}
return res;
}
}

第337场周赛

题目一:奇偶位数

奇偶位数

标签

位运算数组

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int[] evenOddBit(int n) {
int[] res = new int[2];
int npc = 0;
int even = 0, odd = 0;
while(n != 0) {
int x = n & 1;
if(x == 1 && npc % 2 == 0) even ++;
else if(x == 1 && npc % 2 != 0) odd ++;
n = n >> 1;
npc ++;
}
res[0] = even;
res[1] = odd;
return res;
}
}

题目二:检查骑士巡视方案

检查骑士巡视方案

标签

广度优先搜索数组矩阵

题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution {

public boolean checkValidGrid(int[][] grid) {
int x = 0, y = 0;
int n = grid.length;
boolean[][] st = new boolean[n][n];
st[0][0] = true;
int npc = 0; // 记录当前已经找到的数
int[] dx = {-1, -2, -2, -1, 1, 2, 2, 1}, dy = {-2, -1, 1, 2, 2, 1, -1, -2}; // x,y偏移量
while(npc < n * n - 1) {
boolean flag = false;
for(int i = 0; i < 8; i ++) {
int r = x + dx[i], c = y + dy[i]; // 新的r,c
if(r < 0 || r >= n || c < 0 || c >= n || st[r][c]) continue;
if(grid[r][c] == npc + 1){
// System.out.println(r + " " + c);
x = r;
y = c;
flag = true;
break;
}
}
if(flag == true) {
npc ++;
} else {
return false;
}
}
return true;
}
}

题目三:美丽子集的数目❗

美丽子集的数目

标签

数组

题解

题目四:执行操作后的最大 MEX❗

执行操作后的最大 MEX

标签

数组

题解

正在加载今日诗词....