第 64 场双周赛
Problem A - 数组中第 K 个独一无二的字符串
方法一:模拟
统计出所有字符串的出现频次即可。
- 时间复杂度。
- 空间复杂度。
参考代码(Python 3)
class Solution:
def kthDistinct(self, arr: List[str], k: int) -> str:
cnt = collections.Counter(arr)
uniq = [s for s in arr if cnt[s] == 1]
return uniq[k - 1] if len(uniq) >= k else ""
Problem B - 两个最好的不重叠活动
方法一:排序+优先队列
将所有活动按开始时间排序后,我们可以这样考虑选择两个活动:
- 选择此刻已经结束的活动中价值最大的。
- 选择当前活动。
我们可以用一个优先队列(以结束时间为权重建立小根堆)维护当前尚未结束的活动,并记录当前已经结束的活动的最大价值。
- 时间复杂度为。
- 空间复杂度。
参考代码(C++)
class Solution {
public:
int maxTwoEvents(vector<vector<int>>& events) {
sort(events.begin(), events.end());
int ans = 0, hi = 0, n = events.size();
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
for (int i = 0; i < n; ++i) {
int s = events[i][0], e = events[i][1], v = events[i][2];
while (!pq.empty() && pq.top().first < s) {
hi = max(hi, pq.top().second);
pq.pop();
}
ans = max(ans, hi + v);
pq.emplace(e, v);
}
return ans;
}
};
Problem C - 蜡烛之间的盘子
方法一:前缀和
我们可以利用前缀和的方法求出以下三个值:
plates[i]
代表中盘子的总数rcandle[i]
代表中最靠右的蜡烛的位置lcandle[i]
代表中最靠左的蜡烛的位置
对于每一询问,我们利用lcandle
和rcandle
找到询问对应的区间中最左边的蜡烛和最右边的蜡烛,然后利用plates
即可计算出盘子的数目。
- 时间复杂度。
- 空间复杂度。
参考代码(C++)
class Solution {
public:
vector<int> platesBetweenCandles(string s, vector<vector<int>>& queries) {
int n = s.size();
vector<int> plates(n + 1), lcandle(n + 1, n + 1), rcandle(n + 1);
for (int i = 1; i <= n; ++i) {
plates[i] = plates[i - 1];
rcandle[i] = rcandle[i - 1];
if (s[i - 1] == '*')
plates[i]++;
else
rcandle[i] = i;
}
for (int i = n - 1; i >= 0; --i) {
lcandle[i] = lcandle[i + 1];
if (s[i] == '|')
lcandle[i] = i + 1;
}
int q = queries.size();
vector<int> ans(q);
for (int i = 0; i < q; ++i) {
int l = queries[i][0] + 1, r = queries[i][1] + 1;
int lc = lcandle[l - 1], rc = rcandle[r];
if (lc >= rc)
continue;
ans[i] = plates[rc] - plates[lc];
}
return ans;
}
};
Problem D - 棋盘上有效移动组合的数目
方法一:模拟
按题意枚举所有可能的移动组合并检查是否有效即可。
- 时间复杂度。但由于限制了最多有一个皇后,实际最大的复杂度是。
- 空间复杂度。
参考代码(C++)
const int d[8][2] = {{-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}};
class Solution {
vector<vector<int>> positions, possible;
int n, ans = 0;
vector<int> direction, step, xinit, yinit;
bool valid(int x, int y) {
return x >= 1 && x <= 8 && y >= 1 && y <= 8;
}
void check() {
vector<int> x(xinit), y(yinit), s(step);
bool go = true;
while (go) {
go = false;
for (int i = 0; i < n; ++i) {
if (s[i] > 0) {
s[i]--;
x[i] += d[direction[i]][0];
y[i] += d[direction[i]][1];
}
if (s[i])
go = true;
}
for (int i = 0; i < n; ++i)
for (int j = i + 1; j < n; ++j)
if (x[i] == x[j] && y[i] == y[j])
return;
}
ans++;
}
void dfs(int i) {
if (i == n) {
check();
} else {
direction.push_back(0);
step.push_back(0);
dfs(i + 1);
direction.pop_back();
step.pop_back();
for (int j = 1; j < 8; ++j) {
for (int k : possible[i]) {
int x = positions[i][0] + d[k][0] * j, y = positions[i][1] + d[k][1] * j;
if (valid(x, y)) {
direction.push_back(k);
step.push_back(j);
dfs(i + 1);
direction.pop_back();
step.pop_back();
}
}
}
}
}
public:
int countCombinations(vector<string>& pieces, vector<vector<int>>& positions) {
n = pieces.size();
possible = vector<vector<int>>(n);
this->positions = positions;
xinit = vector<int>(n), yinit = vector<int>(n);
for (int i = 0; i < n; ++i) {
xinit[i] = positions[i][0], yinit[i] = positions[i][1];
if (pieces[i] != "rook") {
possible[i].emplace_back(1);
possible[i].emplace_back(3);
possible[i].emplace_back(5);
possible[i].emplace_back(7);
}
if (pieces[i] != "bishop") {
possible[i].emplace_back(0);
possible[i].emplace_back(2);
possible[i].emplace_back(4);
possible[i].emplace_back(6);
}
}
dfs(0);
return ans;
}
};