【发布时间】:2013-01-19 11:29:16
【问题描述】:
我已经用数字作为键对数组进行了排序,我需要一个相当快的算法来选择一个键号,它的值与给定变量最接近或相同(如果存在)。如果给定值高于最大值或低于最小值,则分别给出持有最大值和最小值的键。
【问题讨论】:
我已经用数字作为键对数组进行了排序,我需要一个相当快的算法来选择一个键号,它的值与给定变量最接近或相同(如果存在)。如果给定值高于最大值或低于最小值,则分别给出持有最大值和最小值的键。
【问题讨论】:
您可以使用binary search。基本算法是这样的,假设你正在寻找myVal
myVal,则完成。myVal,则将数组一分为二并转到1,但只使用数组的下半部分这应该是一个 O(log N) 搜索。
【讨论】:
这是一个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;
}
【讨论】:
所以我做了一个尝试,这里有一个函数可以根据另一个数组转换一个数组中的值,它可以用于例如温度,-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;
}
【讨论】:
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);
}
【讨论】: