DeepSeek LeetCode 2488. 统计中位数为 K 的子数组 TypeScript实现
·
以下是 LeetCode 2488 的 TypeScript 实现,使用哈希表统计左右两侧的平衡值:
function countSubarrays(nums: number[], k: number): number {
const n = nums.length;
let pos = -1;
// 找到 k 的位置
for (let i = 0; i < n; i++) {
if (nums[i] === k) {
pos = i;
break;
}
}
// 哈希表存储左边出现的平衡值及次数
const leftMap = new Map<number, number>();
leftMap.set(0, 1); // 空子数组(只包含 k 自身)
let balance = 0;
// 向左遍历,统计平衡值
for (let i = pos - 1; i >= 0; i--) {
if (nums[i] > k) {
balance++;
} else if (nums[i] < k) {
balance--;
}
leftMap.set(balance, (leftMap.get(balance) || 0) + 1);
}
let result = 0;
balance = 0;
// 向右遍历并统计
for (let i = pos; i < n; i++) {
if (i > pos) { // 避免重复处理 pos 位置
if (nums[i] > k) {
balance++;
} else if (nums[i] < k) {
balance--;
}
}
// 奇数长度子数组:leftBalance + rightBalance = 0
// 偶数长度子数组(k在左中位):leftBalance + rightBalance = 1
result += (leftMap.get(-balance) || 0);
result += (leftMap.get(1 - balance) || 0);
}
return result;
}
优化版本(使用数组代替 Map,适合数值范围较小的情况):
function countSubarrays(nums: number[], k: number): number {
const n = nums.length;
let pos = -1;
for (let i = 0; i < n; i++) {
if (nums[i] === k) {
pos = i;
break;
}
}
// 使用对象存储(更简洁)
const leftCount: Record<number, number> = { 0: 1 };
let balance = 0;
for (let i = pos - 1; i >= 0; i--) {
balance += nums[i] > k ? 1 : (nums[i] < k ? -1 : 0);
leftCount[balance] = (leftCount[balance] || 0) + 1;
}
let result = 0;
balance = 0;
for (let i = pos; i < n; i++) {
if (i > pos) {
balance += nums[i] > k ? 1 : (nums[i] < k ? -1 : 0);
}
// 两种情况
result += (leftCount[-balance] || 0);
result += (leftCount[1 - balance] || 0);
}
return result;
}
测试用例:
// 示例 1
console.log(countSubarrays([3,2,1,4,5], 4)); // 输出: 3
// 示例 2
console.log(countSubarrays([2,3,1], 3)); // 输出: 1
// 示例 3
console.log(countSubarrays([1,2,3,4,5], 3)); // 输出: 2
关键点说明:
- 平衡值的定义:
balance = (大于k的数量) - (小于k的数量) - 中位数条件:
- 奇数长度子数组:左边平衡 + 右边平衡 = 0
- 偶数长度子数组:左边平衡 + 右边平衡 = 1(k 在左中位)
- 哈希表存储:记录从 k 向左的所有平衡值的出现次数
- 向右遍历:对每个右边界,查找满足条件的左边界数量
时间复杂度:O(n),空间复杂度:O(n)
更多推荐





所有评论(0)