我有一个从- 1000到+ 1000的数我有一个数组,里面都是数字。是这样的:

[2, 42, 82, 122, 162, 202, 242, 282, 322, 362]

我想让我得到的数字变成数组中最接近的数字。

例如,我的数字是80,我希望它是82。


当前回答

这里的另一个变体是圆形范围,从头到脚连接,只接受给定输入的最小值。这帮助我获得了一个加密算法的字符代码值。

function closestNumberInCircularRange(codes, charCode) {
  return codes.reduce((p_code, c_code)=>{
    if(((Math.abs(p_code-charCode) > Math.abs(c_code-charCode)) || p_code > charCode) && c_code < charCode){
      return c_code;
    }else if(p_code < charCode){
      return p_code;
    }else if(p_code > charCode && c_code > charCode){
      return Math.max.apply(Math, [p_code, c_code]);
    }
    return p_code;
  });
}

其他回答

我喜欢Fusion的方法,但其中有一个小错误。这样是正确的:

    function closest(array, number) {
        var num = 0;
        for (var i = array.length - 1; i >= 0; i--) {
            if(Math.abs(number - array[i]) < Math.abs(number - array[num])){
                num = i;
            }
        }
        return array[num];
    }

它也更快一点,因为它使用了改进的for循环。

最后,我这样写函数:

    var getClosest = function(number, array) {
        var current = array[0];
        var difference = Math.abs(number - current);
        var index = array.length;
        while (index--) {
            var newDifference = Math.abs(number - array[index]);
            if (newDifference < difference) {
                difference = newDifference;
                current = array[index];
            }
        }
        return current;
    };

我用console.time()测试了它,它比其他函数略快。

我对一个类似问题的回答是考虑关系,它是在纯Javascript中,尽管它不使用二进制搜索,所以它是O(N)而不是O(logN):

var searchArray= [0, 30, 60, 90];
var element= 33;

function findClosest(array,elem){
    var minDelta = null;
    var minIndex = null;
    for (var i = 0 ; i<array.length; i++){
        var delta = Math.abs(array[i]-elem);
        if (minDelta == null || delta < minDelta){
            minDelta = delta;
            minIndex = i;
        }
        //if it is a tie return an array of both values
        else if (delta == minDelta) {
            return [array[minIndex],array[i]];
        }//if it has already found the closest value
        else {
            return array[i-1];
        }

    }
    return array[minIndex];
}
var closest = findClosest(searchArray,element);

https://stackoverflow.com/a/26429528/986160

O(n)时间复杂度的一个更简单的方法是在数组的一次迭代中完成。此方法用于未排序的数组。

下面是一个javascript的例子,在这里我们从数组中找到最接近“58”的数字。

var inputArr = [150, 5, 200, 50, 30]; Var搜索= 58; var min = Math.min(); Var结果= 0; (我= 0;< inputArr.length; + +) { let absVal =数学。abs(search - inputArr[i]) if(min > absVal) { min = absVal; result = inputArr[i]; } } console.log(结果);//如果输入为58,则期望输出为50

这也适用于正数,负数,小数。

Math.min()将返回Infinity。

结果将存储离搜索元素最近的值。

对于排序数组(线性搜索)

到目前为止,所有答案都集中在搜索整个数组上。 考虑到你的数组已经排序,你真的只想要最近的数字,这可能是最简单的(但不是最快的)解决方案:

var a = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]; var target = 90000; /** * Returns the closest number from a sorted array. **/ function closest(arr, target) { if (!(arr) || arr.length == 0) return null; if (arr.length == 1) return arr[0]; for (var i = 1; i < arr.length; i++) { // As soon as a number bigger than target is found, return the previous or current // number depending on which has smaller difference to the target. if (arr[i] > target) { var p = arr[i - 1]; var c = arr[i] return Math.abs(p - target) < Math.abs(c - target) ? p : c; } } // No number in array is bigger so return the last. return arr[arr.length - 1]; } // Trying it out console.log(closest(a, target));

请注意,该算法可以大大改进,例如使用二叉树。

下面是伪代码,可以转换成任何过程语言:

array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
number = 112
print closest (number, array)

def closest (num, arr):
    curr = arr[0]
    foreach val in arr:
        if abs (num - val) < abs (num - curr):
            curr = val
    return curr

它只是计算出给定数字和每个数组元素之间的绝对差值,然后返回差值最小的一个。

对于示例值:

number = 112  112  112  112  112  112  112  112  112  112
array  =   2   42   82  122  162  202  242  282  322  362
diff   = 110   70   30   10   50   90  130  170  210  250
                         |
                         +-- one with minimal absolute difference.

作为概念的证明,下面是我用来演示这一点的Python代码:

def closest (num, arr):
    curr = arr[0]
    for index in range (len (arr)):
        if abs (num - arr[index]) < abs (num - curr):
            curr = arr[index]
    return curr

array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
number = 112
print closest (number, array)

而且,如果你真的需要它在Javascript中,请参阅下面的完整HTML文件,其中演示了该函数的操作:

<html>
    <head></head>
    <body>
        <script language="javascript">
            function closest (num, arr) {
                var curr = arr[0];
                var diff = Math.abs (num - curr);
                for (var val = 0; val < arr.length; val++) {
                    var newdiff = Math.abs (num - arr[val]);
                    if (newdiff < diff) {
                        diff = newdiff;
                        curr = arr[val];
                    }
                }
                return curr;
            }
            array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];
            number = 112;
            alert (closest (number, array));
        </script>
    </body>
</html>

现在请记住,如果数据项已经排序(这可以从示例数据中推断出来,但您没有显式地说明),则可能存在提高效率的空间。例如,您可以使用二分搜索来查找最接近的项。

您还应该记住,除非您需要每秒执行多次,否则效率的提高基本上是不明显的,除非您的数据集变得更大。

如果你确实想尝试这种方式(并且可以保证数组按升序排序),这是一个很好的起点:

<html>
    <head></head>
    <body>
        <script language="javascript">
            function closest (num, arr) {
                var mid;
                var lo = 0;
                var hi = arr.length - 1;
                while (hi - lo > 1) {
                    mid = Math.floor ((lo + hi) / 2);
                    if (arr[mid] < num) {
                        lo = mid;
                    } else {
                        hi = mid;
                    }
                }
                if (num - arr[lo] <= arr[hi] - num) {
                    return arr[lo];
                }
                return arr[hi];
            }
            array = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362];
            number = 112;
            alert (closest (number, array));
        </script>
    </body>
</html>

它基本上使用括号和中间值的检查来将每次迭代的解空间减少一半,这是一个经典的O(log N)算法,而上面的顺序搜索是O(N):

0  1  2   3   4   5   6   7   8   9  <- indexes
2 42 82 122 162 202 242 282 322 362  <- values
L             M                   H  L=0, H=9, M=4, 162 higher, H<-M
L     M       H                      L=0, H=4, M=2, 82 lower/equal, L<-M
      L   M   H                      L=2, H=4, M=3, 122 higher, H<-M
      L   H                          L=2, H=3, difference of 1 so exit
          ^
          |
          H (122-112=10) is closer than L (112-82=30) so choose H

如前所述,对于小型数据集或不需要盲目快速的东西,这应该没有太大区别,但这是您可能想要考虑的一个选项。