【问题标题】:how to find closest value in sorted array?如何在排序数组中找到最接近的值?
【发布时间】:2013-01-19 11:29:16
【问题描述】:

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

【问题讨论】:

标签: php arrays


【解决方案1】:

您可以使用binary search。基本算法是这样的,假设你正在寻找myVal

  1. 查看数组的中间值。
  2. 如果值为myVal,则完成。
  3. 如果该值高于myVal,则将数组一分为二并转到1,但只使用数组的下半部分
  4. 如果值较低,则转到 1,但只使用上半部分。
  5. 一旦达到长度为 1 的数组,将该值与其相邻的值进行比较,看看哪个最接近。

这应该是一个 O(log N) 搜索。

【讨论】:

  • 我认为该算法没有给出最接近的值。最接近的值可能与返回的值相邻。
  • 反例是:[1, 3, 10],寻找最接近4的值。第一个中间是3,然后考虑子数组[10],返回10。然而,最接近的值实际上是 3。
  • 我同意 lijie 的观点,但是你可以调整二分搜索来获得最接近的值:每次,你去一半,你在一半中包含上一个检查的数字。当您的子集计数为 2 时,您选择两者中更接近的值。
【解决方案2】:

这是一个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;
}

【讨论】:

    【解决方案3】:

    所以我做了一个尝试,这里有一个函数可以根据另一个数组转换一个数组中的值,它可以用于例如温度,-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;
    

    }

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-20
        • 2016-07-08
        • 2015-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多