A 候诊室中的最少椅子数
计数:记录室内顾客数,每次顾客进入时,计数器+1,顾客离开时,计数器-1
cpp
class Solution {
public:
int minimumChairs(string s) {
int res = 0;
int cnt = 0;
for (auto c : s) {
if (c == 'E')
res = max(res, ++cnt);
else
cnt--;
}
return res;
}
};
B 无需开会的工作日
排序:将 m e e t i n g s meetings meetings 按开始时间升序排序(若开始时间相同,则按结束时间降序排序),这样使得存在重叠的一组会议在数组中是相邻的,然后遍历 m e e t i n g s meetings meetings 求各个不重叠会议时间段
cpp
class Solution {
public:
int countDays(int days, vector<vector<int>>& meetings) {
sort(meetings.begin(), meetings.end(), [](vector<int>& a, vector<int>& b) {
if (a[0] != b[0])
return a[0] < b[0];
return a[1] > b[1];
});
int res = days;
int n = meetings.size();
for (int i = 0, j = 0; i < n; i = ++j) {
int r = meetings[i][1];
while (j + 1 < n && meetings[j + 1][0] <= r) {//求与meetings[i]重叠的一组会议
r = max(r, meetings[++j][1]);
}
res -= r - meetings[i][0] + 1;//减去会议天数
}
return res;
}
};
C 删除星号以后字典序最小的字符串
优先级队列:遇到 ∗ * ∗ 时,因为需删除该星号字符左边一个字典序最小的字符,且题目需最终剩余字符形成的字符串字典序最小,所以应该删除该星号字符左边下标最大的字典序最小的字符。用优先级队列维护当前还没删除的字符中的字典序最小的下标最大的字符
cpp
class Solution {
public:
string clearStars(string s) {
int n = s.size();
priority_queue<pair<int, int>> heap;//最大堆
vector<int> del(n);//删除标记
for (int i = 0; i < n; i++) {
if (s[i] != '*')
heap.emplace('a' - s[i], i);
else {
auto [_, loc] = heap.top();
heap.pop();
del[loc] = 1;
}
}
string res;
for (int i = 0; i < n; i++) {
if (s[i] != '*' && !del[i])
res.push_back(s[i]);
}
return res;
}
};
D 找到按位与最接近 K 的子数组
前缀和 + 二分:枚举子数组的左端点 i i i ,用二分求 l l l 使得 n u m s [ i ] & ⋯ & n u m s [ l ] nums[i]\&\cdots\&nums[l] nums[i]&⋯&nums[l] 为不小于 k k k 的最小值,若 l + 1 < n l+1<n l+1<n ,则 ∣ n u m s [ i ] & ⋯ & n u m s [ l + 1 ] − k ∣ |nums[i]\&\cdots\&nums[l+1]-k| ∣nums[i]&⋯&nums[l+1]−k∣ 也可能更新答案,二分过程中用前缀和来计算 n u m s [ i ] & ⋯ & n u m s [ m i d ] nums[i]\&\cdots\&nums[mid] nums[i]&⋯&nums[mid] 的值( n u m s [ i ] & ⋯ & n u m s [ m i d ] nums[i]\&\cdots\&nums[mid] nums[i]&⋯&nums[mid] 第 j j j 位为 1 1 1 当且仅当 n u m s [ i ] , ⋯ , n u m s [ m i d ] nums[i],\cdots,nums[mid] nums[i],⋯,nums[mid] 第 j j j 位都为 1 1 1)
cpp
class Solution {
public:
int minimumDifference(vector<int>& nums, int k) {
int n = nums.size();
int ps[30][n + 1];//每一位的前缀和
memset(ps, 0, sizeof(ps));
for (int j = 0; j < 30; j++)
for (int i = 0; i < n; i++)
ps[j][i + 1] = nums[i] >> j & 1 ? ps[j][i] + 1 : ps[j][i];
int res = INT32_MAX;
for (int i = 0; i < n; i++) {
int l = i, r = n - 1;
while (l < r) {//二分求l
int mid = (l + r + 1) / 2;
int t = 0;
for (int j = 0; j < 30; j++)
if (ps[j][mid + 1] - ps[j][i] == mid - i + 1)
t |= 1 << j;
if (t >= k)
l = mid;
else
r = mid - 1;
}
int t = 0;
for (int j = 0; j < 30; j++)
if (ps[j][l + 1] - ps[j][i] == l - i + 1)
t |= 1 << j;
res = min(res, abs(t - k));
if (t > k && l + 1 < n)
res = min(res, abs((t & nums[l + 1]) - k));
}
return res;
}
};