--- tags: algorithms --- <style>.markdown-body { max-width: 1200px; }</style> [AlgoExpert Cert](https://certificate.algoexpert.io/AE-3dece3260e) # Algorithms ## Levinstein Distance ```csharp= public static int GetLevinsteinDistanceBase(string source, string target){ var costMatrix = Enumerable.Range(0, source.Length+1) .Select(line => new int[target.Length+1]) .ToArray(); for(var row = 1; row <= source.Length; row++){ costMatrix[row][0] = row; } for(var col = 1; col <= target.Length; col++){ costMatrix[0][col] = col; } for (var row = 1; row <= source.Length; row++) { for (var col = 1; col <= target.Length; col++) { var insertion = costMatrix[row][col-1] + 1; var deletion = costMatrix[row-1][col] + 1; var substitution = costMatrix[row-1][col-1] + (source[row-1] == target[col-1] ? 0 : 1); costMatrix[row][col] = Math.Min(Math.Min(insertion, deletion), substitution); } } return costMatrix[source.Length][target.Length]; } public static int GetLevinsteinDistance2(string source, string target){ // trim all mathing caracters to avoid extra calculation var startIndex = 0; var sourceEnd = source.Length; var targetEnd = target.Length; while (startIndex < sourceEnd && startIndex < targetEnd && source[startIndex] == target[startIndex]) { startIndex++; } while (startIndex < sourceEnd && startIndex < targetEnd && source[sourceEnd - 1] == target[targetEnd - 1]) { sourceEnd--; targetEnd--; } var sourceLength = sourceEnd - startIndex; var targetLength = targetEnd - startIndex; if(sourceLength == 0) return targetLength; if(targetLength == 0) return sourceLength; var sourceSpan = source.AsSpan().Slice(startIndex, sourceLength); var targetSpan = target.AsSpan().Slice(startIndex, targetLength); // calculate cost var previousRow = ArrayPool<int>.Shared.Rent(targetSpan.Length); for(var col = 0; col < targetSpan.Length; col++){ previousRow[col] = col+1; } for (var row = 0; row < sourceSpan.Length; row++) { var lastSubstitutionCOst = row; var lastInsertionCOst = row+1; for (var col = 0; col < targetSpan.Length; col++) { var deletion = previousRow[col]; var substitution = lastSubstitutionCOst + (sourceSpan[row] == targetSpan[col] ? 0 : 1); lastInsertionCOst = Math.Min(Math.Min(lastInsertionCOst, deletion)+1, substitution); lastSubstitutionCOst = deletion; previousRow[col] = lastInsertionCOst; } } var result = previousRow[targetSpan.Length-1]; ArrayPool<int>.Shared.Return(previousRow); return result; } public static int GetLevinsteinDistance3(string source, string target){ // trim all mathing caracters to avoid extra calculation var startIndex = 0; var sourceEnd = source.Length; var targetEnd = target.Length; while (startIndex < sourceEnd && startIndex < targetEnd && source[startIndex] == target[startIndex]) { startIndex++; } while (startIndex < sourceEnd && startIndex < targetEnd && source[sourceEnd - 1] == target[targetEnd - 1]) { sourceEnd--; targetEnd--; } var sourceLength = sourceEnd - startIndex; var targetLength = targetEnd - startIndex; if(sourceLength == 0) return targetLength; if(targetLength == 0) return sourceLength; var sourceSpan = source.AsSpan().Slice(startIndex, sourceLength); var targetSpan = target.AsSpan().Slice(startIndex, targetLength); // calculate cost var previousRow = ArrayPool<int>.Shared.Rent(targetSpan.Length); for(var col = 0; col < targetSpan.Length; col++){ previousRow[col] = col+1; } for (var row = 0; row < sourceSpan.Length; row++) { var lastSubstitutionCost = row; var lastInsertionCost = row + 1; for (var col = 0; col < targetSpan.Length; col++) { var localCost = lastSubstitutionCost; var deletionCost = previousRow[col]; if (sourceSpan[row] != targetSpan[col]) { localCost = Math.Min(lastInsertionCost, localCost); localCost = Math.Min(deletionCost, localCost); localCost++; } lastInsertionCost = localCost; previousRow[col] = localCost; lastSubstitutionCost = deletionCost; } } var result = previousRow[targetSpan.Length-1]; ArrayPool<int>.Shared.Return(previousRow); return result; } ``` ## Deserialize binary tree from a string ```csharp= void Main() { var s = "4(-21(3(7)(-8))(1))(6(5)(4))"; int i = 0; Build(s, ref i).D(); } TreeNode Build(string s, ref int i){ int val = 0; bool negative = false; while (i < s.Length && s[i] != '(' && s[i] != ')') { if (s[i] == '-') { negative = true; } else { val = 10 * val + (s[i] - '0'); } i++; } if (negative) val = -val; var root = new TreeNode(val); if (i < s.Length && s[i] == '(') { i++; root.left = Build(s, ref i); i++; if (i < s.Length && s[i] == '(') { i++; root.right = Build(s, ref i); i++; } } return root; } public class TreeNode { public int val; public TreeNode left; public TreeNode right; public TreeNode(int val = 0, TreeNode left = null, TreeNode right = null) { this.val = val; this.left = left; this.right = right; } } ``` ## Minimum sum ```csharp= public int MinSumOfLengths(int[] arr, int target) { int n = arr.Length; int [] best = new int[n]; Array.Fill(best, Int32.MaxValue); int sum = 0, start = 0, ans = Int32.MaxValue, bestSoFar = Int32.MaxValue; for(int i = 0; i < n; i++){ sum += arr[i]; while(sum > target){ sum -= arr[start]; start++; } if(sum == target){ $"sum [{start}:{i}] = {target}".D(); int currentLength = i + 1 - start ; if(start > 0 && best[start - 1] != Int32.MaxValue){ ans = Math.Min(ans, best[start - 1] + currentLength); } bestSoFar = Math.Min(bestSoFar, currentLength); } best[i] = bestSoFar; best.Print(); i.D("--"); } return ans == Int32.MaxValue ? -1 : ans; } ``` ## Regex matching ```csharp= void Main() { string s = "aab"; string p = "c*a*b"; matches(s,p).D(); } bool matches(string s, string p){ if(string.IsNullOrEmpty(p)) return string.IsNullOrEmpty(s); bool firstMatches = !string.IsNullOrEmpty(s) && (s[0] == p[0] || p[0] == '.'); // a*bc aaabc => a*bc, aabc => a*bc, abc => a*bc, bc => bc, bc => c,c = > true // c*a*b, aab => a*b, aab => a*b, ab => a*b, b => b => b; if(p.Length > 1 && p[1] == '*'){ return matches(s, p.Substring(2)) || firstMatches && matches(s.Substring(1), p); }else{ return firstMatches && matches(s.Substring(1), p.Substring(1)); } } ``` ## Optimal Account Balancing ```csharp= public class Solution { public int MinTransfers(int[][] transactions) { var debt = new Dictionary<int,int>(); foreach(var t in transactions){ debt[t[0]] = GetOrDefault(debt, t[0], 0) - t[2]; debt[t[1]] = GetOrDefault(debt, t[1], 0) + t[2]; } return helper(0, debt.Values.ToArray()); } int helper(int start, int[] debt){ while(start < debt.Length && debt[start] == 0) start++; if(start >= debt.Length) return 0; int min = Int32.MaxValue; for(int i = start + 1; i < debt.Length; i++){ if(debt[start] * debt[i] < 0){ debt[i] += debt[start]; min = Math.Min(min, 1 + helper(start+1, debt)); debt[i] -= debt[start]; } } return min; } int GetOrDefault(Dictionary<int,int> map, int key, int def){ if(!map.ContainsKey(key)){ return def; } return map[key]; } } ``` ## Remove comments ```csharp= void Main() { var source = new[]{"/*Test program */", "int main()", "{ ", " // variable declaration ", "int a, b, c;", "/* This is a test", " multiline ", " comment for ", " testing */", "a = b + c;", "}"}; f(source).D(); } List<string> f(string[] source){ bool isInBlock = false; var result = new List<string>(); var buffer = new StringBuilder(); foreach(var s in source){ int i=0; while(i < s.Length){ if(i < s.Length-1 && s[i] == '/' && s[i+1] == '/' && !isInBlock){ i = s.Length; }else if(i < s.Length-1 && s[i] == '/' && s[i+1] == '*' && !isInBlock){ isInBlock = true; i++; }else if(i < s.Length-1 && s[i] == '*' && s[i+1] == '/' && isInBlock){ isInBlock = false; i++; }else if(!isInBlock){ buffer.Append(s[i]); } i++; } if(!isInBlock){ result.Add(buffer.ToString()); buffer.Clear(); } } return result; } ``` ## Fenwick Tree ```csharp= void Main() { int[] array = new[]{2,1,1,3,2,3,4,5,6,7,8,9}; var ft = new FenwickTree(array); ft.BinaryTree.Print(); for(int i = 0; i < array.Length; i++){ $"i: [{i}], sum: [{ft.Query(i)}]".D(); } } public class FenwickTree{ int[] binaryTree; public FenwickTree(int[] array){ binaryTree = new int[array.Length+1]; for(int i = 1; i < binaryTree.Length; i++){ UpdateBinaryTree(binaryTree, i, array[i-1]); } } public void UpdateBinaryTree(int[] binaryTree, int index, int value){ while(index < binaryTree.Length){ binaryTree[index] += value; index += index & (-index); } } public int Query(int from, int to){ return Query(to) - Query(from-1); } public int Query(int index){ int sum = 0; index = index+1; while(index > 0){ sum += binaryTree[index]; index -= index & (-index); } return sum; } public int[] BinaryTree => binaryTree; } ``` ## Minimum Swaps To Make Sequences Increasing ```csharp= public class Solution { public int MinSwap(int[] A, int[] B) { int n1 = 0; int s1 = 1; for(int i = 1; i < A.Length; i++){ int n2 = Int32.MaxValue; int s2 = Int32.MaxValue; if(A[i] > A[i-1] && B[i] > B[i-1]){ n2 = n1; s2 = s1 + 1; } if(A[i-1] < B[i] && B[i-1] < A[i]){ n2 = Math.Min(n2, s1); s2 = Math.Min(s2, n1 + 1); } //$"i: [{i}], n1: {n1}, s1: {s1}, n2: {n2}, s2: {s2}".D(); n1 = n2; s1 = s2; } return Math.Min(n1,s1); } } ``` ## Min coin change ```csharp= void Main() { int n = 35; var denoms = new[]{1,5,10,25,100}; var mins = new int[n+1]; Array.Fill(mins, Int32.MaxValue); mins[0] = 0; int toCompare = 0; foreach(var denom in denoms){ for(int amount = 1; amount <= n; amount++){ if(amount >= denom){ if(mins[amount-denom] == Int32.MaxValue){ toCompare = mins[amount-denom]; }else{ toCompare = mins[amount-denom] + 1; } mins[amount] = Math.Min(toCompare, mins[amount]); } } } mins[n].Dump(); mins.Print(); } ``` ## Find missing numbers in array (1..n) ```csharp= void Main() { var nums = new[]{1,2,2,3,3,4,6,5,7}; for(int i = 0; i < nums.Length; i++){ int index = Math.Abs(nums[i]) - 1; if(nums[index] > 0){ nums[index] *= -1; } } nums.Dump(); var result = new List<int>(); for(int i = 0; i < nums.Length; i++){ if(nums[i] > 0) result.Add(i+1); } result.Dump(); } ``` ## Min Palindromic Cuts ```csharp= void Main() { string s = "noonabbad"; var lengths = BuildPalindromeTable(s); lengths.Dump(); int[] cuts = new int[s.Length]; for(int i = 0; i < s.Length; i++) { if(lengths[0,i]){ cuts[i] = 0; }else{ int min = 1 + cuts[i-1]; for(int j = 1; j < i; j++){ if(lengths[j,i]) { s.Substring(0,i).Dump(); min = Math.Min(min, cuts[j-1] + 1); } } cuts[i] = min; } } cuts.Print(); } public static bool[,] BuildPalindromeTable(string s){ int n = s .Length; bool[,] palindromeLengths = new bool[n, n]; for(int i = 0; i < n; i++){ for(int j = i; j < n; j++){ palindromeLengths[i,j] = isPalindrome(i,j,s); } } return palindromeLengths; } static bool isPalindrome(int startIndex, int endIndex, string s){ while(startIndex <= endIndex){ if(s[startIndex++] != s[endIndex--]) return false; } return true; } // palindrome ``` ## Decode Ways ```csharp= void Main() { var s = "120212"; var dp = new int[s.Length + 1]; dp[0] = 1; dp[1] = s[0] == '0' ? 0 : 1; for(int i = 2; i <= s.Length; i++){ Int32.TryParse(s.Substring(i-1, 1), out var oneDigit); Int32.TryParse(s.Substring(i-2, 2), out var twoDigit); $"{oneDigit}, {twoDigit}".Dump(); if(oneDigit != 0) dp[i] += dp[i-1]; if(twoDigit >= 10 && twoDigit <=26) dp[i] += dp[i-2]; } dp.Dump(); } ``` ## Longest Word ```csharp= /* Given a list of words, find the longest word made from other words in the list. */ void Main() { var words = new []{"big", "testing", "tester", "bad", "test", "testingtesterbigbadmouse", "bigbad", "mouse", "bigbadmouse", "testmouse", "testerbigmouse"}; var map = new Dictionary<string, bool>(); foreach(var word in words){ map.Add(word, true); } foreach(var word in words.OrderByDescending(s => s.Length)){ if(CanBuildWord(word, map, true)){ word.Dump(); } } map.Dump(); } bool CanBuildWord(string word, Dictionary<string, bool> map, bool isOriginal){ if(map.ContainsKey(word) && !isOriginal){ return map[word]; } for(int i = 1; i < word.Length; i++){ string left = word.Substring(0, i); string right = word.Substring(i); //$"{left}, {right}".Dump(); if(map.ContainsKey(left) && map[left] && CanBuildWord(right, map, false)){ return true; } } //$"Putting {word} into map with false value".Dump(); map[word] = false; return false; } ``` ## Largest Area in Histogram ```csharp= void Main() { var hist = new int[]{1,2,3,5,4,4,3,2,5}; MaxAreaHist(hist).Dump(); } int MaxAreaHist(int[] hist){ int i = 0; int maxArea = 0; Stack<int> stack = new Stack<int>(); while(i < hist.Length){ if(stack.Count == 0 || hist[stack.Peek()] <= hist[i]){ stack.Push(i++); }else{ int top = stack.Pop(); int width = stack.Count == 0 ? i : i - stack.Peek() - 1; int area = hist[top] * width; maxArea = Math.Max(maxArea, area); } } while(stack.Count != 0){ int top = stack.Pop(); int width = stack.Count == 0 ? i : i - stack.Peek() - 1; int area = hist[top] * width; maxArea = Math.Max(maxArea, area); } return maxArea; } ``` ## Four Number Sum ```csharp= using System.Collections.Generic; using System; public class Program { public static List<int[]> FourNumberSum(int[] array, int targetSum) { var map = new Dictionary<int, List<Pair>>(); var result = new List<int[]>(); for(int i = 0; i < array.Length - 1; i++){ for(int j = i + 1; j < array.Length; j++){ int sum = array[i] + array[j]; int compliment = targetSum - sum; if(map.ContainsKey(compliment)){ foreach(var complimentPair in map[compliment]){ result.Add(new int[]{array[i], array[j], array[complimentPair.i], array[complimentPair.j]}); Console.WriteLine($"{i}, {j}, {complimentPair.i}, {complimentPair.j}"); } } } for(int k = 0; k < i; k++){ int sum = array[k] + array[i]; if(!map.ContainsKey(sum)){ map.Add(sum, new List<Pair>(){new Pair(k, i)}); }else{ map[sum].Add(new Pair(k, i)); } } } return result; } public class Pair { public int i; public int j; public Pair(int i, int j){ this.i = i; this.j = j; } } } ``` ## Sum (without addition) ```csharp= /* Write a function that adds two numbers without using + or any arithmetic operators. */ void Main() { Sum2(2,3).Dump(); } // Recursive int Sum(int a, int b){ if(b == 0) return a; int sum = a ^ b; // XOR is equivalent to adding without carry int carry = (a & b) << 1; // carry is equivalent to AND and left shift. $"a: {Convert.ToString(a,2)}, \nb:{Convert.ToString(b,2)}, \nsum: {Convert.ToString(sum,2)}, \ncarry: {Convert.ToString(carry,2)}".Dump("--"); return Sum(sum, carry); } // Iterative int Sum2(int a, int b){ while(b != 0){ int sum = a ^ b; int carry = (a & b) << 1; a = sum; b = carry; } return a; } ``` ## Shuffle ```csharp= /* Write a method to shuffle a deck of cards. It must be a perfect shuffle, i.e. each of the 52! permutations of the deck has to be equally likely. */ void Main() { var nums = new[]{1,2,3,4,5,6,7,8,9,10,11,12,13}; Shuffle(nums).Print(); } int[] Shuffle(int[] nums){ Random rand = new Random(); for(int i = 0; i< nums.Length; i++){ int k = rand.Next(i+1); Swap(i, k, nums); } return nums; } int[] Shuffle1(int[] nums){ return ShuffleRecursively(nums, nums.Length -1 ); } int[] ShuffleRecursively(int[] nums, int i){ if(i == 0) return nums; ShuffleRecursively(nums, i-1); Random rand = new Random(); int k = rand.Next(i+1); Swap(k, i, nums); return nums; } static void Swap(int i, int j, int[] a){ int tmp = a[i]; a[i] = a[j]; a[j] = tmp; } ``` ## Simple Calculator ( with parenthesis) ```csharp= void Main() { string input = "7 + 3*2/6 + (3+4)*5"; Calculate(input).Dump(); } int Calculate(string s){ var listInput = s.ToCharArray().ToList(); listInput.RemoveAll(c => c == ' '); return Calculate(listInput); } int Calculate(List<char> s){ if(s.Count == 0) return 0; var stack = new Stack<int>(); int num = 0; var sign = '+'; while(s.Count > 0){ char c = s[0]; s.RemoveAt(0); if(Char.IsDigit(c)){ num = num * 10 + (c - '0'); } if(c == '(') num = Calculate(s); if(s.Count == 0 || c == '+' || c == '-' || c == '*' || c == '/' || c == ')'){ if(sign == '+'){ stack.Push(num); } if(sign == '-'){ stack.Push(-num); } if(sign == '*'){ int top = stack.Pop(); stack.Push(top * num); } if(sign == '/'){ int top = stack.Pop(); stack.Push(top / num); } sign = c; num = 0; if(sign == ')') break; } } stack.Dump(); return stack.Sum(); } ``` ## Phone Digit Words ```csharp= void Main() { var path = "C:\\temp\\words_alpha.txt"; var words = File.ReadAllLines(path); var trie = new Trie(); foreach(var word in words){ trie.Insert(word); } var input = Console.ReadLine(); while(input != ""){ GetSequence(input, trie).Dump(); input = Console.ReadLine(); } } List<string> GetSequence(string number, Trie trie){ var words = new List<string>(); GetSequence(number, 0, trie.Root, words); return words; } private void GetSequence(string number, int index, TrieNode currentNode, List<string> words){ if(index == number.Length){ if(Trie.IsTerminating(currentNode)){ words.Add(currentNode.Word); } return; } char digit = number[index]; var letters = GetT9Letters(digit); if(letters != null){ foreach(var letter in letters){ if(currentNode.Children.ContainsKey(letter)){ GetSequence(number, index + 1, currentNode.Children[letter], words); } } } } public char[] GetT9Letters(char digit){ var t9Letters = new char[][]{ null,null, new []{'a','b','c'}, new []{'d','e','f'}, new []{'g','h','i'}, new []{'j','k','l'}, new []{'m','n','o'}, new []{'p','q','r', 's'}, new []{'t','u','v'}, new []{'w','x','y','z'}}; if(!Char.IsDigit(digit)) return null; int index = digit - '0'; return t9Letters[index]; } public HashSet<string> walk(string word, Trie trie){ var currentNode = trie.Root; var result = new HashSet<string>(); char letter = word[0]; for(int i=0; i < word.Length; i++){ letter = word[i]; if(!currentNode.Children.ContainsKey(letter)){ return result; } currentNode = currentNode.Children[letter]; } Walk(currentNode, result); return result; } public void Walk(TrieNode currentNode, HashSet<string> result){ if(currentNode == null) return; if(Trie.IsTerminating(currentNode)){ result.Add(currentNode.Word); } foreach(var node in currentNode.Children.Values){ Walk( node, result); } } public class Trie{ public TrieNode Root = new TrieNode(); const char EndChar = '*'; public int Count; public static bool IsTerminating(TrieNode node){ return node.Children.ContainsKey(EndChar); } public bool Contains(string word){ TrieNode currentNode = Root; for(int i=0; i < word.Length; i++){ var letter = word[i]; if(!currentNode.Children.ContainsKey(letter)){ return false; } currentNode = currentNode.Children[letter]; } return IsTerminating(currentNode); } public void Insert(string word){ TrieNode currentNode = Root; for(int i=0; i < word.Length; i++){ var letter = word[i]; if(!currentNode.Children.ContainsKey(letter)){ currentNode.Children.Add(letter, new TrieNode()); } currentNode = currentNode.Children[letter]; } currentNode.Children[EndChar] = null; currentNode.Word = word; Count++; } } public class TrieNode{ public Dictionary<char, TrieNode> Children = new Dictionary<char, TrieNode>(); public string Word; } ``` ## LCS ```csharp= using System.Collections.Generic; using System; public class Program { public static List<char> LongestCommonSubsequence(string str1, string str2) { List<char> result = new List<char>(); int rows = str1.Length + 1; int columns = str2.Length + 1; int[,] dp = new int[rows, columns]; for(int row=0; row<rows; row++){ dp[row, 0] = 0; } for(int column = 0; column < columns; column++){ dp[0, column] = 0; } for(int row = 1; row < rows; row++){ for(int column = 1; column < columns; column++){ if(str1[row-1] == str2[column-1]){ dp[row,column] = 1 + dp[row-1, column-1]; }else{ dp[row,column] = Math.Max(dp[row-1, column], dp[row, column-1]); } } } int r = rows - 1; int c = columns - 1; while(r != 0 && c != 0){ if(dp[r,c] == dp[r, c-1]) { c--; }else if(dp[r,c] == dp[r-1, c]){ r--; }else{ result.Insert(0, str1[r-1]); r--; c--; } } return result; } } ``` ## Weaving Lists ```csharp= void Main() { var nums = new[]{50,20,60,10,25,70,5,15,65,80}; BstNode root = new BstNode(nums[0]); for(int i = 1; i<nums.Length; i++){ root.Insert(nums[i]); } var sequences = AllSequences(root); sequences.ToList().ForEach(s => s.Print()); } public List<List<int>> AllSequences(BstNode node){ List<List<int>> result = new List<List<int>>(); if(node == null){ result.Add(new List<int>()); return result; } var prefix = new List<int>(){node.value}; var leftSequences = AllSequences(node.left); var rightSequences = AllSequences(node.right); foreach(var left in leftSequences){ foreach(var right in rightSequences){ var woven = new List<List<int>>(); WeaveLists(left, right, prefix, woven); result.AddRange(woven); } } return result; } public void WeaveLists(List<int> first, List<int> second, List<int> prefix, List<List<int>> result){ if(first.Count == 0 || second.Count == 0){ var merged = new List<int>(prefix); merged.AddRange(first); merged.AddRange(second); result.Add(merged); //merged.Print(); return; } var firstHead = first.ElementAt(0); first.RemoveAt(0); prefix.Add(firstHead); WeaveLists(first, second, prefix, result); prefix.RemoveAt(prefix.Count-1); first.Insert(0, firstHead); var secondHead = second.ElementAt(0); second.RemoveAt(0); prefix.Add(secondHead); WeaveLists(first, second, prefix, result); prefix.RemoveAt(prefix.Count-1); second.Insert(0, secondHead); } public class BstNode { public readonly int value; public BstNode left; public BstNode right; public BstNode(int value) { this.value = value; } public void Insert(int val){ if(val < this.value){ if(this.left == null){ this.left = new BstNode(val); }else{ this.left.Insert(val); } }else{ if(this.right == null){ this.right = new BstNode(val); }else{ this.right.Insert(val); } } } } ``` ## Rotate Matrix ```csharp= static void rotate(int [,] matrix){ int n = matrix.GetLength(0); for(int layer = 0; layer < n; layer++) { int first = layer; int last = n - layer - 1; for(int i = first; i < last; i++) { int offset = i - first; int tmp = matrix[first, i]; matrix[first, i] = matrix[last-offset, first]; matrix[last-offset, first] = matrix[last, last-offset]; matrix[last, last-offset] = matrix[i, last]; matrix[i, last] = tmp; } } } ``` ## Binary Search (Insertion Point) - equivalent of Array.BinarySearch ```csharp= static int BinarySearch(int[] array, int target) { return bs(0, array.Length - 1, array, target); } static int bs(int start, int end, int[] array, int target){ int lastMid = start + (end - start) / 2; while(start <= end){ int mid = start + (end - start) / 2; lastMid = mid; if(array[mid] == target){ return mid; }else if(array[mid] > target){ end = mid - 1; }else{ start = mid + 1; lastMid++; } } return -1 * lastMid - 1; } ``` ## Sum of 2 linked lists ```csharp= /* Write a function to add 2 linked lists, where each linked list node represents a single digit. Example: Input: List 1: ( 1 -> 2 -> 5 ) List 2: ( 2 -> 4 -> 3 ) Output: ( 3 -> 6 -> 8 ) */ void Main() { var l1 = new LinkedListNode(9); l1.next = new LinkedListNode(9); l1.next.next = new LinkedListNode(9); var l2 = new LinkedListNode(9); l2.next = new LinkedListNode(9); l2.next.next = new LinkedListNode(9); Print(AddLists(l1,l2)); } public LinkedListNode AddLists(LinkedListNode l1, LinkedListNode l2){ var partial = AddListsUtil(l1, l2); if(partial.carry > 0){ return InsertBefore(partial.sum, partial.carry); } return partial.sum; } public PartialSum AddListsUtil(LinkedListNode l1, LinkedListNode l2){ if(l1 == null && l2 == null){ return new PartialSum(); } var partial = AddListsUtil(l1.next, l2.next); int value = l1.value + l2.value + partial.carry; var final = InsertBefore(partial.sum, value % 10); partial.carry = value / 10; partial.sum = final; return partial; } public LinkedListNode InsertBefore(LinkedListNode l, int value){ var node = new LinkedListNode(value); if(l != null){ node.next = l; } return node; } public class PartialSum{ public int carry; public LinkedListNode sum; } public class LinkedListNode { public int value; public LinkedListNode next; public LinkedListNode(int val){ this.value = val; } } static void Print(LinkedListNode l){ if(l == null) { "( )".Dump(); return;} Console.Write("\n( "); while(l.next != null){ Console.Write($" {l.value} ->"); l = l.next; } Console.Write($" {l.value}"); Console.Write(" )"); } ``` ## PowerSet (All subsets of a set) ```csharp= void Main() { var set = new List<int> {1,2,3}; int n = 1 << set.Count(); for(int i = 0; i < n; i++){ convertIntToSet(set, i).Dump($"{i}"); } } private static List<int> convertIntToSet(List<int> set, int n){ var result = new List<int>(); int index = 0; for(int i = n; i > 0; i >>=1){ if((i & 1) == 1){ result.Add(set[index]); } index++; } return result; } ``` ## Matrix Zigzag traverse ```csharp= using System; using System.Collections.Generic; public class Program { public static List<int> ZigzagTraverse(List<List<int>> array) { bool down = true; var result = new List<int>(); if(array == null) return result; int height = array.Count; int width = array[0].Count; int lastRow = height - 1; int lastColumn = width - 1; int totalCount = height * width; int r = 0; int c = 0; while(result.Count < totalCount){ result.Add(array[r][c]); if(down){ if(c == 0 || r == lastRow){ down = false; if(r == lastRow){ c++; }else{ r++; } }else{ r++; c--; } }else{ // going up if(r == 0 || c == lastColumn){ down = true; if(c == lastColumn){ r++; }else{ c++; } }else{ r--; c++; } } } return result; } } ``` ## Travelling salesperson (dynamic programming formula) $$ g(i,s)=Min_{k \epsilon s}(C_{ik} + g(k, s-\{k\})) $$ The formula is **recursive**. `i` - ith element of graph (start of graph) `g(i,s)` - the fucntion to calculate the optimal path `Cik` - cost of travelling from `i`th vertex to the next `S` - set of vertices `S - {k}` - set of vertices where vertex k is excluded from the set ## Min/Max subset sum (dynamic programming) ```java= static int isSubsetSum(int[] set, int sum, bool useMinItems = true){ bool[,] dp = new bool[set.Length + 1, sum + 1]; int[,] counts = new int[set.Length + 1, sum + 1]; for(int i = 0; i <= sum; i++){ dp[0, i] = false; counts[0,i] = -1; } for(int i = 0; i <= set.Length; i++){ dp[i,0] = true; counts[i,0] = 0; } for(int i = 1; i <= set.Length; i++){ for(int j = 1; j <= sum; j++){ if(set[i-1] > j){ dp[i,j] = dp[i-1,j]; counts[i,j] = counts[i-1,j]; }else{ dp[i,j] = dp[i-1, j] || dp[i-1, j - set[i-1]]; if(dp[i,j]) { counts[i,j] = useMinItems ? dp[i-1, j] // prefer using the sum without including the next item ? counts[i-1, j] : 1 + counts[i-1,j-set[i-1]] : Math.Max(counts[i-1,j], counts[i-1,j-set[i-1]] + 1); } } } } return counts[set.Length, sum]; } ``` ## Next permutation ```java= public class Solution { public void nextPermutation(int[] nums) { int i = nums.length - 2; while (i >= 0 && nums[i + 1] <= nums[i]) { i--; } if (i >= 0) { int j = nums.length - 1; while (j >= 0 && nums[j] <= nums[i]) { j--; } swap(nums, i, j); } reverse(nums, i + 1); } private void reverse(int[] nums, int start) { int i = start, j = nums.length - 1; while (i < j) { swap(nums, i, j); i++; j--; } } private void swap(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } } ``` ## Minimum Window Substring ```java= class Solution { public String minWindow(String searchString, String t) { Map<Character, Integer> requiredCharacters = buildMappingOfCharactersToOccurrences(t); Map<Character, Integer> windowCharacterMapping = new HashMap<Character, Integer>(); int left = 0; int right = 0; int totalCharFrequenciesToMatch = requiredCharacters.size(); int charFrequenciesInWindowThatMatch = 0; int minWindowLengthSeenSoFar = Integer.MAX_VALUE; String minWindow = ""; while (right < searchString.length()) { char characterAtRightPointer = searchString.charAt(right); addCharacterToHashtableMapping(windowCharacterMapping, characterAtRightPointer); boolean rightCharIsARequirement = requiredCharacters.containsKey(characterAtRightPointer); if (rightCharIsARequirement) { boolean requirementForCharacterMet = requiredCharacters.get(characterAtRightPointer) .intValue() == windowCharacterMapping.get(characterAtRightPointer).intValue(); if (requirementForCharacterMet) { charFrequenciesInWindowThatMatch++; } } while (charFrequenciesInWindowThatMatch == totalCharFrequenciesToMatch && left <= right) { char characterAtLeftPointer = searchString.charAt(left); int windowSize = right - left + 1; if (windowSize < minWindowLengthSeenSoFar) { minWindowLengthSeenSoFar = windowSize; minWindow = searchString.substring(left, right + 1); } windowCharacterMapping.put(characterAtLeftPointer, windowCharacterMapping.get(characterAtLeftPointer) - 1); boolean leftCharIsARequirement = requiredCharacters.containsKey(characterAtLeftPointer); if (leftCharIsARequirement) { boolean characterFailsRequirement = windowCharacterMapping.get(characterAtLeftPointer) .intValue() < requiredCharacters.get(characterAtLeftPointer).intValue(); if (characterFailsRequirement) { charFrequenciesInWindowThatMatch--; } } left++; } right++; } return minWindow; } private Map<Character, Integer> buildMappingOfCharactersToOccurrences(String s) { Map<Character, Integer> map = new HashMap<Character, Integer>(); for (int i = 0; i < s.length(); i++) { int occurrencesOfCharacter = map.getOrDefault(s.charAt(i), 0); map.put(s.charAt(i), occurrencesOfCharacter + 1); } return map; } private void addCharacterToHashtableMapping(Map<Character, Integer> map, Character c) { int occurrences = map.getOrDefault(c, 0); map.put(c, occurrences + 1); } } ``` ## Min Heap ```cs= public class Heap{ readonly List<int> array; readonly Func<int, int, bool> comparisonFunction; public Heap(Func<int, int, bool> comparisonFunction, List<int> list){ this.comparisonFunction = comparisonFunction; this.array = BuildHeap(list); } public int Peek(){ return array[0]; } public int Length{ get {return array.Count;} } public void Insert(int value){ array.Add(value); SiftUp(array.Count - 1, array); } public int Remove(){ Swap(0, array.Count - 1, array); int valueToReturn = array[array.Count - 1]; array.RemoveAt(array.Count-1); SiftDown(0, array.Count - 1, array); return valueToReturn; } private List<int> BuildHeap(List<int> list){ int firstParentIndex = (list.Count - 1 ) / 2; for(int i = firstParentIndex; i >= 0; i--){ SiftDown(i, list.Count - 1, list); } return list; } private void SiftUp(int currentIndex, List<int> heap){ while(currentIndex > 0){ int parentIndex = (currentIndex - 1) / 2; if(comparisonFunction(heap[currentIndex], heap[parentIndex])){ Swap(currentIndex, parentIndex, heap); } currentIndex = parentIndex; } } private void SiftDown(int currentIndex, int endIndex, List<int> heap){ int childOneIndex = (currentIndex * 2) + 1; while(childOneIndex <= endIndex){ int childTwoIndex = (currentIndex * 2) + 2 > endIndex ? -1 : (currentIndex * 2) + 2; int indexToSwap; if(childTwoIndex != -1 && comparisonFunction(heap[childTwoIndex], heap[childOneIndex])){ indexToSwap = childTwoIndex; }else{ indexToSwap = childOneIndex; } if(comparisonFunction(heap[indexToSwap], heap[currentIndex])){ Swap(currentIndex, indexToSwap, heap); currentIndex = indexToSwap; childOneIndex = (currentIndex * 2) + 1; }else{ return; } } } private void Swap(int i, int j, List<int> heap){ int tmp = heap[i]; heap[i] = heap[j]; heap[j] = tmp; } public static bool MinFunction(int a, int b){ return a < b; } public static bool MaxFunction(int a, int b){ return a > b; } } ``` ## Quickselect ```cs= using System; public class Program { public static int Quickselect(int[] array, int k) { int position = k - 1 ; return Quickselect(array, 0, array.Length - 1, position); } static int Quickselect(int[] array, int startIdx, int endIdx, int position){ while(true) { if(startIdx > endIdx) { throw new Exception("This should never happen") ; } int pivotIdx = startIdx; int leftIdx = startIdx + 1; int rightIdx = endIdx; while(leftIdx <= rightIdx) { if(array[leftIdx] > array[pivotIdx] && array[rightIdx] < array[pivotIdx] ){ swap(leftIdx, rightIdx, array); } if(array[leftIdx] <= array[pivotIdx]){ leftIdx++; } if(array[rightIdx] >= array[pivotIdx]){ rightIdx--; } } swap(rightIdx, pivotIdx, array); if(rightIdx == position){ return array[position]; }else if(rightIdx < position){ startIdx = rightIdx + 1; }else{ endIdx = rightIdx - 1; } } } static void swap(int i, int j, int[] array){ int tmp = array[i]; array[i] = array[j]; array[j] = tmp; } } ``` ## Reverse Linked List ```cs= public class Program { public static LinkedList ReverseLinkedList(LinkedList head) { LinkedList prev = null; while(head != null){ LinkedList next_node = head.Next; head.Next = prev; prev = head; head = next_node; } return prev; } public class LinkedList { public int Value; public LinkedList Next = null; public LinkedList(int value) { this.Value = value; } } } ``` ## LRUCache ```cs= using System.Collections.Generic; public class Program { public class LRUCache { public int maxSize; readonly Dictionary<string, Node> map; readonly Node head = new Node(); readonly Node tail = new Node(); public LRUCache(int maxSize) { this.maxSize = maxSize > 1 ? maxSize : 1; map = new Dictionary<string, Node>(maxSize); head.next = tail; tail.prev = head; } public void InsertKeyValuePair(string key, int value) { if(map.ContainsKey(key)){ Node node = map[key]; node.value = value; UpdateNode(node); }else{ if(map.Count >= maxSize){ Node leastRecent = tail.prev; map.Remove(leastRecent.key); RemoveNode(leastRecent); } Node newNode = new Node(); newNode.key = key; newNode.value = value; AddNode(newNode); map.Add(key, newNode); } } public LRUResult GetValueFromKey(string key) { var result = new LRUResult(false, -1); if(map.ContainsKey(key)){ var resultNode = map[key]; result.found = true; result.value = resultNode.value; UpdateNode(resultNode); } return result; } public string GetMostRecentKey() { Node mostRecentNode = head.next; return mostRecentNode.key; } private void AddNode(Node node){ // Add to head Node headNext = head.next; head.next = node; node.prev = head; node.next = headNext; headNext.prev = node; } private void RemoveNode(Node node){ Node nextNode = node.next; Node prevNode = node.prev; nextNode.prev = prevNode; prevNode.next = nextNode; } private void UpdateNode(Node node){ RemoveNode(node); AddNode(node); } } public class Node { public string key; public int value; public Node prev; public Node next; } public class LRUResult { public bool found; public int value; public LRUResult(bool found, int value) { this.found = found; this.value = value; } } } ``` ## Suffix Tries ```cs= using System.Collections.Generic; public class Program { public class TrieNode { public Dictionary<char, TrieNode> Children = new Dictionary<char, TrieNode>(); } public class SuffixTrie { public TrieNode root = new TrieNode(); public char endSymbol = '*'; public SuffixTrie(string str) { PopulateSuffixTrieFrom(str); } public void PopulateSuffixTrieFrom(string str) { for(int i = 0; i < str.Length; i++){ PopulateStartingAt(i, str); } } public bool Contains(string str) { TrieNode node = root; for(int i = 0; i < str.Length; i++){ char letter = str[i]; if(!node.Children.ContainsKey(letter)){ return false; } node = node.Children[letter]; } return node.Children.ContainsKey(endSymbol); } public void PopulateStartingAt(int i, string str){ TrieNode node = root; for(int j = i; j < str.Length; j++){ char letter = str[j]; if(!node.Children.ContainsKey(letter)){ node.Children.Add(letter, new TrieNode()); } node = node.Children[letter]; } node.Children.Add(endSymbol, null); } } } ``` ## Spiral Traverse ```cs= using System.Collections.Generic; using System; public class Program { public static List<int> SpiralTraverse(int[,] array) { var result = new List<int>(); int rowBegin = 0; int columnBegin = 0; int rowEnd = array.GetLength(0)-1; int columnEnd = array.GetLength(1)-1; int maxSize = (rowEnd + 1) * (columnEnd + 1); while(result.Count < maxSize){ for(int i=columnBegin; i<= columnEnd; i++){ result.Add(array[rowBegin, i]); } rowBegin++; for(int i=rowBegin; i<= rowEnd; i++){ result.Add(array[i, columnEnd]); } columnEnd--; if(columnBegin <= columnEnd && result.Count < maxSize){ for(int i=columnEnd; i>=columnBegin; i--){ result.Add(array[rowEnd, i]); } } rowEnd--; if(rowBegin <= rowEnd && result.Count < maxSize){ for(int i=rowEnd; i>=rowBegin; i--){ result.Add(array[i, columnBegin]); } } columnBegin++; } return result; } } ``` ## In Order Traversal (Non-Recursive) ```cs= using System; using System.Collections.Generic; public class Program { public static void IterativeInOrderTraversal(BinaryTree tree, Action<BinaryTree> callback) { if(tree == null) return; BinaryTree current = tree; Stack<BinaryTree> stack = new Stack<BinaryTree>(); while(current != null || stack.Count != 0){ while(current != null){ stack.Push(current); current = current.left; } current = stack.Pop(); callback(current); current = current.right; } } public class BinaryTree { public int value; public BinaryTree left; public BinaryTree right; public BinaryTree parent; public BinaryTree(int value) { this.value = value; } public BinaryTree(int value, BinaryTree parent) { this.value = value; this.parent = parent; } } } ``` ## Merge Linked Lists ```cs= public class Program { // This is an input class. Do not edit. public class LinkedList { public int value; public LinkedList next; public LinkedList(int value) { this.value = value; this.next = null; } } public static LinkedList mergeLinkedLists(LinkedList headOne, LinkedList headTwo) { LinkedList p1 = headOne; LinkedList p2 = headTwo; LinkedList prev = null; while(p1 != null && p2 != null){ if(p1.value < p2.value){ prev = p1; p1 = p1.next; }else{ if(prev != null) prev.next = p2; prev = p2; p2 = p2.next; prev.next = p1; } } if(p1 == null){ prev.next = p2; } return headOne.value < headTwo.value ? headOne : headTwo; } } ```