统计中位数为K的子数组

给你一个长度为 n 的数组 nums ,该数组由从 1 到 n 的不同整数组成
另给你一个正整数 k ,统计并返回 nums 中的中位数等于 k 的非空子数组的数目

1. 前缀和 + 哈希

容易知道子数组必然包含数字k,其实就是列举包含k子数组,计算并且中位数为k的个数
同时列举两侧的复杂度是O(n2)级别,可以一侧先用哈希记录前缀和,只需遍历另一侧即可
左侧更小值 + 右侧更小值 = 左侧更大值 + 右侧更大值
变换一下即,左侧更小值-左侧更大值 = 右侧更大值 - 右侧更小值
先用哈希记录左侧不同数目值区间的个数,这里用前缀和,然后遍历右侧找满足条件的即可

class Solution {
public:
    int countSubarrays(vector<int> &nums, int k) {
        int pos = find(nums.begin(), nums.end(), k) - nums.begin(); //找k的位置
        // i=pos 的时候 x 是 0,直接记到 cnt 中,这样下面不是大于 k 就是小于 k
        unordered_map<int, int> cnt; //左侧区间各贡献值数量
        cnt[0] = 1;
        for (int i = pos - 1, x = 0; i >= 0; --i) { // 从 pos-1 开始累加 x
            x += nums[i] < k ? -1 : 1;  //小于贡献-1,大于贡献1 ,最终可以等于0或1
            ++cnt[x]; //记录左边贡献值,其实就是(i,pos)区间贡献值
        }

        // i=pos 的时候 x 是 0,直接加到答案中,这样下面不是大于 k 就是小于 k
        int ans = cnt[1] + cnt[0];
        for (int i = pos + 1, x = 0; i < nums.size(); i++) { // 从 pos+1 开始累加 x
            x += nums[i] > k ? -1 : 1; //右侧贡献值
            ans += cnt[x+1] + cnt[x];//匹配左侧值
        }
        return ans;
    }
};


posted @ 2023-05-17 19:30  失控D大白兔  阅读(31)  评论(0编辑  收藏  举报