Java 带阈值的最大和子序列

Java 带阈值的最大和子序列,java,arrays,algorithm,recursion,dynamic-programming,Java,Arrays,Algorithm,Recursion,Dynamic Programming,给定一个整数数组,求小于或等于给定阈值的子序列的最大和 承包商: 数组的最大大小为10^5 数组中的元素为10^9时的最大大小 阈值在1到10^9的范围内 e、 g. 输入: 1 2 4 5 十, 输出: 十, 在上面的示例中,数组是[1,2,4,5],阈值是10。最大和子序列为10,由(1,4,5)组成 导入java.util.array; 公共类MaxSumSubsequenceWithThreshold{ 类解决方案{ int[]A; int阈值; 整数[][]dp; 解决方案(int[]

给定一个整数数组,求小于或等于给定阈值的子序列的最大和

承包商:
数组的最大大小为10^5
数组中的元素为10^9时的最大大小
阈值在1到10^9的范围内

e、 g.
输入:
1 2 4 5
十,

输出:
十,

在上面的示例中,数组是[1,2,4,5],阈值是10。最大和子序列为10,由(1,4,5)组成

导入java.util.array;
公共类MaxSumSubsequenceWithThreshold{
类解决方案{
int[]A;
int阈值;
整数[][]dp;
解决方案(int[]A,int阈值){
this.A=A;this.threshold=threshold;
dp=新整数[A.length][threshold+1];
}
整数和(整数位置,整数阈值){

如果(threshold为获得更好的性能,我将只循环一次值,并将跟踪
TreeSet
中以前的所有总和

作为一个
集合
会自动消除重复的总和。例如,如果输入是
[1,3,4,7]
,那么当我们处理7时,前面看到的总和将是
[1,3,4,1+3,1+4,3,3+4,3+4]=[1,3,4,4,5,7,8]=[1,3,4,5,7,8]
,其中已消除重复总和
4
。防止冗余处理

如果我们找到一个等于
阈值的和,我们应该停止查找。这称为短循环。如果我们已经找到了最大可能的和,则无需继续查找。例如,如果
threshold=8
,我们将跳过
7
值的处理,因为我们已经找到了一个等于
阈值的和,即
1+3+4=8

作为<代码> SoReSETTSE/COD>允许我们找到一个可以添加到当前正在处理的值的子集。例如,如果<代码>阈值= 10 < /代码>,当我们处理<代码> 7 < /代码>时,我们查找<潜在的短路>代码> 3 /代码>,然后只需要考虑范围<代码> 1 < /代码> -<代码> 2 < /代码>中的先前和,因此我们可以调用<代码>t(1,3)

来获取这些

虽然问题没有明确说明,但是我们认为空序列是有效的,这意味着<代码> 0 <代码>是一个有效的结果,如果我们没有找到一个解决方案。这很容易防范

使用上述逻辑,我们不会添加超过
阈值的总和。例如,如果
阈值=6
,则完成后,上述集合将包含
[1,3,4,5]
。然后,我们可以调用
last()
来查找最大总和

以下是所有这些的代码:

静态整数最大和(整数阈值,整数…值){
树集和=新树集();
for(int值:值){
如果(值==阈值)
返回阈值;//短路
如果(值<阈值){
if(总和包含(阈值))
返回阈值;//短路
for(int prevSum:sums.subSet(1,阈值).toArray(新整数[0]))
总和。相加(前总和+值);
增加(价值);
}
}
返回(sums.isEmpty()?0:sums.last().intValue());
}
注意:我们不能在迭代子集时添加到
,因此我们需要子集的副本。
toArray()
是获得此类副本的最快方法

测验

System.out.println(最大和(10,1,2,4,5));
系统输出println(最大和(8,1,3,4,7));
系统输出println(最大和(10,1,3,4,7));
系统输出println(最大和(6,1,3,4,7));
系统输出println(最大和(3,5,7,9));
输出

10
8.
10
5.
0

为了获得更好的解决方案,不要使用递归。阈值是否有限制,例如,
1在说明中添加了阈值范围。
import java.util.Arrays;

public class MaxSumSubsequenceWithThreshold {

    class Solution {
        int[] A;
        int threshold;
        Integer[][] dp;
        Solution(int[] A, int threshold) {
            this.A = A; this.threshold = threshold;
            dp = new Integer[A.length][threshold + 1];
        }

        int sum(int pos, int threshold) {
            if (threshold <= 0) return 0;
            if (threshold - A[pos] < 0) return dp[pos][threshold] = Integer.MIN_VALUE;
            if (dp[pos][threshold] != null) return dp[pos][threshold];
            int sum = 0;
            int max = Integer.MIN_VALUE;
            for (int i = pos + 1; i < A.length; i++) {
                sum = sum(i, threshold - A[pos]);
                max = Math.max(max, sum);
            }
            return dp[pos][threshold] = max == Integer.MIN_VALUE ? A[pos] : max + A[pos];
        }

        int solve() {
            Arrays.sort(A);
            int max = Integer.MIN_VALUE;
            for (int i = 0; i < A.length; i++) {
                dp[i][threshold] = sum(i, threshold);
                max = Math.max(max, dp[i][threshold]);
            }
            return max;
        }

    }

    public static void main(String[] args) {
        int[] A = InputUtils.nextIntLine();
        int threshold = InputUtils.nextInt();
        System.out.println(
                new MaxSumSubsequenceWithThreshold().new Solution(A, threshold).solve()
        );
    }

}