Last active
April 25, 2020 11:57
-
-
Save kunitsyn/7f5fdbe17771fa4ec5c8b169017eef41 to your computer and use it in GitHub Desktop.
Binary searching imaginary sorted merge of two sorted arrays
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.Linq; | |
namespace BinarySearchOlymp | |
{ | |
class Program | |
{ | |
enum ResultType { FOUND, NOT_FOUND }; | |
struct BinarySearchResult { public ResultType type; public int index; }; | |
private static int? FindIndexByValue(int[] array1, int[] array2, int targetValue) | |
{ | |
var res1 = BinarySearch(array1, targetValue); | |
var res2 = BinarySearch(array2, targetValue); | |
if (res1.type == ResultType.FOUND || res2.type == ResultType.FOUND) | |
{ | |
return res1.index + res2.index; | |
} | |
return null; | |
} | |
// returns found index or, if not found, how many elements are less than targetValue | |
private static BinarySearchResult BinarySearch(int[] array, int targetValue) | |
{ | |
if (array.Length == 0) | |
{ | |
return new BinarySearchResult() { type = ResultType.NOT_FOUND, index = 0 }; | |
} | |
int l = 0; | |
int r = array.Length - 1; | |
while (l <= r) | |
{ | |
int i = (l + r) / 2; | |
if (array[i] < targetValue) l = i + 1; | |
else if (array[i] > targetValue) r = i - 1; | |
else return new BinarySearchResult() { type = ResultType.FOUND, index = i }; | |
} | |
if (l == array.Length) | |
{ | |
return new BinarySearchResult() { type = ResultType.NOT_FOUND, index = array.Length }; | |
} | |
if (array[l] < targetValue) | |
{ | |
return new BinarySearchResult() { type = ResultType.NOT_FOUND, index = l + 1 }; | |
} | |
return new BinarySearchResult() { type = ResultType.NOT_FOUND, index = l }; | |
} | |
static void Main(string[] args) | |
{ | |
Test( | |
new int[] { }, | |
new int[] { }, | |
33); | |
Test( | |
new int[] { 12, 17, 34, 42, 44, 46, 47, 51, 67, 89, 111, 116, 118, 163, 164, 177, 189, 192, 195, 197, 214, 217, 242, 244, 276, 280, 286, 291, 305, 308, 309 }, | |
new int[] { 0, 0, 16, 17, 26, 29, 34, 41, 45, 66, 86, 89, 100, 103, 139, 164, 172, 184, 191, 192 }, | |
163); | |
Test( | |
new int[] { 4 }, | |
new int[] { 15, 42, 48, 56, 58, 74, 77, 80, 92, 93, 100, 102 }, | |
92); | |
var r = new Random(); | |
for (int i = 0; i < 200; i++) | |
{ | |
int length1 = r.Next(50); | |
int length2 = r.Next(50); | |
int[] array1 = Enumerable.Range(1, length1).Select(x => r.Next(length1)).OrderBy(x => x).ToArray(); | |
int[] array2 = Enumerable.Range(1, length2).Select(x => r.Next(length2)).OrderBy(x => x).ToArray(); | |
int targetExistingValue = array1.Concat(array2).ElementAt(r.Next(length1 + length2)); | |
Test(array1, array2, targetExistingValue); | |
int targetMissingValue = Enumerable.Range(1, length1 + length2 + 1).First(x => Array.IndexOf(array1, x) == -1 && Array.IndexOf(array2, x) == -1); | |
Test(array1, array2, targetMissingValue); | |
} | |
} | |
private static void Test(int[] array1, int[] array2, int targetValue) | |
{ | |
int[] truth = FindIndexByValueGroundTruth(array1, array2, targetValue); | |
int? test = FindIndexByValue(array1, array2, targetValue); | |
if (test == null && truth.Length > 0) | |
{ | |
Debug.WriteLine("not found where was supposed to find"); | |
Debug.WriteLine("array1 = " + p(array1) + " array2 = " + p(array2) + " targetValue = " + targetValue + " truth = " + p(truth)); | |
} | |
if (test != null && truth.Length == 0) | |
{ | |
Debug.WriteLine("found where not supposed to find"); | |
Debug.WriteLine("array1 = " + p(array1) + " array2 = " + p(array2) + " targetValue = " + targetValue + " test = " + test); | |
} | |
if (test != null && Array.IndexOf(truth, test) == -1) | |
{ | |
Debug.WriteLine("found not correct"); | |
Debug.WriteLine("array1 = " + p(array1) + " array2 = " + p(array2) + " targetValue = " + targetValue + " truth = " + p(truth) + " test = " + test); | |
} | |
} | |
private static int[] FindIndexByValueGroundTruth(int[] array1, int[] array2, int targetValue) | |
{ | |
return array1.Concat(array2).OrderBy(x => x).Select((x, i) => new int[] { x, i }).Where((x, i) => x[0] == targetValue).Select(x => x[1]).ToArray(); | |
} | |
private static string p(int[] array) | |
{ | |
return string.Join(", ", array); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment