Find closest number in a list

1,Problem

There are two ordered list, the list a and the list b, such as:

a=>[1,14,20,36]

b=>[2,7,11,25,32,39]

the result that I want to get is:

result=>[(2,1),(7,null),(11,14),(25,null),(32,null),(39,36)]

Put it into word: find the closest number(which delta between counterpart  is less than 5) in list a for each item in list b.

 

First of all, I decide to divide the problem to:

1,find closest number for each item in a, since a is less elements than b.

2,compose a result into a list. if no proper value be found, put it to null.

 

Because a&b are ordered list, so binary search is fast way to find out corresponding closest value. The complexity of binary search for a ordered list is O(log(N)).Each of item in list a have O(N), so the total complexity is O(N*log(N))。

 

2,Code

How to use the code:

static void Main(string[] args)

{

    int[] arrTime = { 1, 3, 5, 7, 8, 9, 10, 12, 15, 18, 25 };

    int[] arrAlign = { 3, 6, 11, 15, 22 };



    FindClosestNumber finder = new FindClosestNumber(3);



    var lst = finder.FindClosestAlignment(arrTime, arrAlign);



    foreach (var item in lst)

    {

        Console.WriteLine("{0}\t\t{1}", item.Time, item.Alignment);

    }



    Console.ReadKey();



}

 

There is the code:

public class Pair

    {

        public Pair(int? time, int? alignment)

        {

            Time = time;

            Alignment = alignment;

        }

        public int? Time { set; get; }

        public int? Alignment { set; get; }

    }



public class FindClosestNumber

    {



        public int Threshold { get; set; }



        public FindClosestNumber()

        {

            this.Threshold = 50;



        }

        public FindClosestNumber(int threshold)

        {

            this.Threshold = threshold;

        }





        public  List<Pair> FindClosestAlignment(int[] arrTime, int[] arrAlignment)

        {

            List<Pair> list = FindClosestTime(arrTime, arrAlignment);



            List<Pair> reslut = new List<Pair>();

            for (int i = 0; i < arrTime.Length; i++)

            {

                Pair pair = new Pair(arrTime[i], null);

                foreach (var p in list)

                {

                    if (pair.Time == p.Time)

                        pair.Alignment = p.Alignment;

                }

                reslut.Add(pair);

            }



            return reslut;

        }



        private  List<Pair> FindClosestTime(int[] arrTime, int[] arrAlignment)

        {

            List<Pair> list = new List<Pair>();



            for (int i = 0; i < arrAlignment.Length; i++)

            {

                int el = arrAlignment[i];

                int index = FindClosestIndexInOrderList(el, arrTime, this.Threshold);

                if (index == -1)

                {

                    list.Add(new Pair(null, el));

                }

                else

                {

                    list.Add(new Pair(arrTime[index], el));

                }

            }



            return list;



        }



        private  int FindClosestIndexInOrderList(int val, int[] arr, int threshold)

        {

            int index = Array.BinarySearch(arr, val);

            if (index >= 0)

            {//found

                return index;

            }

            else

            {

                //bitwise complement for index

                int compl = (~index);

                if (compl == arr.Length)

                {//val is biggest value in the arr



                    if (Math.Abs(arr[arr.Length - 1] - val) > threshold)

                        return -1;

                    else

                        return (arr.Length - 1);

                }

                else if (compl == 0)

                {//val is smallest value in the arr

                    if (Math.Abs(arr[0] - val) > threshold)

                        return -1;

                    else

                        return 0;

                }

                else

                {

                    int preIndex = compl - 1;



                    int deltaToPrevious = Math.Abs(arr[preIndex] - val);

                    int deltaToCurrent = Math.Abs(arr[compl] - val);



                    if (deltaToPrevious > threshold)

                        return -1;

                    if (deltaToCurrent > threshold)

                        return -1;



                    return deltaToPrevious <= deltaToCurrent ? preIndex : compl;

                }

            }

        }

    }

你可能感兴趣的:(number)