Java 如何找到数组';将元素转换为特定值?
在Java中,如何找到与特定值K最接近(或相等)的数组元素和 例如,对于数组{19,23,41,5,40,36}和K=44,最接近的可能和是23+19=42。Java 如何找到数组';将元素转换为特定值?,java,arrays,algorithm,dynamic-programming,Java,Arrays,Algorithm,Dynamic Programming,在Java中,如何找到与特定值K最接近(或相等)的数组元素和 例如,对于数组{19,23,41,5,40,36}和K=44,最接近的可能和是23+19=42。 我已经为此奋斗了几个小时;我对动态规划几乎一无所知。顺便说一句,数组只包含正数。我想先对数组进行排序。那么您的示例是:arr={5,19,23,36,40,41}。 然后: 1) 取arr[0]和arr[i],其中i=arr.Size。如果总和小于K,则求和并记录总和与K之间的差值。 2) 如果sum>K,则执行步骤1,但不使用arr[i
我已经为此奋斗了几个小时;我对动态规划几乎一无所知。顺便说一句,数组只包含正数。我想先对数组进行排序。那么您的示例是:arr={5,19,23,36,40,41}。 然后: 1) 取arr[0]和arr[i],其中i=arr.Size。如果总和小于K,则求和并记录总和与K之间的差值。 2) 如果sum>K,则执行步骤1,但不使用arr[i],而是使用arr[i-1],因为我们希望降低sum。 如果sum
使用不同的TopNode执行步骤1-3。您通常会使用动态编程解决此类问题。然而,这本质上归结为保留一组可能的和,并将输入值逐个相加,如以下代码所示,并且具有相同的渐近运行时间:
O(nk)
,其中n
是输入数组的大小,K
是目标值
然而,下面版本中的常量可能更大,但我认为代码比动态编程版本更容易理解
public class Test {
public static void main(String[] args) {
int K = 44;
List<Integer> inputs = Arrays.asList(19,23,41,5,40,36);
int opt = 0; // optimal solution so far
Set<Integer> sums = new HashSet<>();
sums.add(opt);
// loop over all input values
for (Integer input : inputs) {
Set<Integer> 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);
}
}
现在初始化为:
SubList opt = new SubList();
Set<SubList> sums = new HashSet<>();
sums.add(opt);
对于所有可能的
k
问题,您可以将其视为一个n-choose-k
问题,因此复杂性很高
K
的数字。对于i=1,集合应包括i
数字;iprivate int closestSum(int[]a,int num){
int k=a.长度-1;
整数和=0;
数组。排序(a);
while(a[k]>num){
k--;
}
对于(inti=0;这是一个公平的问题,但可能更适合这里:5+40不是最接近的总和吗?我的意思是,总和将小于或等于KIs,你可以加起来的数字有一个限制吗?例如,你能不能每个总和只使用两个元素,或者你能不能对所有元素都使用总和?如果我理解正确,这将不会是正确地解决他的问题;举个例子[1,2,10]搜索13。@Calpis,但是如果结果中有两个以上的数字呢?哦,对不起,我没有意识到这是一个任意的数字。让我重新思考一下。我阅读了你的解决方案并试图理解,也许我的问题很愚蠢,但我可以看到你在最终解决方案中添加了一个数字,但我看不到的是你在哪里排除我希望,在某个时刻,你应该意识到,为了得到更好的解决方案,应该排除一个包含的数字,不是吗?@zafeiris.m我只跟踪和,而不是它们组成的值。基本上,在外循环的迭代I
之后(超过输入
),集合总和
包含所有可以用第一个i
输入值进行的总和。为了确保该集合的大小不会呈指数增长,我添加了上限
,以确保总和
最多包含2*K
值。但如果最佳解决方案不包括第一个值,该怎么办i
元素,但是,比如说,第1、第4和第6个?@Heuster谢谢,我现在可以看到了,很好的解决方案!但我不理解的是最坏情况的复杂性。在您的评论示例中(在任何示例中,大多数元素都将包含在结果中),我看到结果集每次都加倍,导致指数复杂性,不是吗?告诉我我是否错了。更新:空间复杂性也是指数的,因为你保留每个子结果,对吗?@zafeiris.m我添加了一个关于运行时间的注释。诀窍在于上限
,它使和
的大小在K
中保持线性>.
SubList opt = new SubList();
Set<SubList> sums = new HashSet<>();
sums.add(opt);
for (Integer input : inputs) {
Set<SubList> newSums = new HashSet<>();
// loop over all sums so far
for (SubList sum : sums) {
List<Integer> 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);
}
private int closestSum(int[] a, int num){
int k=a.length-1;
int sum=0;
Arrays.sort(a);
while(a[k]>num){
k--;
}
for(int i=0;i<k;i++){
for(int j=i+1;j<=k;j++){
if(a[i]+a[j]<=num && a[i]+a[j]>sum)
sum = a[i]+a[j];
}
}
return sum;
}