LeetCode 双周赛 88 题解

plus2047 于 2022-10-01 发布

LeetCode 周赛之外,还有个双周赛。本周开始,我会更新双周赛的文字版题解!

中国站传送门 国际站传送门

1. 删除字符使频率相同

image

比较简单,逐个删除,然后检查即可。

这个问题是有时间复杂度更低的解的,但这个最粗暴的解足够过掉了。

class Solution:
    def equalFrequency(self, word: str) -> bool:
        def check(s):
            return len(set(Counter(s).values())) == 1
        for i in range(len(word)):
            if check(word[:i] + word[i + 1:]):
                return True
        return False

2. 最长上传前缀

image

题目有点难懂,仔细读一下题。

class LUPrefix:
    def __init__(self, n: int):
        self.curr_longest = 0
        self.uploaded = [False] * (n + 2)

    def upload(self, video: int) -> None:
        self.uploaded[video] = True
        while self.uploaded[self.curr_longest + 1] == True:
            self.curr_longest += 1

    def longest(self) -> int:
        return self.curr_longest

3. 所有数对的异或和

image

这是一个数学题目。你需要知道,XOR 运算满足交换律、结合律,并且对任意 x 都有 x xor x == 0.

class Solution:
    def xorAllNums(self, nums1: List[int], nums2: List[int]) -> int:
        res = 0
        if len(nums2) % 2 == 1:
            for x in nums1:
                res = res ^ x
        if len(nums1) % 2 == 1:
            for x in nums2:
                res = res ^ x
        return res

4. 满足不等式的数对数目

image

最近我们用了很多次 SegmentTree 模板。这个题目有更精巧的解,但 SegmentTree 是这种不等式范围查询题目的捷径。

template <typename NUM>
struct SegmentTree {
    // a + b or max(a, b) or min(a, b)
    inline NUM func(NUM a, NUM b) { return a + b; }
    // VOID == 0 for sum, NUM_MAX for min, NUM_MIN for max
    const static NUM VOID = 0;

    int size;
    std::vector<NUM> tree;  // 1-indexed full tree
    inline NUM get(int idx) { return tree[idx + size]; }
    SegmentTree(std::vector<NUM>& data) { init(data); }

    // SegmentTree(int size) : size(size), tree(size * 2, VOID) {}
    // LeetCode didn't support below!!! use the this one instead:
    SegmentTree(int size) { this->size = size, this->tree.resize(size * 2); }

    void init(std::vector<NUM>& data) {
        size = int(data.size());
        tree.resize(size * 2);
        std::copy(data.begin(), data.end(), tree.begin() + size);
        for (int i = size - 1; i > 0; i--) {
            tree[i] = func(tree[i * 2], tree[i * 2 + 1]);
        }
    }

    void update(int idx, NUM val) {
        idx += size;
        tree[idx] = val;
        while (idx > 1) {
            idx /= 2;
            tree[idx] = func(tree[2 * idx], tree[2 * idx + 1]);
        }
    }

    NUM query(int left, int right) {
        left += size, right += size;
        NUM res = VOID;
        while (left <= right) {
            if (left % 2 == 1) res = func(res, tree[left++]);
            if (right % 2 == 0) res = func(res, tree[right--]);
            left /= 2, right /= 2;
        }
        return res;
    }
};

class Solution {
public:
    long long numberOfPairs(vector<int>& nums1, vector<int>& nums2, int diff) {
        // nums1[i] - nums1[j] <= nums2[i] - nums2[j] + diff
        // nums2[j] - nums1[j] <= nums2[i] - nums1[i] + diff

        int n = nums1.size();
        vector<int> delta(n);
        for(int i = 0; i < n; i++) delta[i] = nums2[i] - nums1[i];

        int size = 1E5 + 8, bias = 5E4;
        SegmentTree<int> st(size);
        for(int i = 0; i < n; i++) {
            int x = delta[i] + bias;
            st.update(x, st.get(x) + 1);
        }

        long long res = 0;
        for(int i = 0; i < n; i++) {
            int x = delta[i] + bias;
            st.update(x, st.get(x) - 1);
            res += st.query(0, delta[i] + diff + bias);
        }
        return res;
    }
};