LeetCode 第400场周赛个人题解

100307. 候诊室中的最少椅子数

原题链接

100307. 候诊室中的最少椅子数

思路分析

直接模拟

时间复杂度:O(n)

AC代码

class Solution:
    def minimumChairs(self, s: str) -> int:
        cur = res = 0
        for x in s:
            if x == 'E':
                cur += 1
            else:
                cur -= 1
            res = max(res, cur)
        return res

100311. 无需开会的工作日

原题链接

100311. 无需开会的工作日

思路分析

区间合并类问题,区间合并后得到若干不相交的区间,数轴上没有被区间覆盖的长度和就是答案

结尾空隙别忘记加

时间复杂度O(nlogn)

AC代码

class Solution:
    def countDays(self, days: int, meetings: List[List[int]]) -> int:
        meetings.sort(key=lambda x: x[0])
        ed = res = 0
        for l, r in meetings:
            if l > ed:
                res += min(l, days) - ed - 1
                ed = r
            else:
                ed = max(ed, r)
        res += max(0, days - ed)
        return res


100322. 删除星号以后字典序最小的字符串

原题链接

100322. 删除星号以后字典序最小的字符串

思路分析

直接顺序遍历,维护每个小写字母的出现下标集合

遇到星号就把当前出现的字典序最小的字母的最右左边打标记

最终返回原字符串中除去打标记和'*'的部分

时间复杂度:O(nU)

AC代码

class Solution:
    def clearStars(self, s: str) -> str:
        n = len(s)
        vis = [False] * n
        st = [[] for _ in range(26)]
        for i, x in enumerate(s):
            if x == '*':
                for j in range(26):
                    if st[j]:
                        vis[st[j][-1]] = True
                        st[j].pop()
                        break
                vis[i] = True
            else:
                st[ord(x) - ord('a')].append(i)
        return ''.join([s[i] for i in range(n) if not vis[i]])

100315. 找到按位与最接近 K 的子数组

原题链接

100315. 找到按位与最接近 K 的子数组

思路分析

没想到好方法,用的线段树+二分

因为固定左端点的前缀与越靠右越小

我们枚举左端点,二分出第一个大于等于 k 的右端点,然后下一个下标就是第一个小于k的右端点,二者贡献出的两个绝对差来对答案进行维护

时间复杂度O(n log^2 n)

应该有更好的方法,比如按位拆分?赛后看下题解区吧


2024.06.02 12:43  吃完饭回来,看评论区说是原题,而且那原题我还做过……去年做的忘了都

F2 ST表+二分

比线段树少个log,跑了300ms

F3 倒序遍历+原地去重

因为所有位置任意长度后缀按位与的值的数目为log级别的,所以我们倒序遍历维护后缀按位与的集合即可,且因为按位与单调递减,我们可以原地去重来维护

这个方法最快,是150ms

AC代码

#define lc p << 1
#define rc p << 1 | 1
constexpr int N = 1e5 + 10;
int tr[N * 4];
// 向上更新
void pushup(int p)
{
    tr[p] = tr[lc] & tr[rc];
}

void build(int p, int l, int r, vector<int>& a)
{
    tr[p] = a[l];
    if (l == r)
        return;
    int mid = (l + r) >> 1;
    build(lc, l, mid, a);
    build(rc, mid + 1, r, a);
    pushup(p);
}

int query(int p, int l, int r, int L, int R)
{
    if (L <= l && r <= R)
        return tr[p];
    int mid = l + r >> 1, res = (1 << 30) - 1;
    if (L <= mid)
        res &= query(lc, l, mid, L, R);
    if (R > mid)
        res &= query(rc, mid + 1, r, L, R);
    return res;
}
#undef lc
#undef rc
class Solution {
public:
    int minimumDifference(vector<int>& a, int k) {
        int n = a.size();
        build(1, 0, n - 1, a);
        int res = abs(tr[1] - k);
        for (int i = 0; i < n; i ++ ) {
            int l = i, r = n - 1, ans = -1;
            while (l <= r) {
                int mid = l + r >> 1;
                if (query(1, 0, n - 1, i, mid) >= k)
                    ans = mid, l = mid + 1;
                else 
                    r = mid - 1;
            } 
            if (ans == -1) {
                l = r = i;
                // cout << a[i] << '\n';
                res = min(res, abs(a[i] - k));
                continue;
            }
            l = ans, r = min(n - 1, ans + 1);
            // cout << query(1, 0, n - 1, i, r) << " " << query(1, 0, n - 1, i, l) << '\n';
            res = min(res, min(abs(query(1, 0, n - 1, i, r) - k), abs(query(1, 0, n - 1, i, l) - k)));
        }
        return res;
    }
};

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EQUINOX1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值