未排序数组中累加和小于或等于给定值的最长子数组长度

链接
来源:牛客网

给定一个无序数组arr,其中元素可正、可负、可0。给定一个整数k,求arr所有的子数组中累加和小于或等于k的最长子数组长度
例如:arr = [3, -2, -4, 0, 6], k = -2. 相加和小于等于-2的最长子数组为{3, -2, -4, 0},所以结果返回4
[要求]
时间复杂度为O(n),空间复杂度为O(n)

import java.util.*;

public class Main {

    private static int solve(int[] arr, int k) {

        int n = arr.length;

        int[] minSum = new int[n];
        int[] minSumEnd = new int[n];
        minSum[n - 1] = arr[n - 1];
        minSumEnd[n - 1] = n - 1;

        for (int i = n - 2; i >= 0; --i) {
            if (minSum[i + 1] <= 0) {
                minSum[i] = minSum[i + 1] + arr[i];
                minSumEnd[i] = minSumEnd[i + 1];
            } else {
                minSum[i] = arr[i];
                minSumEnd[i] = i;
            }
        }

        int ret = 0;

        int sum = 0;
        int end = 0;

        for (int i = 0; i < n; ++i) {
            while (end < n && sum + minSum[end] <= k) {
                sum += minSum[end];
                end = minSumEnd[end] + 1;
            }

            ret = Math.max(ret, end - i);

            /**
             * 说明没扩展成功
             */
            if (i == end) {
                end = i + 1;
            } else {
                sum -= arr[i];
            }
        }

        return ret;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            int n = in.nextInt();
            int k = in.nextInt();
            int[] arr = new int[n];
            for (int i = 0; i < n; ++i) {
                arr[i] = in.nextInt();
            }
            System.out.println(solve(arr, k));
        }
    }
}
posted @ 2021-10-12 23:26  Tianyiya  阅读(147)  评论(0)    收藏  举报