如何在排序数组中找到最接近的值?

时间:2010-11-23 15:42:27

标签: php arrays

我已经用数字作为键对数组进行了排序,我需要一个合理快速的算法来选择一个键值,该键值保持与给定变量最接近或相同(如果存在)的值。如果给定值高于最大值或低于最小值,则分别给出保持最大值和最小值的键。

4 个答案:

答案 0 :(得分:3)

您可以使用binary search。假设您正在寻找myVal

,基本算法就是这样的
  1. 查看数组的中间值。
  2. 如果值为myVal,则表示您已完成。
  3. 如果该值高于myVal,请将数组拆分为一半并转到1,但仅使用数组的下半部分
  4. 如果值较低,请转到1,但仅使用上半部分。
  5. 一旦到达并且长度= 1的数组,将该值与其邻居进行比较,以查看哪个最接近。
  6. 这应该是O(log N)搜索。

答案 1 :(得分:3)

这是一个java实现,您可以将其翻译成您选择的语言。

static int findNearestValue(int value, int arr[], int low, int high) {
    int result = -1;
    if(high-low>1){
            int mid = low + (high-low)/2;

            if(arr[mid]>value)
                result = findNearestValue3(value, arr, low, mid);
            else if(arr[mid]<value)
                result = findNearestValue3(value, arr, mid, high);
            else
                result = arr[mid];
        }else
            result = (abs(value-arr[low]) < abs(value-arr[high])) ? arr[low] : arr[high];

        return result;
}

答案 2 :(得分:0)

所以我做了一个尝试,这里是一个函数,可以根据另一个数组转换一个数组中的值,它可以用于例如温度,-10到冷或+30到热,但对于大数组,它不是这样的快,任何线索如何让它更快?

function transnum($nums,$transarr,$searchkey='x',$returnkey='y') {
$was_arr = is_array($nums); $nums = (array)$nums;
foreach ($nums as &$num) {
    if ($num===null or $num==='') continue;
    reset($transarr[$searchkey]);
    $ckey= key($transarr[$searchkey]);
    $closest = abs($num-current($transarr[$searchkey]));
    while($next = next($transarr[$searchkey])) {
        $checkclosest=abs($num-$next);
        if($closest>$checkclosest) {
            $closest = $checkclosest;
            $ckey = key($transarr[$searchkey]);
        }
        else break;
    }
    $num = $transarr[$returnkey][$ckey];
}
if(!$was_arr) $nums = $nums[0];
return $nums;

}

答案 3 :(得分:0)

C代码:

#include <stdio.h>

#define moddiff(a,b) ((a > b) ? (a-b) : (b-a))

#define uint unsigned int

/* test case : sample array */
uint arr[] = { 1, 4, 9, 16, 25, 36, 49 , 64, 81 };

/* search for nearest num to key in a sorted array */
uint nrst_num(uint arr[], uint lo, uint hi, uint key) 
{
  uint mid = 0;
  uint mid_parent = 0;

  while (lo < hi) {
    mid_parent = mid;
    mid = (lo + hi) / 2; 

    if (key == arr[mid]) {
        return mid;
    } else if (key < arr[mid]) {
        hi = mid - 1;
    } else if (key > arr[mid]) {
        lo = mid + 1;
    }   
  }

  uint ldiff = moddiff(key, arr[lo]);
  uint mdiff = moddiff(key, arr[mid]);
  uint hdiff = moddiff(key, arr[hi]);
  uint mid_parent_diff = moddiff(key, arr[mid_parent]);

  /* select the index from the lowest diff */
  if ((mid_parent_diff <= mdiff) && (mid_parent_diff <= ldiff) && (mid_parent_diff <= hdiff)) {
        return mid_parent;
  } else if ((mdiff <= mid_parent_diff) && (mdiff <= ldiff) && (mdiff <= hdiff)) {
        return mid;
  } else if ((ldiff <= mdiff) && (ldiff <= hdiff) && (ldiff <= mid_parent_diff)) {
        return lo;
  }

  return hi; 
}


int main()
{
 /* test case */
  uint key = 0;

  printf(" { 1, 4, 9, 16, 25, 36, 49 , 64, 81 }");
  uint res = nrst_num(arr, 0, 8, key);

  printf (" nearest point to key=%d is val=%d \n", key, res); 
}