如何找到最接近零的数组中两个元素的总和

时间:2015-08-09 10:31:16

标签: java

如何从数组中找到两个元素,其总和最接近零而不是零(注意:-1最接近零而不是+2)。我试过这个...

 int a[]=new int[n];
 int b[]=new int[2];
 int prev=0;
 for(int i=0;i<n;a[i++]=in.nextInt());
 for(int i=0;i<a.length;i++){
     for(int j=i+1;j<a.length;j++){
         int sum=a[i]+a[j];
         if(prev==0)
             prev=sum;
         if(sum > 0){
             if(sum < prev ){
                 prev=sum;
                 b[0]=a[i];
                 b[1]=a[j];
             }
         }
         else if(sum < 0){
             if(-sum < prev){
                 prev=sum;
                 b[0]=a[i];
                 b[1]=a[j];
             }
         }
     }
 }

    Sop(b[0]+" "+b[1]);

3 个答案:

答案 0 :(得分:1)

你可以尝试:

 int a[]=new int[n];
 int b[]=new int[2];
 int prev=0;
 for(int i=0;i<n;a[i++]=in.nextInt());
 for(int i=0;i<a.length;i++){
     for(int j=i+1;j<a.length;j++){
         int sum=a[i]+a[j];
         if(prev==0)
             prev=sum;
         if(Math.abs(sum)>0 && Math.abs(sum)<Math.abs(prev)){
            prev=sum;
            b[0]=a[i];
            b[1]=a[j];
         }
     }
 }

Sop(b[0]+" "+b[1]);

答案 1 :(得分:1)

我有一些评论,你使用3 for循环,可以改进为2个嵌套for循环(用于选择当前元素的外循环和用于与其他元素进行比较的内循环)。

此外,您还有多个if测试,以检查总和现在是否接近零,然后是前一个总和。但是,如果测试可以通过获取总和的绝对值而不是在sum > 0sum < 0上进行测试,那么这些测试可以减少到只有一个,这对于可读性来说是好的。

这就是我提出的:

int array[] = new int[5];
array[0] = -3; array[1] = -2; array[2] = -1; array[3] = 1; array[4] = 2; // Fill array

int idx[] = new int[2]; // Will store the result (index of the two elements that need to be added)
double lowest_sum = Double.POSITIVE_INFINITY; // Of type double to be able to use infinity

for(int i = 0; i < array.length; i++) {
    // Outer loop --> Uses a current (array[i]) from left to right
    int current = array[i];
    for(int j = i+1; j < array.length; j++) {
        // Inner loop --> Check all elements we didn't used as current till now
        int compare_with = array[j];
        if((Math.abs(current + compare_with) < lowest_sum) && ((current + compare_with) != 0)) {
            // We found two elements whose sum is closer to zero
            lowest_sum = Math.abs(current + compare_with);
            idx[0] = i; // Index of the first element to add
            idx[1] = j; // Index of second element to add
        }
    }
}

int res_idx1 = idx[0];
int res_idx2 = idx[1];
System.out.println("The first element to add is : " + array[res_idx1] + "\nThe second element to add is : " + array[res_idx2]);

输入:数组= [ - 3,-2,-1,1,2] ,输出:要添加的第一个元素是:-3, 要添加的第二个元素是:2

请注意,此代码将打印解决方案,而不是所有解决方案(如果存在多个解决方案)。编辑代码以使其返回所有解决方案应该是相当简单的。

答案 2 :(得分:1)

这个问题可以在O(N * log(N))中解决。在这种情况下,最昂贵的操作是对数组进行排序。如果您的域允许您使用非比较类别,例如counting sort,那么您将能够将整个解决方案的时间复杂度降低到线性时间。

我们的想法是,在排序数组中,您可以并行地按升序和降序迭代元素,从而找到线性时间内具有最小/最大和的所有对。这种方法应用于您的任务的唯一缺点是您需要找到总和的最小绝对值,这意味着在正和之间找到最小值,在负和之间找到最大值。这将需要两次线性传球。

我的解决方案如下。它在针对暴力O(N ^ 2)解决方案的随机数据上进行了验证。

minI

我刚刚意识到排序会混淆索引,因此minJCast()将不会对应原始非排序数组中的索引。修复很简单 - 原始数组应该在排序之前转换为对数组(value,original_index)。虽然我不会在我的示例代码段中实现此修复程序,因为它会进一步影响可读性。