调java用数组元素_java – 如何找到数组元素与特定值最接近的总和?

该博客讨论了一种使用动态规划求解寻找输入数组中元素之和最接近目标值的方法。代码示例展示了如何通过维护可能的总和集合,并在每一步中更新最优解,算法的时间复杂度为O(nK),其中n是输入数组大小,K为目标值上限。此外,文中还提供了如何找到导致最优总和的元素的改进方法。
摘要由CSDN通过智能技术生成

您通常会使用动态编程来解决此类问题.但是,这基本上归结为保持一组可能的总和并逐个添加输入值,如下面的代码所示,并具有相同的渐近运行时间:O(n K),其中n是输入的大小数组和K是目标值.

但是,下面版本中的常量可能更大,但我认为代码比动态编程版本更容易理解.

public class Test {

public static void main(String[] args) {

int K = 44;

List inputs = Arrays.asList(19,23,41,5,40,36);

int opt = 0; // optimal solution so far

Set sums = new HashSet<>();

sums.add(opt);

// loop over all input values

for (Integer input : inputs) {

Set newSums = new HashSet<>();

// loop over all sums so far

for (Integer sum : sums) {

int newSum = sum + input;

// ignore too big sums

if (newSum <= K) {

newSums.add(newSum);

// update optimum

if (newSum > opt) {

opt = newSum;

}

}

}

sums.addAll(newSums);

}

System.out.println(opt);

}

}

编辑

关于运行时间的简短说明可能是有用的,因为我只是声称O(n K)没有正当理由.

显然,初始化和打印结果只需要一个恒定的时间,所以我们应该分析双循环.

外循环遍历所有输入,因此它的主体被执行n次.

到目前为止,内循环遍及所有总和,理论上可能是指数.但是,我们使用K的上限,因此所有和的值都在[0,K]范围内.由于sum是一个集合,它最多包含K 1个元素.

内循环内的所有计算都需要恒定的时间,因此总循环需要O(K).由于同样的原因,set newSums还包含最多K 1个元素,因此最后的addAll也需要O(K).

结束:外循环执行n次.循环体取O(K).因此,算法在O(n K)中运行.

编辑2

根据请求如何找到导致最佳总和的元素:

而不是跟踪单个整数 – 子列表的总和 – 您还应该跟踪子列表本身.如果您创建一个新类型(没有getter / setters来保持示例简洁),这是相对简单的:

public class SubList {

public int size;

public List subList;

public SubList() {

this(0, new ArrayList<>());

}

public SubList(int size, List subList) {

this.size = size;

this.subList = subList;

}

}

现在初始化变为:

SubList opt = new SubList();

Set sums = new HashSet<>();

sums.add(opt);

总和上的内循环也需要一些小的调整:

for (Integer input : inputs) {

Set newSums = new HashSet<>();

// loop over all sums so far

for (SubList sum : sums) {

List newSubList = new ArrayList<>(sum.subList);

newSubList.add(input);

SubList newSum = new SubList(sum.size + input, newSubList);

// ignore too big sums

if (newSum.size <= K) {

newSums.add(newSum);

// update optimum

if (newSum.size > opt) {

opt = newSum;

}

}

}

sums.addAll(newSums);

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值