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

Java 如何找到数组中最接近零的两个元素之和,java,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];

如何从一个数组中找到两个元素,其和最接近于零但不是零(注意:-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]);
inta[]=newint[n];
int b[]=新int[2];
int prev=0;
对于(int i=0;i您可以尝试:

 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]);
inta[]=newint[n];
int b[]=新int[2];
int prev=0;

对于(int i=0;i我有几点意见,您使用了3个for循环,这可以改进为2个嵌套for循环(外部循环用于选择当前元素,内部循环用于与其他元素进行比较)

此外,您还有多个if测试来检查总和现在是否比上一个总和更接近于零。但是,这些if测试可以减少为一个if测试,方法是取总和的绝对值,而不是在
sum>0
sum<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]);
int数组[]=newint[5];
数组[0]=-3;数组[1]=-2;数组[2]=-1;数组[3]=1;数组[4]=2;//填充数组
int idx[]=new int[2];//将存储结果(需要添加的两个元素的索引)
double lower_sum=double.POSITIVE_INFINITY;//类型为double,可以使用INFINITY
for(int i=0;i从左到右使用电流(数组[i])
int电流=阵列[i];
对于(int j=i+1;j检查到目前为止未用作当前元素的所有元素
int compare_with=数组[j];
如果((数学绝对值(当前值+比较值)<最低值和)&((当前值+比较值)!=0)){
//我们发现两个元素的和接近于零
最低总和=Math.abs(当前+比较);
idx[0]=i;//要添加的第一个元素的索引
idx[1]=j;//要添加的第二个元素的索引
}
}
}
int res_idx1=idx[0];
int res_idx2=idx[1];
System.out.println(“要添加的第一个元素是:“+array[res_idx1]+”\n要添加的第二个元素是:“+array[res_idx2]);
输入:数组=[-3,-2,-1,1,2],输出:要添加的第一个元素是:-3, 要添加的第二个元素是:2


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

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

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

下面是我的解决方案。它通过随机数据与bruteforce O(N^2)解决方案进行验证

// note: mutates argument!
static Solution solve(int a[]) {
    Arrays.sort(a);

    int i = 0;
    int j = a.length - 1;

    // -1 indicates uninitialized min value
    int minI = -1;
    int minJ = -1;
    int min = 0;

    // finding maximal sum among negative sums
    while (i < j) {
        int cur = a[i] + a[j];
        if (cur != 0 && (minI == -1 || Math.abs(cur) < Math.abs(min))) {
            min = cur;
            minI = i;
            minJ = j;
        }

        // if current sum is below zero, increase it
        // by trying the next, larger element
        if (cur < 0) {
            i++;
        } else { // sum is already non-negative, move to the next element
            j --;
        }
    }

    i = 0;
    j = a.length - 1;
    // finding minimal sum among positive sums
    while (i < j) {
        int cur = a[i] + a[j];
        if (cur != 0 && (minI == -1 || Math.abs(cur) < Math.abs(min))) {
            min = cur;
            minI = i;
            minJ = j;
        }

        if (cur > 0) {
            j--;
        } else {
            i ++;
        }
    }

    if (minI >=0) {
        return new Solution(minI, minJ, min);
        //System.out.printf("a[%d]=%d, a[%d]=%d, sum=%d", minI, minJ, a[minI], a[minJ], min);
    } else {
        return null;
        //System.out.println("No solution");
    }
}
//注意:变异参数!
静态解算(int a[]){
数组。排序(a);
int i=0;
int j=a.长度-1;
//-1表示未初始化的最小值
int minI=-1;
int minJ=-1;
int min=0;
//求负和中的最大和
而(i0){
j--;
}否则{
i++;
}
}
如果(最小值>=0){
返回新的解决方案(minI、minJ、min);
//System.out.printf(“a[%d]=%d,a[%d]=%d,sum=%d”,minI,minJ,a[minI],a[minJ],min);
}否则{
返回null;
//System.out.println(“无解决方案”);
}
}

我刚刚意识到排序会弄乱索引,因此
minI
minJ
不会与原始未排序数组中的索引相对应。解决方法很简单-原始数组应转换为成对数组(值,原始索引)排序之前。虽然我不会在我的示例代码段中实现此修复,因为它会进一步影响可读性。

当存在多个解决方案时,您希望的行为是什么?只打印一个解决方案还是打印所有解决方案?以及您尝试不工作的内容如何?您得到了什么输出?您希望得到什么输出?我只想打印两个el来自一个数组的元素,其总和接近于零,与符号无关。在我的代码中,第一个循环用于读取数组中的n个元素,其余两个循环用于操作。使用Math.abs是的,我们可以减少多个if语句,感谢您的建议,最后一件事是如果有多个解决方案,然后打印元素首先出现的是正确的,正如您所做的。是的,除了b[1]=b[j],代码是正确的,但它应该是b[1]=a[j];