算法
可以用动态规划的思想去看,
设 S(i) 为以第 i 个元素结尾的和小于 N 的最长连续数组
设 len(i) 为 S(i) 的长度
设 sum(i) 为 S(i) 的和
- 边界:
- len(0) = arr[0] < N ? 1 : 0
- sum(0) = arr[0] (对于不可取的数(比 N 大)我们也把和记上)
- 当计算 S(i) 时,如果 arr[i] >= N,那么舍弃
- 否则
- 将 arr[i] 加入 S(i) 中(目前 len(i) 为 1, sum(i) 为 arr[i])
- 不停归并 S(i) 左边相邻的 S(i-len(i)) ,直到 sum(i) 不再小于 N
- 这里需要注意对于一些比 N 大的项原来不可取,现在也有可能取到
- 最后从 S(i) 最左的元素往右筛除,缩小数组直到总和小于 N
最后根据最长的 len 返回数组即可
public class LongestArr {int longestArr(int[] arr, int N){int[] len=new int[arr.length];int[] sum=new int[arr.length];for(int i=1;i<arr.length; i++){if(arr[i] >N){len[i]=0;sum[i] = arr[i];}else {len[i]=1;sum[i]=arr[i];for(int j=i;j>=0&&sum[i]<N;j=j-len[i]){sum[i]+=sum[j];len[i]+=len[j]|1;}for(int j=i+1-len[i]; j<i && sum[i]>=N; j++){len[i]-=1;sum[i]-=arr[j];}}}int max = 0;for(int i=0; i<len.length; i++){max=Math.max(len[i], max);}return max;}public static void main(String[] args) {LongestArr longestArr = new LongestArr();int[] arr = new int[]{-1,1,1,9};int N=10;System.out.println(longestArr.longestArr(arr, N)); //3int[] arr2 = new int[]{-1,1,1,9,-1};System.out.println(longestArr.longestArr(arr2, N)); //5}}
