先附上本次周赛排名:
5601. 设计有序流
思路:利用map模拟题目过程即可。
class OrderedStream {
int n, ptr;
int[] arr;
Map map;
public OrderedStream(int n) {
ptr = 1;
this.n = n;
arr = new int[n + 1];
map = new HashMap<>();
}
public List insert(int id, String value) {
List res = new ArrayList<>();
if (id != ptr)
map.put(id, value);
else {
int i = id;
map.put(id, value);
for (; i <= n; i++) {
if (!map.containsKey(i))
break;
res.add(map.get(i));
}
ptr = i;
}
return res;
}
}
5603. 确定两个字符串是否接近
思路:记录下两个串中字符出现的数量,之后将这两个数组排序判断即可。
class Solution {
public boolean closeStrings(String word1, String word2) {
int n = word1.length();
int m = word2.length();
if (n != m) return false;
int[] a = new int[26];
int[] b = new int[26];
for (int i = 0; i < n; i++) {
a[word1.charAt(i) - 'a']++;
b[word2.charAt(i) - 'a']++;
}
for (int i = 0; i < 26; i++) {
if (a[i] != 0 && b[i] == 0 || a[i] == 0 && b[i] != 0)
return false;
}
Arrays.sort(a);
Arrays.sort(b);
for (int i = 0; i < 26; i++)
if (a[i] != b[i])
return false;
return true;
}
}
5602. 将 x 减到 0 的最小操作数
思路:这类题套路都一样,枚举左边拿了多少,利用后缀和优化右边能拿多少。
class Solution {
public int minOperations(int[] nums, int x) {
int n = nums.length;
int[] sum = new int[n + 1];
Map map = new HashMap<>();
sum[n - 1] = nums[n - 1];
int ans = n + 1;
map.put(0, 0);
for (int i = n - 1; i >= 0; i--) {
sum[i] = sum[i + 1] + nums[i];
if (sum[i] == x)
ans = Math.min(ans, n - i);
map.put(sum[i], n - i);
}
for (int i = 0; i < n; i++) {
x -= nums[i];
if (map.containsKey(x))
ans = Math.min(ans, i + 1 + map.get(x));
}
return ans == n + 1 ? -1 : ans;
}
}
5604. 最大化网格幸福感
思路:力扣好久没出这种质量较高的动态规划啦。
我们考虑状压dp。定义dp[i][j][k][x][y]:表示第i行外向的人放置的状态为j,内向的人放置的状态为k并且前i行已经使用了x个外向的人和y个内向的人的最大价值和。
class Solution {
public int getMaxGridHappiness(int m, int n, int introvertsCount, int extrovertsCount) {
int[][][][][] dp = new int[m][1 << n][1 << n][introvertsCount + 1][extrovertsCount + 1];
for (int i = 0; i < m; i++)
for (int j = 0; j < (1 << n); j++)
for (int k = 0; k < (1 << n); k++)
for (int x = 0; x <= introvertsCount; x++)
for (int y = 0; y <= extrovertsCount; y++)
dp[i][j][k][x][y] = -1;
for (int i = 0; i < (1 << n); i++)
for (int j = 0; j < (1 << n); j++) {
if (!check(i, j, introvertsCount, extrovertsCount))
continue;
int num1 = findNum(i);
int num2 = findNum(j);
dp[0][i][j][num1][num2] = findSum(i, j);
}
for (int i = 1; i < m; i++)
for (int x = 0; x < (1 << n); x++)
for (int y = 0; y < (1 << n); y++) {
if (!check(x, y, introvertsCount, extrovertsCount))
continue;
int last1 = findNum(x);
int last2 = findNum(y);
for (int num1 = 0; num1 <= introvertsCount; num1++)
for (int num2 = 0; num2 <= extrovertsCount; num2++) {
if (last1 > num1 || last2 > num2 || dp[i - 1][x][y][num1][num2] == -1)
continue;
for (int xx = 0; xx < (1 << n); xx++)
for (int yy = 0; yy < (1 << n); yy++) {
if (!check(xx, yy, introvertsCount - num1, extrovertsCount - num2))
continue;
int now1 = findNum(xx);
int now2 = findNum(yy);
int sum = dp[i - 1][x][y][num1][num2];
int state = x & xx;
sum -= findNum(state) * 30 * 2;
state = x & yy;
sum = sum - findNum(state) * 30 + findNum(state) * 20;
state = y & xx;
sum = sum + findNum(state) * 20 - findNum(state) * 30;
state = y & yy;
sum += findNum(state) * 20 * 2;
dp[i][xx][yy][num1 + now1][num2 + now2] =
Math.max(dp[i][xx][yy][num1 + now1][num2 + now2], sum + findSum(xx, yy));
}
}
}
int ans = 0;
for (int i = 0; i < (1 << n); i++)
for (int j = 0; j < (1 << n); j++)
for (int x = 0; x <= introvertsCount; x++)
for (int y = 0; y <= extrovertsCount; y++)
ans = Math.max(ans, dp[m - 1][i][j][x][y]);
return ans;
}
private int findSum(int x, int y) {
int z = x | y;
int ans = findNum(x) * 120 + findNum(y) * 40;
ans -= findNum(x & (z << 1)) * 30;
ans -= findNum(x & (z >> 1)) * 30;
ans += findNum(y & (z << 1)) * 20;
ans += findNum(y & (z >> 1)) * 20;
return ans;
}
private int findNum(int x) {
int num = 0;
while (x > 0) {
if ((x & 1) != 0)
num++;
x >>= 1;
}
return num;
}
private boolean check(int x, int y, int xx, int yy) {
if ((x & y) != 0) return false;
return findNum(x) <= xx && findNum(y) <= yy;
}
}