# Leetcode 第215场周赛题解
# Problem A - 设计有序流 (opens new window)
模拟。
- 插入操作的均摊时间复杂度为。因为指针是单向移动的。
- 空间复杂度。
参考代码(C++)
class OrderedStream {
int ptr = 1;
vector<string> v;
public:
OrderedStream(int n) {
v = vector<string>(n + 1);
}
vector<string> insert(int id, string value) {
v[id] = value;
vector<string> ret;
while (ptr < v.size() && !v[ptr].empty())
ret.emplace_back(v[ptr++]);
return ret;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Problem B - 确定两个字符串是否接近 (opens new window)
首先判断长度是否相等。在长度相等的情况下,题目中的两种操作可以理解为:
- 对字符串进行任意排列
- 交换两个字符的频次
所以实际上,我们需要判断的是:
- 两个字符串的字符集是否一致
- 两个字符串的字符频率集是否一致
统计频次,分别进行判断即可。
- 时间复杂度,为字母表的大小。
- 空间复杂度。
参考代码(C++)
class Solution {
public:
bool closeStrings(string word1, string word2) {
int l1 = word1.size(), l2 = word2.size();
if (l1 != l2)
return false;
vector<int> v1(26), v2(26);
for (char c : word1)
v1[c - 'a']++;
for (char c : word2)
v2[c - 'a']++;
for (int i = 0; i < 26; ++i)
if ((v1[i] > 0) ^ (v2[i] > 0))
return false;
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end());
for (int i = 0; i < 26; ++i)
if (v1[i] != v2[i])
return false;
return true;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Problem C - 将 x 减到 0 的最小操作数 (opens new window)
使用双指针。初始状态左指针在前缀和大于等于的第一个位置处。之后右指针从最右边开始左移,左指针相应向左移动。在过程中不断更新最优解。
- 时间复杂度。
- 空间复杂度。
参考代码(C++)
class Solution {
public:
int minOperations(vector<int>& nums, int x) {
int n = nums.size();
int sum = 0;
int l = 0;
while (l < n && sum < x)
sum += nums[l++];
if (sum < x)
return -1;
int ans = INT_MAX;
if (sum == x) {
ans = l;
if (l == n)
return n;
}
int rsum = 0;
for (int r = n - 1; r >= 0; --r) {
rsum += nums[r];
while (l >= 1 && rsum + sum > x)
sum -= nums[--l];
if (sum + rsum == x)
ans = min(ans, n - r + l);
}
return ans == INT_MAX ? -1 : ans;
}
};
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
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
# Problem D - 最大化网格幸福感 (opens new window)
较麻烦的三进制状态压缩动态规划。可以利用类似滑动窗口(或者叫轮廓线)的方法进一步优化时间复杂度(参见zerotrac (opens new window)和newhar (opens new window)的题解)。这里仅给出基本的按行动态规划的实现。
- 时间复杂度。
- 空间复杂度。
参考代码(C++)
int dp[26][26][243];
int three[6] = {1, 3, 9, 27, 81, 243};
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1};
int g[243][243];
int points[3] = {0, 120, 40};
int delta[3][3] = {{0, 0, 0}, {0, -60, -10}, {0, -10, 40}};
class Solution {
public:
int getMaxGridHappiness(int m, int n, int intro, int extro) {
if (m < n)
swap(m, n);
for (int i = 0; i <= intro; ++i)
for (int j = 0; j <= extro; ++j)
for (int k = 0; k < three[n]; ++k)
dp[i][j][k] = -1;
dp[0][0][0] = 0;
int ans = 0;
auto get_points = [&](int last, int nxt) {
int pts = 0;
vector<vector<int>> mat(2, vector<int>(n));
for (int j = 0; j < n; ++j) {
mat[0][j] = last % 3;
last /= 3;
mat[1][j] = nxt % 3;
nxt /= 3;
}
for (int j = 0; j < n; ++j) {
pts += points[mat[1][j]];
pts += delta[mat[0][j]][mat[1][j]];
if (j + 1 < n)
pts += delta[mat[1][j]][mat[1][j + 1]];
}
return pts;
};
for (int i = 0; i < three[n]; ++i)
for (int j = 0; j < three[n]; ++j)
g[i][j] = get_points(i, j);
vector<pair<int, int>> decode(three[n]);
for (int i = 0; i < three[n]; ++i) {
int d = i;
while (d) {
if (d % 3 == 1)
decode[i].first++;
if (d % 3 == 2)
decode[i].second++;
d /= 3;
}
}
for (int i = 0; i < m; ++i) {
for (int p = intro; p >= 0; --p)
for (int q = extro; q >= 0; --q) {
for (int last = 0; last < three[n]; ++last) {
if (dp[p][q][last] == -1)
continue;
for (int nxt = 1; nxt < three[n]; ++nxt) {
auto [a, b] = decode[nxt];
if (p + a > intro || q + b > extro)
continue;
dp[p + a][q + b][nxt] = max(dp[p + a][q + b][nxt], dp[p][q][last] + g[last][nxt]);
}
dp[p][q][0] = max(dp[p][q][0], dp[p][q][last]);
if (last != 0)
dp[p][q][last] = -1;
}
}
}
for (int i = 0; i <= intro; ++i)
for (int j = 0; j <= extro; ++j)
for (int k = 0; k < three[n]; ++k)
ans = max(ans, dp[i][j][k]);
return ans;
}
};
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77