• 難度分: 1786
  • 我覺得這一題稍有難度,主要在處理 findKth 方法時,有一些技巧,如果單純用 vector 來記錄 window,會 LTE,因為 nums[i] 的範圍滿小的(-50~50之間),可以用 bucket sort,如果數字再更大一點,可以使用 fenwick tree 或是 segment tree 範圍求和,使 updatequery 的複雜度都是 log(n)\log(n)
  • Bucket Sort
class NumberTracker {
public:
    virtual void update(int num, int delta) = 0;
    virtual int findKth(int k) = 0;
    virtual ~NumberTracker() {}
};

class BucketSort : public NumberTracker {
private:
    vector<int> cnt;
    int left_;
    int right_;
    int n_;
public:
    BucketSort(int left, int right) {
        left_ = left;
        right_ = right;
        n_ = right - left + 1;
        cnt.assign(n_, 0);
    }

    void update(int num, int delta) override {
        cnt[num - left_] += delta;
    }

    int findKth(int k) override {
        int total = 0;
        for (int i = 0; i <= n_; i++) {
            total += cnt[i];
            if (total >= k) {
                return i + left_;
            }
        }
        return -1;
    }
};

class Solution {
private: 
    unique_ptr<NumberTracker> tracker;
public:
    Solution() : tracker(make_unique<BucketSort>(-50, 50)) {}
    
    vector<int> getSubarrayBeauty(vector<int>& nums, int k, int x) {
        int n = nums.size();
        vector<int> res;
        for (int i = 0; i < k; i++) {
            tracker->update(nums[i], 1);
        }
        int ans = tracker->findKth(x);
        res.push_back(min(ans, 0));
        for (int i = k; i < n; i++) {
            tracker->update(nums[i-k], -1);
            tracker->update(nums[i], 1);
            ans = tracker->findKth(x);
            res.push_back(min(ans, 0));
        }
        return res;
    }
};
  • Fenwick Tree
class FenwickTree : public NumberTracker {
private:
    int left_;
    int right_;
    int n_;
    vector<int> bit;
    int lowbit(int a) {
        return a & (-a);
    }
    void add(int idx, int diff) {
        idx++;
        int n = bit.size();
        while (idx < n) {
            bit[idx] += diff;
            idx += lowbit(idx);
        }
    }

    int query(int idx) {
        int sum = 0;
        idx++;
        while (idx > 0) {
            sum += bit[idx];
            idx -= lowbit(idx);
        }
        return sum;
    }
public:
    FenwickTree(int left, int right) {
        left_ = left;
        right_ = right;
        n_ = right - left + 1;
        bit.assign(n_ + 1, 0);
    }
    void update(int num, int delta) {
        num -= left_;
        add(num, delta);
    }
    int findKth(int k) {
        int left = 0;
        int right = n_;
        while (left < right) {
            int mid = (left + right) >> 1;
            if (query(mid) >= k) 
                right = mid;
            else
                left = mid + 1;
        }
        return min(0, left + left_);
    }
};
  • Segment Tree (zkw tree)
class NumberTracker {
public:
    virtual void build(vector<int> nums) = 0;
    virtual void update(int num, int delta) = 0;
    virtual int findKth(int k) = 0;
    virtual ~NumberTracker() {}
};

class SegmentTree : public NumberTracker {
private:
    int n_;
    int m_;
    vector<int> tree_;
    unordered_map<int,int> num_to_idx;
    unordered_map<int,int> idx_to_num;
    int lowbit(int a) {
        return a & (-a);
    }
    
public:
    SegmentTree() {}
    void build(vector<int> nums) override {
        sort(nums.begin(), nums.end());
        for (int i = 0, j = 0; i < nums.size(); i++) {
            if (i > 0 && nums[i] == nums[i-1]) continue;
            num_to_idx[nums[i]] = j;
            idx_to_num[j++] = nums[i];
        }
        for (n_ = 1; n_ < num_to_idx.size(); n_ <<= 1);
        m_ = n_ << 1;
        tree_.assign(m_, 0);
    }
    void update(int num, int delta) override {
        int idx = num_to_idx[num];
        idx += n_;
        while (idx > 0) {
            tree_[idx] += delta;
            idx >>= 1;
        }
    }
    int findKth(int k) override {
        int idx = 1;
        while (idx < n_) {
            idx <<= 1;
            if (tree_[idx] < k) {
                k -= tree_[idx];
                idx++;
            }
        }
        return idx_to_num[idx - n_];
    }
};

class Solution {
private: 
    unique_ptr<NumberTracker> tracker;
public:
    Solution() : tracker(make_unique<SegmentTree>()) {}
    
    vector<int> getSubarrayBeauty(vector<int>& nums, int k, int x) {
        tracker->build(nums);
        int n = nums.size();
        vector<int> res;
        for (int i = 0; i < k; i++) {
            tracker->update(nums[i], 1);
        }
        int ans = tracker->findKth(x);
        res.push_back(min(ans, 0));
        for (int i = k; i < n; i++) {
            tracker->update(nums[i-k], -1);
            tracker->update(nums[i], 1);
            ans = tracker->findKth(x);
            res.push_back(min(ans, 0));
        }
        return res;
    }
};