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

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

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

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


当前回答

在数组中找到两个最接近的数字

function findTwoClosest(givenList, goal) {
  var first;
  var second;
  var finalCollection = [givenList[0], givenList[1]];
  givenList.forEach((item, firtIndex) => {
    first = item;

    for (let i = firtIndex + 1; i < givenList.length; i++) {
      second = givenList[i];

      if (first + second < goal) {
        if (first + second > finalCollection[0] + finalCollection[1]) {
          finalCollection = [first, second];
        }
      }
    }
  });

  return finalCollection;
}

var counts = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]
var goal = 80;
console.log(findTwoClosest(counts, goal));

其他回答

我喜欢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是一种灵活的语言,它为我们提供了以多种不同方式解决问题的工具。 当然,这一切都取决于你的风格。如果你的代码更实用,你会发现减少变化是合适的,即:

  arr.reduce(function (prev, curr) {
    return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
  });

然而,有些人可能会发现这很难阅读,这取决于他们的编码风格。因此,我提出了一种新的解决方法:

  var findClosest = function (x, arr) {
    var indexArr = arr.map(function(k) { return Math.abs(k - x) })
    var min = Math.min.apply(Math, indexArr)
    return arr[indexArr.indexOf(min)]
  }

  findClosest(80, [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]) // Outputs 82

与使用Math.min找到最小值的其他方法相反。应用,这个不需要输入数组arr排序。我们不需要关心索引或者事先排序。

为了清晰起见,我将逐行解释代码:

arr.map(function(k) { return Math.abs(k - x) }) Creates a new array, essentially storing the absolute values of the given numbers (number in arr) minus the input number (x). We'll look for the smallest number next (which is also the closest to the input number) Math.min.apply(Math, indexArr) This is a legit way of finding the smallest number in the array we've just created before (nothing more to it) arr[indexArr.indexOf(min)] This is perhaps the most interesting part. We have found our smallest number, but we're not sure if we should add or subtract the initial number (x). That's because we used Math.abs() to find the difference. However, array.map creates (logically) a map of the input array, keeping the indexes in the same place. Therefore, to find out the closest number we just return the index of the found minimum in the given array indexArr.indexOf(min).

我创建了一个箱子来演示它。

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。

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

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

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;
  });
}

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

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

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));

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