How to save CPU cycles when searching for a value in a sorted list?

后端 未结 6 1418
不思量自难忘°
不思量自难忘° 2021-02-10 05:16

In CodinGame learning platform, one of the questions used as an example in a C# tutorial is this one:

The aim of this exercise is to check the presence of

相关标签:
6条回答
  • 2021-02-10 05:34
     public static bool Exists(int[] ints, int k)
            {
                var d = 0;
                var f = ints.Length - 1;
                if (d > f) return false;
                if (k > ints[f] || k < ints[d]) return false;
                if (k == ints[f] || k == ints[d]) return true;
                return (BinarySearch(ints, k, d, f) > 0);
            }
    
     public static int BinarySearch(int[] V, int Key, int begin, int end)
            {
                if (begin > end)
                    return -1;
                var MidellIndex = (begin + end) / 2;
    
                if (Key == V[MidellIndex])
                    return MidellIndex;
                else
                {
                    if (Key > V[MidellIndex])
                    {
                        begin = MidellIndex + 1;
                        return BinarySearch(V, Key, begin, end);
                    }
                    else
                    {
                        end = MidellIndex - 1;
                        return BinarySearch(V, Key, begin, end);
                    }
                }
    
            }
    
    0 讨论(0)
  • 2021-02-10 05:36

    If you are trying to squeeze every ounce of speed out of it... consider that your array has 1..100 and you want to search for 78. Your algorithm needs to search and compare 78 items before you find the right one. How about instead you search the first item and its not there, so you jump to array size / 2 and find 50? Now you skipped 50 iterations. You know that 78 MUST be in the top half of the array, so you can again split it in half and jump to 75, etc. By continuously splitting the array in half, you do much fewer iterations then your brute force approach.

    0 讨论(0)
  • 2021-02-10 05:46

    Yes, I think that binary search O(log(N)) complexity v. O(N) complexity is the solution:

       public static bool Exists(int[] ints, int k) {
         return Array.BinarySearch(ints, k) >= 0;
       }
    

    since Array.BinarySearch return non-negative value if the item (k) has been found:

    https://msdn.microsoft.com/en-us/library/2cy9f6wb(v=vs.110).aspx

    Return Value Type: System.Int32 The index of the specified value in the specified array, if value is found; otherwise, a negative number.

    0 讨论(0)
  • 2021-02-10 05:46
    class Answer
    {
        public static bool Exists(int[] ints, int k)
        {
            int index = Array.BinarySearch(ints, k);
            if (index > -1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        static void Main(string[] args)
        {
            int[] ints = { -9, 14, 37, 102 };
            Console.WriteLine(Answer.Exists(ints, 14)); // true
            Console.WriteLine(Answer.Exists(ints, 4)); // false
        }
    
    }
    
    0 讨论(0)
  • 2021-02-10 05:52

    Here is a fast method for an ordered array

    public static class Answer
    {
        public static bool Exists( int[] ints, int k )
        {
            var lower = 0;
            var upper = ints.Length - 1;
    
            if ( k < ints[lower] || k > ints[upper] ) return false;
            if ( k == ints[lower] ) return true;
            if ( k == ints[upper] ) return true;
    
            do
            {
                var middle = lower + ( upper - lower ) / 2;
    
                if ( ints[middle] == k ) return true;
                if ( lower == upper ) return false;
    
                if ( k < ints[middle] )
                    upper = Math.Max( lower, middle - 1 );
                else
                    lower = Math.Min( upper, middle + 1 );
            } while ( true );
        }
    }
    

    Takes around 50 ticks on my cpu (with 90.000.000 items in the array)

    Sample on dotnetfiddle

    0 讨论(0)
  • 2021-02-10 05:52

    Yes, BinarySearch would be faster than most algorithms you can write manually. However, if the intent of the exercise is to learn how to write an algorithm, you are on the right track. Your algorithm, though, makes an unnecessary check with if (i > k) ... why do you need this?

    Below is my general algorithm for simple requirements like this. The while loop like this is slightly more performant than a for-loop and out performs a foreach easily.

    public class Answer
    {
        public static bool Exists(int[] ints, int k)
        {
            var i = 0;
            var hasValue = false;
    
            while(i < ints.Length && !hasValue)
            {
                hasValue = ints[i] == k;
                ++i;
            }
    
            return hasValue;
        }
    }
    
    0 讨论(0)
提交回复
热议问题