难度困难15
给你一个长度为 n
的数组 nums
,该数组由从 1
到 n
的 不同 整数组成。另给你一个正整数 k
。
统计并返回 num
中的 中位数 等于 k
的非空子数组的数目。
注意:
[2,3,1,4]
的中位数是 2
,[8,4,3,5,1]
的中位数是 4
。示例 1:
输入:nums = [3,2,1,4,5], k = 4
输出:3
解释:中位数等于 4 的子数组有:[4]、[4,5] 和 [1,4,5] 。
示例 2:
输入:nums = [2,3,1], k = 3
输出:1
解释:[3] 是唯一一个中位数等于 3 的子数组。
提示:
n == nums.length
1 <= n <= 105
1 <= nums[i], k <= n
nums
中的整数互不相同题解:https://leetcode.cn/problems/count-subarrays-with-median-k/solution/deng-jie-zhuan-huan-pythonjavacgo-by-end-5w11/
class Solution:def countSubarrays(self, nums: List[int], k: int) -> int:# 展开成一个数学式子# 中位数 ==> (奇数长度) 小于 k 的数的个数 = 大于 k 的数的个数 # ==> k左侧小于k的个数 + k右侧小于k的个数 = k左侧大于k的个数 + k右侧大于k的个数# ==> + k左侧小于k的个数 - k左侧大于k的个数 = + k右侧大于k的个数 - k右侧小于k的个数# 用哈希表将k右边出现的数的次数统计下来,再k的左侧遍历 从右到左寻找个数# 偶数长度怎么办? 小于+1 = 大于# 左侧小于 + 右侧小于+1 = 左侧大于 + 右侧大于# 左侧小于 - 左侧大于+1 = + 右侧大于 - 右侧小于pos = nums.index(k) # 找到k的位置cnt = Counter() # int : int 的哈希表cnt[0] = 1 # 长度为1的个数有一个c = 0for i in range(pos+1, len(nums)):c += 1 if nums[i] > k else -1cnt[c] += 1c = 0ans = cnt[0] + cnt[1] # 加上 k 和 (k,k+i) 的个数for i in range(pos-1, -1, -1): # 从k左侧从右往左遍历c += 1 if nums[i] < k else -1ans += cnt[c] + cnt[c+1]return ans
可以注意到条件里说了:nums中的整数互不相同。
也就是说数组里只有一个k,那么我们可以想到,以k为中心向左右两边扩展求子数组。
class Solution {
public:int countSubarrays(vector& nums, int k) {int n=nums.size(),idx=-1;for(int i=0;ileft;left[0]=1;for(int i=idx-1;i>=0;i--){if(nums[i]