当列表具有一些重复的元素时,在列表<long>中查找下一个最接近的元素

时间:2015-11-26 02:04:41

标签: c# list binary-search

  • 我有一个SortedList,其中包含元素的长数据类型元素 可能会重复(也有一些重复的记录)。

  • 例如: ValueCov = {1,2,2,2,5,5,5,5,6,6,7,7,7,.......... }

  • 我必须搜索一个值&#34; x&#34;每次在此列表中都有选项 二进制搜索(x)在C#中和值#34; x&#34;是不是在那里 ValueCov列表,我需要找到下一个更接近的值的索引。 (最小 从价值差异&#34; x&#34; )。

  • 我在这里遇到的问题是,如果我搜索,可以使用重复元素 对于值x = 3,这应该从valueCov返回value = 2&#39的索引( 指数= 1)。但是第二次搜索值= 3时,这不应该 返回先前返回的索引,因为我正在修复它 其他一些工作的位置。所以当我搜索时我需要索引为= 2 第二次。

请为此搜索提供解决方案,同时在列表中提供重复项。

for (int i = 0; i < valueWat.Count; i++)
{
    var x=valueWat[i];
    int index = valueCov.BinarySearch(x);

                //Console.Write(index + ",");
    if (index >= 0)
    {
                    //Console.Write(sortedCov[index].Key + ",");
    Console.WriteLine("addr of w/m" + sortedWat[i].Key);
                    //adding addr of w/m and coveraddr
    blockedWaterCoverMap.Add(sortedCov[index].Key, sortedWat[i].Key);
                    //valueCov.Remove(x);
                    //valueCov[index] = 10000000000;
    valueCov[index] = -100000000;
                    // valueWat[i] = 20000000000;

                    //foreach (var z in blockedWaterCoverMap)
                    //{
                    //    Console.WriteLine("cov,wat indexpair" + z.Key+z.Value);
                    //}
    }
    else
    {
        int ind = findClosest(x);
        Console.WriteLine("index,value@index\t" + ind + "\t" + valueCov[ind]);
        blockedWaterCoverMap.Add(sortedCov[ind].Key, sortedWat[i].Key);
        valueCov[ind] = 00000; valueCov[index] = 00000;   
    }
}

/////////
private int findClosest(long data)
{
    int i = 0; // index of currently checked element from valueCov
    int ind =i; // returned index of the closest element 
    //  current lowest distance to searched value:
    long min = long.MaxValue;
    // currently counted difference between input value
    // and the next element of the list valueCov
    long diff = 0;
    var valueCov = new List<long>();

    foreach (var y in sortedCov)
    {
        valueCov.Add(y.Value);
    }
    for ( i = 0; i < valueCov.Count; i++)
    {
        var x=valueCov[i];

        if ((diff = Math.Abs(x - data)) < min)
        {
            min = diff;
            ind = i; // the searched index is updated
            //Console.WriteLine("findclosest i\t" + i);
        }
    }
    // random selection of the index from the closest
    // found values
    List<int> indices = new List<int>();
    for (int n = 0; n < valueCov.Count; n++)
    {
        if (valueCov[n] == valueCov[ind])
        indices.Add(n);
    }
    Random r = new Random();
    ind = indices[r.Next(indices.Count)];
    return ind;
}

2 个答案:

答案 0 :(得分:0)

我只想使用linq获取值,然后您可以通过BinarySearch获取索引

public static void Main()
{
    var valueCov = new long[]{ 1,2,2,2,5,5,5,5,6,6,7,7,7};  
    var result = 0L;
    var x = 3;

    result = FindNextCloseset(valueCov, x, result);

    Console.WriteLine(result);

    result = FindNextCloseset(valueCov, x, result);

    Console.WriteLine(result);
}

public static long FindNextCloseset(long[] values, int occurrence, long searchAfterValue)
{
    return values
        .Where(i => i > searchAfterValue)
        .GroupBy(i => i)
        .Where(i => i.Count() == occurrence)
        .Select(i => i.Key)
        .FirstOrDefault();  
}

Fiddle

答案 1 :(得分:0)

这是我想出的一个解决方案,你可以从这开始。它很长,你应该创建单元测试并重构它,因为它包含很多逻辑:

public static int FindIndexOfClosest(List<long> list, long value_to_search_for, int time)
{
    int index = list.BinarySearch(value_to_search_for);

    if (index >= 0) //We found the value
    {
        while (index > 0 && list[index - 1] == value_to_search_for)
            //BinarySearch might not return the index of the first occurance
        {
            index--;
        }

        index += time;

        if (index >= list.Count || list[index] != value_to_search_for)
            return -1;

        return index;

    }
    else
    {
        int location_for_next_larger_number = ~index; //This could be equal to Count

        int? larger_index = location_for_next_larger_number == list.Count
            ? (int?) null
            : location_for_next_larger_number;

        int? smaller_index = null;

        if (!larger_index.HasValue)
        {
            if (list.Count > 0)
                smaller_index = list.Count - 1;
        }
        else
        {
            int i = location_for_next_larger_number;

            while (i > 0 && list[i - 1] == larger_index.Value)
                i--;

            if (i > 0)
                smaller_index = i - 1;

        }

        int? closer_number_index = null;

        if (larger_index.HasValue)
            closer_number_index = larger_index.Value;

        if (smaller_index.HasValue)
        {
            if (!closer_number_index.HasValue)
                closer_number_index = smaller_index.Value;
            else
            {
                if (Math.Abs(list[smaller_index.Value] - value_to_search_for) < Math.Abs(list[closer_number_index.Value] - value_to_search_for))
                    closer_number_index = smaller_index.Value;
            }
        }

        if (closer_number_index.HasValue)
        {
            while (closer_number_index > 0 && list[closer_number_index.Value - 1] == list[closer_number_index.Value])
                closer_number_index = closer_number_index.Value - 1;

            long closer_number_value = list[closer_number_index.Value];

            closer_number_index += time;

            if (closer_number_index.Value >= list.Count || list[closer_number_index.Value] != closer_number_value)
                return -1;

            return closer_number_index.Value;

        }

        return -1;
    }

}

你可以这样测试:

static void Main(string[] args)
{
    List<long> list = new List<long> {1, 2, 2, 2, 5, 5, 5, 5, 6, 6, 7, 7, 7};

    var test1 = FindIndexOfClosest(list, 3, 0); // returns 1
    var test2 = FindIndexOfClosest(list, 3, 1); // returns 2
    var test3 = FindIndexOfClosest(list, 3, 2); // returns 3
    var test4 = FindIndexOfClosest(list, 3, 3); // returns -1 (not found)
}

确保您为FindIndexOfClosest方法提供的列表始终排序。

查看reference for the BinarySearch method,因为它可以帮助您理解我提供的代码。