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

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

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

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


当前回答

如果数组像你的例子中那样排序,你可以使用二进制搜索来获得O(log n)更好的时间复杂度。

const myArray = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]; const binaryClosestIdx = (arr, target) => { let start = 0; let end = arr.length - 1; let mid = Math.floor((start + end) / 2); while (1) { if (arr[mid] === target) { return mid; } else if (start >= end) { break; } else if (arr[mid] > target) { end = mid - 1; } else { start = mid + 1; } mid = Math.floor((start + end) / 2); } // Return the closest between the last value checked and it's surrounding neighbors const first = Math.max(mid - 1, 0); const neighbors = arr.slice(first, mid + 2); const best = neighbors.reduce((b, el) => Math.abs(el - target) < Math.abs(b - target) ? el : b); return first + neighbors.indexOf(best); } const closestValue = myArray[binaryClosestIdx(myArray, 80)]; console.log(closestValue);

工作原理:

它将目标值与数组的中间元素进行比较。如果中间的元素更大,我们可以忽略它后面的每个元素,因为它们会更大。同样,如果中间的元素更小,我们可以忽略它之前的所有元素。 如果找到了目标值,则返回它,否则将最后测试的值与其周围的相邻值进行比较,因为最近的值只能在这3个值之间。

其他回答

ES6

适用于已排序和未排序数组

数字整数和浮点数,字符串欢迎

/**
 * Finds the nearest value in an array of numbers.
 * Example: nearestValue(array, 42)
 * 
 * @param {Array<number>} arr
 * @param {number} val the ideal value for which the nearest or equal should be found
 */
const nearestValue = (arr, val) => arr.reduce((p, n) => (Math.abs(p) > Math.abs(n - val) ? n - val : p), Infinity) + val

例子:

let values = [1,2,3,4,5]
console.log(nearestValue(values, 10)) // --> 5
console.log(nearestValue(values, 0)) // --> 1
console.log(nearestValue(values, 2.5)) // --> 2

values = [100,5,90,56]
console.log(nearestValue(values, 42)) // --> 56

values = ['100','5','90','56']
console.log(nearestValue(values, 42)) // --> 56

#include <algorithm>
#include <iostream>
#include <cmath>

using namespace std;

class CompareFunctor
{

public:
    CompareFunctor(int n) { _n = n; }
    bool operator()(int & val1, int & val2)
    {
        int diff1 = abs(val1 - _n);
        int diff2 = abs(val2 - _n);
        return (diff1 < diff2);
    }

private:
    int _n;
};

int Find_Closest_Value(int nums[], int size, int n)
{
    CompareFunctor cf(n);
    int cn = *min_element(nums, nums + size, cf);
    return cn;
}

int main()
{
    int nums[] = { 2, 42, 82, 122, 162, 202, 242, 282, 322, 362 };
    int size = sizeof(nums) / sizeof(int);
    int n = 80;
    int cn = Find_Closest_Value(nums, size, n);
    cout << "\nClosest value = " << cn << endl;
    cin.get();
}

我对一个类似问题的回答是考虑关系,它是在纯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(log n)更好的时间复杂度。

const myArray = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]; const binaryClosestIdx = (arr, target) => { let start = 0; let end = arr.length - 1; let mid = Math.floor((start + end) / 2); while (1) { if (arr[mid] === target) { return mid; } else if (start >= end) { break; } else if (arr[mid] > target) { end = mid - 1; } else { start = mid + 1; } mid = Math.floor((start + end) / 2); } // Return the closest between the last value checked and it's surrounding neighbors const first = Math.max(mid - 1, 0); const neighbors = arr.slice(first, mid + 2); const best = neighbors.reduce((b, el) => Math.abs(el - target) < Math.abs(b - target) ? el : b); return first + neighbors.indexOf(best); } const closestValue = myArray[binaryClosestIdx(myArray, 80)]; console.log(closestValue);

工作原理:

它将目标值与数组的中间元素进行比较。如果中间的元素更大,我们可以忽略它后面的每个元素,因为它们会更大。同样,如果中间的元素更小,我们可以忽略它之前的所有元素。 如果找到了目标值,则返回它,否则将最后测试的值与其周围的相邻值进行比较,因为最近的值只能在这3个值之间。

最有效的方法是二分查找。然而,即使是简单的解决方案,当下一个数字与当前数字进一步匹配时,也可以退出。这里几乎所有的解决方案都没有考虑到数组是有序的,并且迭代整个:/

const closest = (orderedArray, value, valueGetter = item => item) => orderedArray.find((item, i) => i === orderedArray.length - 1 || Math.abs(value - valueGetter(item)) < Math.abs(value - valueGetter(orderedArray[i + 1]))); var data = [2, 42, 82, 122, 162, 202, 242, 282, 322, 362]; console.log('21 -> 2', closest(data, 21) === 2); console.log('22 -> 42', closest(data, 22) === 42); // equidistant between 2 and 42, select highest console.log('23 -> 42', closest(data, 23) === 42); console.log('80 -> 82', closest(data, 80) === 82);

这也可以在非原语上运行,例如,nearest (data, 21, item => item.age)

将find更改为findIndex以返回数组中的索引。