Description
I am not well trained into solving algorithms but from time to time this topic raises my interest and I find my self drawn into wanting to understand the underlying logic. I recently found a problem that I found to interresting to solve, it’s a Microsoft engineer interviewing question and I followed along the question and the solution and I might say the following:
- I am a bit disappointing that the interviewer was only focused on having the problem solved in his own way
- The solution is not the best
The problem to solve was:
Given a list of integers L and a number K, write a function to partition L into elements that are <K, =K, >K. There is no need for the partions to be sorted, so a sorting algorithm is out of question because it’s not efficient in this case.
E.G.
Given a list 4 5 3 2 1 0 and K = 3 we need to rearrange the list L to be 2 1 0 3 4 5 (more or less. Important is that 3 is in the middle, smaller values on the left, higher values on the right).
Classic Solution
static void PartitionKBasedMicrosoftSolving(int[] array, int k) { void Swap(ref int[] arr, int index1, int index2) { int swap = arr[index2]; arr[index2] = arr[index1]; arr[index1] = swap; } int mid = 0; int s = 0; int l = array.Length - 1; while (mid < l) { if (array[mid] < k) { Swap(ref array, s, mid); s++; mid++; } else if (array[mid] >= k) { Swap(ref array, l, mid); l--; } else { mid++; } } }
My Simplified approach
static void PartitionKBasedCustom(int[] array, int k) { void Swap(ref int[] arr, int index1, int index2) { int swap = arr[index2]; arr[index2] = arr[index1]; arr[index1] = swap; } //4 5 3 2 1 2 = 1 //2 5 3 2 1 4 = 2 //2 1 3 2 5 4 = 3 //2 1 2 3 5 4 = 4 int mid = array.Length / 2; for (int i = 0, j = array.Length - 1; i < array.Length - mid && j >= mid; i++, j--) { if (array[i] > array[j]) { Swap(ref array, i, j); } } };
To understand the microsoft interview solution you can follow the link: https://www.youtube.com/watch?v=UaI3WeesCoE&list=RDCMUCNc-Wa_ZNBAGzFkYbAHw9eg&start_radio=1&t=2433
What I did is to write in code what my brain did when solving this in my head:
- iterate the list from left to mid, and from right to mid
- when an element on the left is greater then an element from the right, swap them
Performance
This might not be a stellar test but i ran a couple of arrays against the 2 methods and the results show that my simple approach is about 4 times faster:
int count = 1000000; int seed = 0; //a list of random arrays List<int[]> randomArrays = Enumerable.Range(0, count).Select(x => Enumerable .Range(0, new Random(seed++).Next(0, 1000)) .Select(x => x) .ToArray()).ToList(); //timing my method Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); for (int i = 0; i < 1000000; i++) { PartitionKBasedCustom(randomArrays[i], 3); } stopwatch.Stop(); Console.WriteLine(stopwatch.ElapsedMilliseconds); //timing the classical method stopwatch.Restart(); for (int i = 0; i < 1000000; i++) { PartitionKBasedMicrosoftSolving(randomArrays[i], 3); } stopwatch.Stop(); Console.WriteLine(stopwatch.ElapsedMilliseconds);