C# 在数字列表中查找最接近的数字

C# 在数字列表中查找最接近的数字,c#,algorithm,C#,Algorithm,我有一个常数的列表。我需要在数字列表中找到最接近x的数字。关于如何实现这个算法有什么想法吗?好吧,你不能比O(N)更快,因为你必须检查所有数字以确保你有最接近的一个。也就是说,为什么不使用一个简单的变量来寻找最小值,寻找与x的绝对差最小的那个 如果可以说列表是从一开始就排序的(它允许随机访问,比如数组),那么更好的方法是使用二进制搜索。当您在索引i处结束搜索(没有找到x)时,只需从该元素及其相邻元素中选择最佳元素。可以使用: 如果要查找的复杂度只计算搜索的复杂度,则复杂度为O(log(n))。

我有一个常数的列表。我需要在数字列表中找到最接近x的数字。关于如何实现这个算法有什么想法吗?

好吧,你不能比
O(N)
更快,因为你必须检查所有数字以确保你有最接近的一个。也就是说,为什么不使用一个简单的变量来寻找最小值,寻找与x的绝对差最小的那个

如果可以说列表是从一开始就排序的(它允许随机访问,比如数组),那么更好的方法是使用二进制搜索。当您在索引i处结束搜索(没有找到x)时,只需从该元素及其相邻元素中选择最佳元素。

可以使用:

如果要查找的复杂度只计算搜索的复杂度,则复杂度为O(log(n))。列表构建将花费O(n*log(n))

如果要在列表中插入项的次数远远多于查询最接近的数字,那么最好的选择是使用并使用朴素算法来查询最接近的数字。每次搜索将花费O(n),但插入时间将减少到O(n)

一般复杂性:如果集合有n个数字和搜索的q次-
列表:
O(n+q*n)

排序列表:
O(n*log(n)+q*log(n))


这意味着,从某些q值来看,排序列表将提供更好的复杂性。

我认为数组是无序的。按顺序,它可以更快

private int? FindClosest(IEnumerable<int> numbers, int x)
{
    return
        (from number in numbers
        let difference = Math.Abs(number - x)
        orderby difference, Math.Abs(number), number descending
        select (int?) number)
        .FirstOrDefault();
}
我认为最简单和最快的方法是使用线性算法来寻找最小值或最大值,但不是比较值,而是比较这个值和针之间差值的绝对值

C++中(我不能C,但它将是相似的)代码看起来像这样:

// array of numbers is haystack
// length is length of array
// needle is number which you are looking for ( or compare with )

int closest = haystack[0];
for ( int i = 0; i < length; ++i ) {
  if ( abs( haystack[ i ] - needle ) < abs( closest - needle ) ) closest = haystack[i];
}
return closest;
//数字数组是草堆
//长度是数组的长度
//针是您正在查找(或比较)的编号
int=haystack[0];
对于(int i=0;i
一般来说,这个网站上的人不会帮你做家庭作业。既然你没有发布代码,我也不会发布代码。然而,这里有一种可能的方法


循环遍历列表,从x中减去列表中的数字。取此差值的绝对值,并将其与您得到的上一个最佳结果进行比较,如果当前差值小于上一个最佳结果,则从列表中保存当前数值。在循环结束时,您将得到您的答案。

由于懒惰,我没有检查这一点,但这不应该起作用吗

private int FindClosest(IEnumerable<int> numbers, int x)
{
    return
        numbers.Aggregate((r,n) => Math.Abs(r-x) > Math.Abs(n-x) ? n
                                 : Math.Abs(r-x) < Math.Abs(n-x) ? r
                                 : r < x ? n : r);
}
private int FindClosest(IEnumerable number,int x)
{
返回
数字聚合((r,n)=>数学Abs(r-x)>数学Abs(n-x)→n
:Math.Abs(r-x)
Haskell:

import Data.List (minimumBy)
import Data.Ord (comparing)

findClosest :: (Num a, Ord a) => a -> [a] -> Maybe a
findClosest _ [] = Nothing
findClosest n xs = Just $ minimumBy (comparing $ abs . (+ n)) xs
Performance-wise自定义代码将更充分地使用。
列出结果;
int targetNumber=0;
int最接近值=0;
if(results.Any(ab=>ab==targetNumber))
{
nearestValue=results.FirstOrDefault(i=>i==targetNumber);
}
其他的
{
int greaterThanTarget=0;
int-lessThanTarget=0;
if(results.Any(ab=>ab>targetNumber))
{
greaterThanTarget=results.Where(i=>i>targetNumber).Min();
}
if(results.Any(ab=>abi别忘了考虑不寻常的情况。(1) 如果没有最近的号码怎么办?(2)如果有两个不同的最接近的数字呢?“针”是我不知道的一些特殊术语吗?“大海捞针”:D“针”和“大海捞针”是搜索算法中经常使用的表达式。尽管我们经常在不希望找到针的时候使用“大海捞针”这个表达式@R.MartinhoFernandes让我高兴:)如果你的搜索空间被排序,你可以打败O(N)。是的,使用二叉搜索树逻辑应该可以让你在O(logn)中进行搜索。或者插值搜索,O(logn)平均可能我遗漏了一些东西,但是你不能只列出绝对数abs(你的num-needle),把它放到数组中,然后排序吗?第一个索引应该是最接近的?@mardala,因为排序是O(N logn)。OP确实使用了
家庭作业
标记。他并不是想对你耍花招。林克的迷人用法。然而,我注意到这是时间上的O(n lgn)和额外空间上的O(n)。如果使用最小序列运算符而不是排序,则可以在O(n)时间和O(1)空间中执行。此外,您还没有完全消除问题陈述的歧义。如果有两个数字具有相同的差值,并且它们都同样接近于零,那该怎么办?好的观点。我按编号降序排序,以确保选择正数(在没有行为要求的情况下,这是最合理的决定)。我将在这条路上工作
import Data.List (minimumBy)
import Data.Ord (comparing)

findClosest :: (Num a, Ord a) => a -> [a] -> Maybe a
findClosest _ [] = Nothing
findClosest n xs = Just $ minimumBy (comparing $ abs . (+ n)) xs
                Performance wise custom code will be more use full. 

                List<int> results;
                int targetNumber = 0;
                int nearestValue=0;
                if (results.Any(ab => ab == targetNumber ))
                {
                    nearestValue= results.FirstOrDefault<int>(i => i == targetNumber );
                }
                else
                {
                    int greaterThanTarget = 0;
                    int lessThanTarget = 0;
                    if (results.Any(ab => ab > targetNumber ))
                    {
                        greaterThanTarget = results.Where<int>(i => i > targetNumber ).Min();
                    }
                    if (results.Any(ab => ab < targetNumber ))
                    {
                        lessThanTarget = results.Where<int>(i => i < targetNumber ).Max();
                    }

                    if (lessThanTarget == 0 )
                    {
                        nearestValue= greaterThanTarget;
                    }
                    else if (greaterThanTarget == 0)
                    {
                        nearestValue= lessThanTarget;
                    }
                    else if (targetNumber - lessThanTarget < greaterThanTarget - targetNumber )
                    {
                        nearestValue= lessThanTarget;
                    }
                    else
                    {
                            nearestValue= greaterThanTarget;
                    }
                }