数组和小于等于k的最长子数组长度b

题目描述​​

给定一个无序数组arr,其中元素可正、可负、可0。给定一个整数k,求arr所有的子数组中累加和小于或等于k的最长子数组长度。

​​示例​​

例如:arr = [3, -2, -4, 0, 6], k = -2,相加和小于等于-2的最长子数组为(3, -2, -4, 0),所以结果返回4。

​​要求​​

时间复杂度为O(n),空间复杂度为O(n)。

​​输入描述​​

第一行两个整数N, k,N表示数组长度,k的定义已在题目描述中给出。

第二行N个整数表示数组内的数。

​​输出描述​​

输出一个整数表示答案。

​​补充说明​​

1 ≤ N ≤ 10^5

-10° ≤ k ≤ 10° (注:原文本如此,可能意谓-10^9 ≤ k ≤ 10^9)

-100 ≤ arr[i] ≤ 100 (注:原文本为"-100 ≤ arr ≤ 100",可能指数组元素范围)

​​示例输入输出​​

示例1:

输入:

5 -2

3 -2 -4 0 6

输出:

4

思路

​​双指针遍历(l和r)​​:

​​l指针​​:遍历前缀和数组的起始位置(0到n)

​​r指针​​:在minb数组上移动,寻找满足条件minb[r] - b[l] <= k的最远位置

​​移动逻辑​​:

对于每个l,不断右移r,直到minb[r] - b[l] > k或r越界

此时,r-1是满足条件的最远位置

​​子数组长度计算​​:

子数组对应原数组下标[l, r-2]

长度 = (r-2) - l + 1 = r - l - 1

示例

示例说明

以示例arr = [3, -2, -4, 0, 6], k = -2为例:

​​前缀和数组b​​:

b[0] = 0

b[1] = 3

b[2] = 3 + (-2) = 1

b[3] = 1 + (-4) = -3

b[4] = -3 + 0 = -3

b[5] = -3 + 6 = 3

​​minb数组​​(从后往前计算):

minb[5] = b[5] = 3

minb[4] = min(b[4], minb[5]) = min(-3, 3) = -3

minb[3] = min(b[3], minb[4]) = min(-3, -3) = -3

minb[2] = min(b[2], minb[3]) = min(1, -3) = -3

minb[1] = min(b[1], minb[2]) = min(3, -3) = -3

minb[0] = min(b[0], minb[1]) = min(0, -3) = -3

​​双指针遍历过程​​:

​​l=0​​:

r从0开始移动:

r=0: minb[0]-b[0]=-3-0=-3 <= -2→ r=1

r=1: minb[1]-b[0]=-3-0=-3 <= -2→ r=2

r=2: minb[2]-b[0]=-3-0=-3 <= -2→ r=3

r=3: minb[3]-b[0]=-3-0=-3 <= -2→ r=4

r=4: minb[4]-b[0]=-3-0=-3 <= -2→ r=5

r=5: minb[5]-b[0]=3-0=3 > -2→ 停止

子数组长度 = r - l - 1 = 5 - 0 - 1 = 4

​​l=1到5​​:无法找到更长满足条件的子数组

​​结果​​:最大长度4(对应子数组[3, -2, -4, 0])

Code

java 复制代码
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int n = in.nextInt();
        int k = in.nextInt();
        int[] a = new int[n];
        int[] b = new int[n+1];
        for(int i=0;i<n;i++) {
            a[i] = in.nextInt();
            if(i == 0) b[i+1] = a[i];
            else b[i+1] = b[i] + a[i];
        }
        int[] minb = new int[n+1];  // minb[i]标识从[i, n]区间内的最小前缀和, 是单调递减的。
        minb[n] = b[n];
        for(int i=n-1;i>=0;i--) {
            minb[i] = Math.min(b[i], minb[i+1]);
        }
        int res = 0;
        int r = 0;
        for(int l=0;l<=n;l++) {
            while(r <= n && minb[r] - b[l] <= k) r ++;
            if(r > l) {
                res = Math.max(res, r-2-l+1);   // r-1才是满足条件的,但是minb下标和a错一位,所以真实下标为r-2
            }
        }
        System.out.println(res);
    }
}
相关推荐
Learner7 分钟前
Python异常处理
java·前端·python
AI科技星10 分钟前
光速飞行器动力学方程的第一性原理推导、验证与范式革命
数据结构·人工智能·线性代数·算法·机器学习·概率论
tao35566711 分钟前
VS Code登录codex,报错(os error 10013)
java·服务器·前端
橘颂TA12 分钟前
【剑斩OFFER】算法的暴力美学——leetCode 946 题:验证栈序列
c++·算法·leetcode·职场和发展·结构与算法
闻缺陷则喜何志丹14 分钟前
【状态机动态规划】3686. 稳定子序列的数量|1969
c++·算法·动态规划·力扣·状态机动态规划
信创天地17 分钟前
核心系统去 “O” 攻坚:信创数据库迁移的双轨运行与数据一致性保障方案
java·大数据·数据库·金融·架构·政务
mjhcsp20 分钟前
C++ AC 自动机:原理、实现与应用全解析
java·开发语言·c++·ac 自动机
huihuihuanhuan.xin21 分钟前
后端八股之java并发编程
java·开发语言
茶本无香24 分钟前
设计模式之二—原型模式:灵活的对象克隆机制
java·设计模式·原型模式
寻星探路25 分钟前
【算法通关】双指针技巧深度解析:从基础到巅峰(Java 最优解)
java·开发语言·人工智能·python·算法·ai·指针