如何在查找表中搜索最接近的值?

时间:2010-05-19 18:40:53

标签: algorithm search

我有一个简单的一个dimmensional整数值数组,表示我必须使用的零件值的物理集合。然后我以数学方式计算和理想值。

我怎样才能编写一个有效的搜索算法,它会在数组中找到与理想值最小的abosulte差异?

数组是预定且恒定的,因此可以按需要对其进行排序。

实施例 查找数组:

100, 152, 256, 282, 300

搜索理想值125会在数组中找到100,而127会找到152。

实际的查找数组大约有250个项目,永远不会改变。

5 个答案:

答案 0 :(得分:3)

对数组进行排序后,请使用binary search

答案 1 :(得分:3)

这与二进制搜索非常相似,除非它找不到确切的密钥,否则返回的密钥将非常接近提供的密钥。

逻辑是搜索到找到确切的键,或者直到在执行二进制搜索时高键和低号之间只剩下一个键。

考虑一个数组n [] = {1,2,4,6,8,10,12,14,16,18,20} 如果您搜索密钥:2,则使用以下算法
步骤1:高= 10,低= 0,med = 5
步骤2:高= 5,低= 0,med = 2
步骤3:高= 2,低= 0,med = 1在此步骤中找到确切的密钥。所以它返回1.

如果您搜索键:3(数组中不存在),则使用以下算法
步骤1:高= 10,低= 0,med = 5
步骤2:高= 5,低= 0,med = 2
步骤3:高= 2,低= 0,med = 1
步骤4:高= 1,低= 0,在此步骤高=低+ 1,即不再有要搜索的元素。所以它返回med = 1。

希望这会有所帮助......

public static <T> int binarySearch(List<T> list, T key, Comparator<T> compare) {
                int low, high, med, c;
                T temp;
                high = list.size();
                low = 0;
                med = (high + low) / 2;

                while (high != low+1) {
                    temp = list.get(med);
                    c = compare.compare(temp, key);

                    if (c == 0) {
                        return med;
                    } else if (c < 0){
                        low = med;
                    }else{
                        high = med;
                    }

                    med = (high + low) / 2;
                }

                return med; 
            }

    /** ------------------------ Example -------------------- **/

    public static void main(String[] args) {
                List<Integer> nos = new ArrayList<Integer>();
                nos.addAll(Arrays.asList(new Integer[]{1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20}));

                search(nos, 2); // Output Search:2  Key:1   Value:2
                search(nos, 3); // Output Search:3  Key:1   Value:2

                search(nos, 10); // Output Search:10    Key:5   Value:10
                search(nos, 11); // Output Search:11    Key:5   Value:10
            }

    public static void search(List<Integer> nos, int search){
                int key = binarySearch(nos, search, new IntComparator());
                System.out.println("Search:"+search+"\tKey:"+key+"\tValue:"+nos.get(key));
            }

            public static class IntComparator implements Comparator<Integer>{
                @Override
                public int compare(Integer o1, Integer o2) {
                    return o1.compareTo(o2);
                }
            }

答案 2 :(得分:1)

维基百科的二进制搜索算法如下:

int binary_search(int A[], int key, int imin, int imax)
{
  // continue searching while [imin,imax] is not empty
  while (imax >= imin)
    {
      // calculate the midpoint for roughly equal partition
      int imid = midpoint(imin, imax);
      if(A[imid] == key)
        // key found at index imid
        return imid; 
      // determine which subarray to search
      else if (A[imid] < key)
        // change min index to search upper subarray
        imin = imid + 1;
      else         
        // change max index to search lower subarray
        imax = imid - 1;
    }
  // key was not found
  return KEY_NOT_FOUND;
}

如果找不到密钥,则结束条件是imax < imin

实际上,这个条件可以找到最近的匹配。最近的匹配位于imaximin之间(考虑到可能在数组边界之外)。最后再次注意imax < imin。有些解决方案使用abs来找出差异,但我们知道A[imax] < key < A[imin]所以:

if imax <= 0 return 0
if imin >= A.count - 1 return A.count - 1
if (key - A[imax]) < (A[imin] - key) return imax
return imin

答案 3 :(得分:0)

通过数组并计算abs(reference-array_value [i])将需要O(N)。 携带具有最小差异的指数。

答案 4 :(得分:0)

Python,对未排序列表的暴力(导致编写Python的乐趣)O(n)

table = (100, 152, 256, 282, 300)
value = 125

lookup_dict = dict([(abs(value-x),x) for x in table])
closest_val = ldict[min(ldict.keys())]

使用二进制搜索找到值O(log_n)的正确实现:

import bisect
'''Returns the closest entry in the sorted list 'sorted' to 'value'
'''
def find_closest(sorted, value):
    if (value <= sorted[0]):
        return sorted[0]
    if (value >= sorted[-1]):
        return sorted[-1]
    insertpos = bisect.bisect(sorted, value)
    if (abs(sorted[insertpos-1] - value) <= abs(sorted[insertpos] - value)):
        return sorted[insertpos-1]
    else:
        return sorted[insertpos]