---
# System prepended metadata

title: Algorithms
tags: [algorithms]

---

---
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;
	}
}
```