
2026-06-08:开销小于等于 K 的子数组数目。用go语言,给定整数数组 nums 和整数 k。 对数组中任意一个连续非空子数组 nums[l..r],先找出该子数组的最大值 max 和最小值 min。然后用它们的差值乘以子数组长度 (r - l + 1),得到该子数组的“代价”。
题目要求:统计 nums 里所有子数组中,代价不超过 k 的子数组一共有多少个,并返回这个数量。
1 <= nums.length <= 100000。
1 <= nums[i] <= 1000000000。
0 <= k <= 1000000000000000。
输入: nums = [1,3,2], k = 4。
输出: 5。
解释:
考虑 nums 的所有子数组:
nums[0..0]: cost = (1 - 1) * 1 = 0
nums[0..1]: cost = (3 - 1) * 2 = 4
nums[0..2]: cost = (3 - 1) * 3 = 6
nums[1..1]: cost = (3 - 3) * 1 = 0
nums[1..2]: cost = (3 - 2) * 2 = 2
nums[2..2]: cost = (2 - 2) * 1 = 0
共有 5 个子数组的开销小于或等于 4。
题目来自力扣3835。
初始状态:
left = 0minQ空,最大队列maxQ空ans = 0minQ = [0](队首是当前最小值)maxQ = [0](队首是当前最大值)当前窗口[0,0]:
最大值=1,最小值=1,差值=0
长度=1
代价=0×1=0 ≤4 → 窗口合法,不移动左指针
以right=0结尾的合法子数组:只有[0,0]
答案累加:ans = 0 + 1 = 1
minQ = [0,1]maxQ = [1]当前窗口[0,1]:
最大值=3(队首1),最小值=1(队首0),差值=2
长度=2
代价=2×2=4 ≤4 → 窗口合法,不移动左指针
以right=1结尾的合法子数组:[0,1]、[1,1] → 共2个
答案累加:ans = 1 + 2 = 3
[0],2 ≥ 下标0对应的值1,加入 → minQ = [0,2]maxQ = [1,2]当前窗口[0,2]:
最大值=3(队首1),最小值=1(队首0),差值=2
长度=3
代价=2×3=6 >4 → 窗口不合法
left = 1minQ = [2]现在窗口[1,2]:
最大值=3(队首1),最小值=2(队首2),差值=1
长度=2
代价=1×2=2 ≤4 → 窗口合法,停止移动左指针
以right=2结尾的合法子数组:[1,2]、[2,2] → 共2个
答案累加:ans = 3 + 2 = 5
最终总答案 = 5,和题目输出完全一致。
left和right只会向右移动,绝不回退,总共最多移动2n次;n成正比。n个元素;.
package main
import (
"fmt"
)
func countSubarrays(nums []int, k int64) (ans int64) {
var minQ, maxQ []int
left := 0
for right, x := range nums {
// 1. 入:元素进入窗口
forlen(minQ) > 0 && x <= nums[minQ[len(minQ)-1]] {
minQ = minQ[:len(minQ)-1]
}
minQ = append(minQ, right)
forlen(maxQ) > 0 && x >= nums[maxQ[len(maxQ)-1]] {
maxQ = maxQ[:len(maxQ)-1]
}
maxQ = append(maxQ, right)
// 2. 出:如果窗口不满足要求,左端点离开窗口
// 只需改下面这行代码,其余逻辑和 2762 题完全一致
forint64(nums[maxQ[0]]-nums[minQ[0]])*int64(right-left+1) > k {
left++
if minQ[0] < left {
minQ = minQ[1:]
}
if maxQ[0] < left {
maxQ = maxQ[1:]
}
}
// 3. 更新答案
ans += int64(right - left + 1)
}
return
}
func main() {
nums := []int{1, 3, 2}
k := 4
result := countSubarrays(nums, int64(k))
fmt.Println(result)
}

.
# -*-coding:utf-8-*-
from collections import deque
def countSubarrays(nums, k):
ans = 0
minQ = deque()
maxQ = deque()
left = 0
for right, x in enumerate(nums):
# 1. 入:元素进入窗口
while minQ and x <= nums[minQ[-1]]:
minQ.pop()
minQ.append(right)
while maxQ and x >= nums[maxQ[-1]]:
maxQ.pop()
maxQ.append(right)
# 2. 出:如果窗口不满足要求,左端点离开窗口
while maxQ and minQ and (nums[maxQ[0]] - nums[minQ[0]]) * (right - left + 1) > k:
left += 1
if minQ and minQ[0] < left:
minQ.popleft()
if maxQ and maxQ[0] < left:
maxQ.popleft()
# 3. 更新答案
ans += right - left + 1
return ans
def main():
nums = [1, 3, 2]
k = 4
result = countSubarrays(nums, k)
print(result)
if __name__ == "__main__":
main()
.
#include <iostream>
#include <vector>
#include <deque>
using namespace std;
long long countSubarrays(vector<int>& nums, long long k) {
long long ans = 0;
deque<int> minQ, maxQ;
int left = 0;
for (int right = 0; right < nums.size(); right++) {
int x = nums[right];
// 1. 入:元素进入窗口
while (!minQ.empty() && x <= nums[minQ.back()]) {
minQ.pop_back();
}
minQ.push_back(right);
while (!maxQ.empty() && x >= nums[maxQ.back()]) {
maxQ.pop_back();
}
maxQ.push_back(right);
// 2. 出:如果窗口不满足要求,左端点离开窗口
while (!minQ.empty() && !maxQ.empty() &&
(long long)(nums[maxQ.front()] - nums[minQ.front()]) * (right - left + 1) > k) {
left++;
if (!minQ.empty() && minQ.front() < left) {
minQ.pop_front();
}
if (!maxQ.empty() && maxQ.front() < left) {
maxQ.pop_front();
}
}
// 3. 更新答案
ans += (right - left + 1);
}
return ans;
}
int main() {
vector<int> nums = {1, 3, 2};
long long k = 4;
long long result = countSubarrays(nums, k);
cout << result << endl;
return0;
}

·
我们相信人工智能为普通人提供了一种“增强工具”,并致力于分享全方位的AI知识。在这里,您可以找到最新的AI科普文章、工具评测、提升效率的秘籍以及行业洞察。