LeetCode Weekly Contest 301
Q1
6112. 装满杯子需要的最短总时长 - 力扣(LeetCode)
提交
1 | class Solution { |
贪心
从最大的两个数开始减少1
2
3
4
5
6
7
8
9
10
11
12
13
14class Solution {
public int fillCups(int[] amount) {
int res = 0;
while(true){
// 每次都排序。从最大的两个数开始减。如果中间的数都为0。再加上残余的最大值。
Arrays.sort(amount);
if (amount[1] == 0) break;
amount[2]--;
amount[1]--;
res++;
}
return res + amount[2];
}
}
公式
如果 最大值 大于另外两个和。返回最大值
如果 最大值小于另外两个和。
a >= b >= c
当 a <= b +c的时候,每次必然可以拿两个数。
当a - 1, b-1, c 最大值仍然为a时, 还是满足a <= b +c这个性质。每次都可以从两边拿
当最大值变为c的时候,c同样可以和a一样操作1
2
3
4
5
6
7class Solution {
public int fillCups(int[] a) {
Arrays.sort(a);
if(a[2] >= a[0] + a[1]) return a[2];
else return (a[0] + a[1] + a[2] + 1) /2;
}
}
Q2
6113. 无限集中的最小数字 - 力扣(LeetCode)
提交
1 | class SmallestInfiniteSet { |
set
使用set存被删除的数。无限集如果数据量大的话,就过不了了。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19class SmallestInfiniteSet {
HashSet<Integer> set;
public SmallestInfiniteSet() {
set=new HashSet<>();
}
public int popSmallest() {
int res=1;
while(set.contains(res)){
res++;
}
set.add(res);
return res;
}
public void addBack(int num) {
if(set.contains(num)) set.remove(num);
}
}
Q3
6114. 移动片段得到字符串 - 力扣(LeetCode)
同 777. 在LR字符串中交换相邻字符 - 力扣(LeetCode)
提交
1 | class Solution { |
双指针
1 | class Solution { |
Q4
6115. 统计理想数组的数目 - 力扣(LeetCode)
组合数 DP
n是数组的长度,t是不同元素的个数。
如果可以相同,就是计算组合数从n -1个位置里 选出t-1个位置。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
46class Solution {
const int MOD = 1000000007;
const int MAXP = 16; // 2^16 > 10000, n <= 10000
public:
int idealArrays(int n, int K) {
// nlnn 求因数
vector<vector<int>> fac(K + 1);
for (int i = 1; i <= K; i++)
// 求的是j的因数的数组
for (int j = i << 1; j <= K; j += i)
fac[j].push_back(i);
// 计算子问题的答案
vector<vector<long long>> f;
f.resize(K + 1, vector<long long>(20));
// i的最大值为K
for (int i = 1; i <= K; i++) {
// 以1为结尾只有一种方案
f[i][1] = 1;
for (int j = 2; j <= MAXP; j++)
// t是i的因数。加上子问题的方案书。以因数为结尾。长度减去1的情况
for (int t : fac[i])
f[i][j] = (f[i][j] + f[t][j - 1]) % MOD;
}
// 求组合数
vector<vector<long long>> C;
C.resize(n + 1, vector<long long>(20));
C[0][0] = C[1][0] = C[1][1] = 1;
for (int i = 2; i <= n; i++) {
C[i][0] = 1;
for (int j = 1; j <= i && j <= MAXP; j++)
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % MOD;
}
// 统计最终答案
long long ans = 0;
for (int i = 1; i <= K; i++)
for (int j = 1; j <= MAXP; j++)
// 以i为最后一个元素。且数组长度为j的数量。组合数-> 计算出元素重复使用的情况
ans = (ans + C[n - 1][j - 1] * f[i][j]) % MOD;
return ans;
}
};
暴力搜索
1 | class Solution { |