寻找最接近0的数字

11

我有一个整数数组,需要找到最接近零的元素(正数优先于负数)。

这是我目前的代码:

public class CloseToZero {    
    public static void main(String[] args) {    
        int[] data = {2,3,-2};    
        int curr = 0;    
        int near = data[0];     
        // find the element nearest to zero    
        for ( int i=0; i < data.length; i++ ){    
            curr = data[i] * data[i];     
            if ( curr <= (near * near) )  {     
                near = data[i]; 
            }     
        }    
        System.out.println( near );    
    }    
}

目前我得到了一个-2的结果,但是我应该得到2。我做错了什么?


1
将数字平方在数学上很优雅,但它显著地限制了可以接受的数组范围。我会使用Math.abs()代替。 - Solomon Slow
28个回答

23

这将在O(n)时间内完成:

int[] arr = {1,4,5,6,7,-1};

int closestIndex = 0;
int diff = Integer.MAX_VALUE;
for (int i = 0; i < arr.length; ++i) {
    int abs = Math.abs(arr[i]);
    if (abs < diff) {
        closestIndex = i;
        diff = abs;
    } else if (abs == diff && arr[i] > 0 && arr[closestIndex] < 0) {
        //same distance to zero but positive 
        closestIndex =i;
    }
}   
System.out.println(arr[closestIndex ]);

10

如果您正在使用java8:

import static java.lang.Math.abs;
import static java.lang.Math.max;

public class CloseToZero {
    public static void main(String[] args) {
        int[] str = {2,3,-2};
        Arrays.stream(str).filter(i -> i != 0)
                .reduce((a, b) -> abs(a) < abs(b) ? a : (abs(a) == abs(b) ? max(a, b) : b))
                .ifPresent(System.out::println);
    }
}

8

将数组排序(添加一行代码),以便在选择正数和负数的相同绝对值且距离相等的情况下,选择的最后一个数字是正数。

源代码:

import java.util.Arrays;

public class CloseToZero {

    public static void main(String[] args) {

        int[] data = {2,3,-2};
        int curr = 0;
        int near = data[0]; 
        Arrays.sort(data);      //  add this
        System.out.println(Arrays.toString(data));        
        // find the element nearest to zero
        for ( int i=0; i < data.length; i++ ){
            System.out.println("dist from " + data[i] + " = " + Math.abs(0 -data[i]));
            curr = data[i] * data[i]; 
            if ( curr <= (near * near) )  { 
                near = data[i];
            } 
        }
        System.out.println( near );
    }
}

6
时间复杂度很糟糕。原本是O(n),但排序所花费的时间比这还要多。 - Thilo
它可以是0(n)的简单暴力方法。你刚刚把它变成了nlog。否则尝试二分查找方法。 - melvil james
不需要对数组进行排序。我用O(n)时间(0.2秒执行时间)解决了它,而且没有使用搜索算法。我发布了新答案。 - AGM Tazim

7

将零添加到此列表中。

然后对列表进行排序。

Arrays.sort(data);

然后获取零前或零后的数字,并选择大于零的最小数字。

2
这个可以工作,但是这个问题可以在O(n)时间内解决。你的解决方案需要O(n lg n)。 - kmera

4
假设数组data至少有一个值。
int closestToZero = 0;
for ( int i = 1; i < data.length; i++ )
{
    if ( Math.abs(data[i]) < Math.abs(data[closestToZero]) ) closestToZero = i;
}
closestToZero中的值是离零最近的值的索引,而不是值本身。

实际上,我想要的逻辑是不使用任何内置函数。 - user3172930
@user3172930 然后编写函数 return (num*num)/num; - usama8800
1
然后用你自己的绝对值方法/代码替换 Math.abs(...) - Eric
那段代码是错误的。我用 int[] data = {2, 3, -2, 4, 10, 6, -1}; 进行了尝试。 - usama8800
@usama8800,错了,代码完美运行。它返回最接近零的索引号,而不是数字本身! - Eric

2
 static int Solve(int N, int[] A){
      int min = A[0];
      for (int i=1; i<N ; i++){
        min = min > Math.abs(0- A[i]) ? Math.abs(0- A[i]) : Math.abs(min);
      }
      return min;
    }

0
使用Set集合和abs方法避免复杂算法 public static void main(String[] args) {
    int [] temperature={0};

    ***// will erase double values and order them from small to big***
    Set<Integer> s= new HashSet<Integer>();
    
    if (temperature.length!=0) {
        
        for(int i=0; i<temperature.length; i++) {
        
            ***// push the abs value to the set*** 
            s.add(Math.abs(temperature[i]));
        }
        
        // remove a zero if exists in the set 
        while(s.contains(0)) {
            s.remove(0);
        }
        
        ***// get first (smallest) element of the set : by default it is sorted*** 
        
        if (s.size()!=0) {
            Iterator iter = s.iterator();
            System.out.println(iter.next());
        }
        
        else System.out.println(0);
        
        
    }
    
    else System.out.println(0);
    
    

}

0

这是一个非常易于阅读的O(n)解决方案。

    int bigestNegative = Integer.MIN_VALUE;
    int smalestpositive = Integer.MAX_VALUE;
    int result = 0; 

    for (int i = 0; i < n; i++) {
        //if the zero should be considered as result as well
        if ( temperatures[i] == 0 )  { 
           result = 0;
           break;
        } 
        if ( temperatures[i] > 0 && temperatures[i] < smalestpositive )  { 
            smalestpositive = temperatures[i];
        } 
        if ( temperatures[i] < 0 && temperatures[i] > bigestNegative )  { 
            bigestNegative = temperatures[i];
        } 
    }
    if( (Math.abs(bigestNegative)) < (Math.abs(smalestpositive)) && bigestNegative != Integer.MIN_VALUE)
        result = bigestNegative;
    else
        result = smalestpositive;
    System.out.println( result );

0

首先将int数组转换为流。然后使用默认排序顺序进行排序。然后过滤大于零的元素,查看第一个元素并打印它。 以声明性风格执行此操作,描述“要做什么”,而不是“如何做”。这种风格更易读。

int[] data = {2,3,-2};
IntStream.of(data)
    .filter(i -> i>0)
    .sorted()
    .limit(1)
    .forEach(System.out::println);

0

当你将data[i]与data[i]相乘时,一个负值和一个正值会产生相同的影响。例如,在你的例子中:2和-2将变成4。因此,你的代码无法按照你的需求进行排序。

所以,在这里,它将-2作为近似值,因为它与2具有相同的“权重”。


是的,这就是为什么我正在寻找任何给定程序的新方法或任何内部修改。 - user3172930
所以在你的问题中指明这一点应该是有好处的。因为它并不清楚。 - lpratlong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接