Search code examples
c#arraystestingrecursionmax

c# find max value recursive (fastest)


I'm out of ideas on this one. Tried originally myself and then copied from SO and google, which worked on all cases except one, however still didn't find a recursive algorithm that is fast enough for that particular test case in my assignment :/

In any case, why this:

        public static int FindMaximum(int[] array)
        {
            if (array is null)
            {
                throw new ArgumentNullException(nameof(array));
            }

            if (array.Length == 0)
            {
                throw new ArgumentException(null);
            }

            return FindMaxRec(array, array.Length);
        }

        public static int FindMaxRec(int[] arr, int n)
        {
            if (n == 1)
            {
                return arr[0];
            }

            return Math.Max(arr[n - 1], FindMaxRec(arr, n - 1));
        }

doesn't work with this TestCase?:

        [Test]
        [Order(0)]
        [Timeout(5_000)]
        public void FindMaximum_TestForLargeArray()
        {
            int expected = this.max;
            int actual = FindMaximum(this.array);
            Assert.AreEqual(expected, actual);
        }

EDIT 1:

This works fine though, but I need recursive:

        public static int FindMaximum(int[] array)
        {
            if (array is null)
            {
                throw new ArgumentNullException(nameof(array));
            }

            if (array.Length == 0)
            {
                throw new ArgumentException(null);
            }

            int maxValue = int.MinValue;

            for (int i = 0; i < array.Length; i++)
            {
                if (array[i] > maxValue)
                {
                    maxValue = array[i];
                }
            }

            return maxValue;
        }


Solution

  • You can try splitting array in two:

    public static int FindMaximum(int[] array) {
      if (null == array)
        throw new ArgumentNullException(nameof(array));
      if (array.Length <= 0)
        throw new ArgumentException("Empty array is not allowed.", nameof(array));
    
      return FindMaxRec(array, 0, array.Length - 1);
    }
    
    private static int FindMaxRec(int[] array, int from, int to) {
      if (to < from)
        throw new ArgumentOutOfRangeException(nameof(to));
      if (to <= from + 1)
        return Math.Max(array[from], array[to]);
    
      return Math.Max(FindMaxRec(array, from, (from + to) / 2),
                      FindMaxRec(array, (from + to) / 2 + 1, to));
    }
    

    Demo:

    Random random = new Random(123);
    
    int[] data = Enumerable
      .Range(0, 10_000_000)
      .Select(_ => random.Next(1_000_000_000))
      .ToArray();
    
    Stopwatch sw = new Stopwatch();
    
    sw.Start();
    
    int max = FindMaximum(data);
    
    sw.Stop(); 
    
    Console.WriteLine($"max  = {max}");
    Console.WriteLine($"time = {sw.ElapsedMilliseconds}");
    

    Outcome:

    max  = 999999635
    time = 100