├── .gitattributes ├── .gitignore ├── CrackingTheCodingInterview ├── App.config ├── Code │ ├── AssemblyAttributes.cs │ ├── Chapter 1 │ │ ├── Question1_1.cs │ │ ├── Question1_2.cs │ │ ├── Question1_3.cs │ │ ├── Question1_4.cs │ │ ├── Question1_5.cs │ │ ├── Question1_6.cs │ │ ├── Question1_7.cs │ │ ├── Question1_8.cs │ │ └── Question1_9.cs │ ├── Chapter 16 │ │ ├── Question16_1.cs │ │ ├── Question16_2.cs │ │ └── Question16_4.cs │ ├── Chapter 2 │ │ ├── Question2_1.cs │ │ ├── Question2_2.cs │ │ ├── Question2_3.cs │ │ ├── Question2_4.cs │ │ ├── Question2_5.cs │ │ ├── Question2_6.cs │ │ ├── Question2_7.cs │ │ └── Question2_8.cs │ ├── Chapter 3 │ │ ├── Question3_2.cs │ │ ├── Question3_3.cs │ │ ├── Question3_4.cs │ │ ├── Question3_5.cs │ │ ├── Question3_6.cs │ │ └── SortedStack.cs │ ├── Chapter 4 │ │ ├── Question4_1.cs │ │ ├── Question4_2.cs │ │ ├── Question4_3.cs │ │ └── Question4_4.cs │ ├── Chapter 5 │ │ ├── Question5_1.cs │ │ └── Question5_2.cs │ ├── Code.csproj │ ├── Data structures │ │ ├── BinaryTreeNode.cs │ │ ├── Digit.cs │ │ ├── Node.cs │ │ └── TreeNode.cs │ ├── MeetingScheduler │ │ ├── Meeting.cs │ │ ├── MeetingScheduler.cs │ │ └── Person.cs │ ├── Misc │ │ ├── BitHelpers.cs │ │ ├── CountingIslands.cs │ │ ├── LeastRecentlyUsedCache.cs │ │ ├── SubstringSearch.cs │ │ └── WordFrequencies.cs │ ├── OverlappingParties │ │ ├── OverlappingParties.cs │ │ └── Party.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Questions.txt │ ├── Settings.StyleCop │ └── packages.config ├── CodeFSharp │ ├── AssemblyInfo.fs │ ├── CodeFSharp.fsproj │ ├── Question1_1.fs │ └── Script.fsx ├── CrackingTheCodingInterview.csproj ├── CrackingTheCodingInterview.sln ├── Properties │ └── AssemblyInfo.cs └── TestsFSharp │ ├── AssemblyInfo.fs │ ├── Script.fsx │ ├── Test1_1.fs │ ├── TestsFSharp.fsproj │ └── packages.config ├── StyleCop.ruleset └── Tests ├── AssemblyAttributes.cs ├── Chapter 1 ├── Test1_1.cs ├── Test1_2.cs ├── Test1_3.cs ├── Test1_4.cs ├── Test1_5.cs ├── Test1_6.cs ├── Test1_7.cs ├── Test1_8.cs └── Test1_9.cs ├── Chapter 16 ├── Tests16_1.cs ├── Tests16_2.cs └── Tests16_4.cs ├── Chapter 2 ├── Test2_1.cs ├── Test2_2.cs ├── Test2_3.cs ├── Test2_4.cs ├── Test2_5.cs ├── Test2_6.cs ├── Test2_7.cs └── Test2_8.cs ├── Chapter 3 ├── SortedStackTests.cs ├── Test3_2.cs ├── Test3_3.cs ├── Test3_4.cs ├── Test3_5.cs └── Test3_6.cs ├── Chapter 4 ├── Test4_1.cs ├── Test4_2.cs ├── Test4_3.cs └── Test4_4.cs ├── Chapter 5 ├── Test5_1.cs └── Tests5_2.cs ├── Data structures ├── DigitTests.cs └── NodeTests.cs ├── ListHelpers.cs ├── MatrixHelpers.cs ├── MeetingScheduler └── MeetingSchedulerTests.cs ├── Misc ├── CountingIslandsTests.cs ├── LeastRecentlyUsedCacheTests.cs ├── SubstringSearchTests.cs └── WordFrequenciesTests.cs ├── OverlappingParties └── OverlappingPartiesTests.cs ├── Properties └── AssemblyInfo.cs ├── TestHelpers.cs ├── Tests.csproj ├── TreeHelpers.cs └── packages.config /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | 32 | # NUNIT 33 | *.VisualState.xml 34 | TestResult.xml 35 | 36 | # Build Results of an ATL Project 37 | [Dd]ebugPS/ 38 | [Rr]eleasePS/ 39 | dlldata.c 40 | 41 | # DNX 42 | project.lock.json 43 | artifacts/ 44 | 45 | *_i.c 46 | *_p.c 47 | *_i.h 48 | *.ilk 49 | *.meta 50 | *.obj 51 | *.pch 52 | *.pdb 53 | *.pgc 54 | *.pgd 55 | *.rsp 56 | *.sbr 57 | *.tlb 58 | *.tli 59 | *.tlh 60 | *.tmp 61 | *.tmp_proj 62 | *.log 63 | *.vspscc 64 | *.vssscc 65 | .builds 66 | *.pidb 67 | *.svclog 68 | *.scc 69 | 70 | # Chutzpah Test files 71 | _Chutzpah* 72 | 73 | # Visual C++ cache files 74 | ipch/ 75 | *.aps 76 | *.ncb 77 | *.opensdf 78 | *.sdf 79 | *.cachefile 80 | 81 | # Visual Studio profiler 82 | *.psess 83 | *.vsp 84 | *.vspx 85 | 86 | # TFS 2012 Local Workspace 87 | $tf/ 88 | 89 | # Guidance Automation Toolkit 90 | *.gpState 91 | 92 | # ReSharper is a .NET coding add-in 93 | _ReSharper*/ 94 | *.[Rr]e[Ss]harper 95 | *.DotSettings.user 96 | 97 | # JustCode is a .NET coding add-in 98 | .JustCode 99 | 100 | # TeamCity is a build add-in 101 | _TeamCity* 102 | 103 | # DotCover is a Code Coverage Tool 104 | *.dotCover 105 | 106 | # NCrunch 107 | _NCrunch_* 108 | .*crunch*.local.xml 109 | 110 | # MightyMoose 111 | *.mm.* 112 | AutoTest.Net/ 113 | 114 | # Web workbench (sass) 115 | .sass-cache/ 116 | 117 | # Installshield output folder 118 | [Ee]xpress/ 119 | 120 | # DocProject is a documentation generator add-in 121 | DocProject/buildhelp/ 122 | DocProject/Help/*.HxT 123 | DocProject/Help/*.HxC 124 | DocProject/Help/*.hhc 125 | DocProject/Help/*.hhk 126 | DocProject/Help/*.hhp 127 | DocProject/Help/Html2 128 | DocProject/Help/html 129 | 130 | # Click-Once directory 131 | publish/ 132 | 133 | # Publish Web Output 134 | *.[Pp]ublish.xml 135 | *.azurePubxml 136 | ## TODO: Comment the next line if you want to checkin your 137 | ## web deploy settings but do note that will include unencrypted 138 | ## passwords 139 | #*.pubxml 140 | 141 | *.publishproj 142 | 143 | # NuGet Packages 144 | *.nupkg 145 | # The packages folder can be ignored because of Package Restore 146 | **/packages/* 147 | # except build/, which is used as an MSBuild target. 148 | !**/packages/build/ 149 | # Uncomment if necessary however generally it will be regenerated when needed 150 | #!**/packages/repositories.config 151 | 152 | # Windows Azure Build Output 153 | csx/ 154 | *.build.csdef 155 | 156 | # Windows Store app package directory 157 | AppPackages/ 158 | 159 | # Visual Studio cache files 160 | # files ending in .cache can be ignored 161 | *.[Cc]ache 162 | # but keep track of directories ending in .cache 163 | !*.[Cc]ache/ 164 | 165 | # Others 166 | ClientBin/ 167 | [Ss]tyle[Cc]op.* 168 | ~$* 169 | *~ 170 | *.dbmdl 171 | *.dbproj.schemaview 172 | *.pfx 173 | *.publishsettings 174 | node_modules/ 175 | orleans.codegen.cs 176 | 177 | # RIA/Silverlight projects 178 | Generated_Code/ 179 | 180 | # Backup & report files from converting an old project file 181 | # to a newer Visual Studio version. Backup files are not needed, 182 | # because we have git ;-) 183 | _UpgradeReport_Files/ 184 | Backup*/ 185 | UpgradeLog*.XML 186 | UpgradeLog*.htm 187 | 188 | # SQL Server files 189 | *.mdf 190 | *.ldf 191 | 192 | # Business Intelligence projects 193 | *.rdl.data 194 | *.bim.layout 195 | *.bim_*.settings 196 | 197 | # Microsoft Fakes 198 | FakesAssemblies/ 199 | 200 | # Node.js Tools for Visual Studio 201 | .ntvs_analysis.dat 202 | 203 | # Visual Studio 6 build log 204 | *.plg 205 | 206 | # Visual Studio 6 workspace options file 207 | *.opt 208 | 209 | # LightSwitch generated files 210 | GeneratedArtifacts/ 211 | _Pvt_Extensions/ 212 | ModelManifest.xml 213 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/AssemblyAttributes.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using System.Reflection; 4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6.1", FrameworkDisplayName = ".NET Framework 4.6.1")] 5 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 1/Question1_1.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Code 4 | { 5 | public static class Question1_1 6 | { 7 | // 1.1 Is Unique: Implement an algorithm to determine if a string has all unique characters. What if you cannot use additional data structures? 8 | 9 | // Space: O(N) 10 | // Time: O(N) 11 | public static bool AreAllCharactersUnique(string input) 12 | { 13 | if (string.IsNullOrEmpty(input)) 14 | { 15 | return true; 16 | } 17 | 18 | var charactersInString = new HashSet(); 19 | foreach (char c in input) 20 | { 21 | if (!charactersInString.Add(c)) 22 | { 23 | return false; 24 | } 25 | } 26 | 27 | return true; 28 | } 29 | 30 | // Space: O(1) 31 | // Time: O(N^2) 32 | public static bool AreAllCharactersUniqueNoAdditionalMemory(string input) 33 | { 34 | if (string.IsNullOrEmpty(input)) 35 | { 36 | return true; 37 | } 38 | 39 | for (int i = 0; i < input.Length - 1; i++) 40 | { 41 | for (int j = i + 1; j < input.Length; j++) 42 | { 43 | if (input[i] == input[j]) 44 | { 45 | return false; 46 | } 47 | } 48 | } 49 | 50 | return true; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 1/Question1_2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Code 6 | { 7 | public static class Question1_2 8 | { 9 | // 1.2 Check Permutation: Given two strings, write a method to decide if one is a permutation of the other. 10 | 11 | // Space: O(N) 12 | // Time: O(N log N) 13 | public static bool AreStringsPermutation(string string1, string string2) 14 | { 15 | if (string.IsNullOrEmpty(string1) || string.IsNullOrEmpty(string2)) 16 | { 17 | throw new ArgumentException("Input strings cannot be null or empty"); 18 | } 19 | 20 | if (string1.Length != string2.Length) 21 | { 22 | return false; 23 | } 24 | 25 | var sortedStr1 = string.Concat(string1.OrderBy(c => c)); 26 | var sortedStr2 = string.Concat(string2.OrderBy(c => c)); 27 | 28 | return sortedStr1.Equals(sortedStr2); 29 | } 30 | 31 | // Space: O(N) 32 | // Time: O(N) 33 | public static bool AreStringsPermutationNoSort(string string1, string string2) 34 | { 35 | if (string.IsNullOrEmpty(string1) || string.IsNullOrEmpty(string2)) 36 | { 37 | throw new ArgumentException("Input strings cannot be null or empty"); 38 | } 39 | 40 | if (string1.Length != string2.Length) 41 | { 42 | return false; 43 | } 44 | 45 | var allChars = new Dictionary(); 46 | 47 | for (int i = 0; i < string1.Length; i++) 48 | { 49 | var c = string1[i]; 50 | if (allChars.ContainsKey(c)) 51 | { 52 | allChars[c]++; 53 | } 54 | else 55 | { 56 | allChars[c] = 1; 57 | } 58 | } 59 | 60 | for (int i = 0; i < string2.Length; i++) 61 | { 62 | var c = string2[i]; 63 | int occurences = 0; 64 | if (!allChars.ContainsKey(c)) 65 | { 66 | return false; 67 | } 68 | else if (occurences == 1) 69 | { 70 | allChars.Remove(c); 71 | } 72 | else 73 | { 74 | allChars[c]--; 75 | } 76 | } 77 | 78 | return true; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 1/Question1_3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public static class Question1_3 6 | { 7 | // 1.3 URLify: Write a method to replace all spaces in a string with '%20'. You may assume that the string has sufficient space at the end of the string to hold the additional characters, and that you are given the "true" length of the string. (Note: if implementing in java, please use a character array so that you can perform this operation in place.) 8 | // EXAMPLE 9 | // Input: "Mr John Smith " 10 | // Output: "Mr%20John%20Smith" 11 | 12 | // Space: O(1) 13 | // Time: O(N) 14 | public static void ReplaceSpaces(char[] inputString, int length) 15 | { 16 | if (length < 0) 17 | { 18 | throw new ArgumentOutOfRangeException(nameof(length), "Value cannot be negative"); 19 | } 20 | 21 | if (inputString == null) 22 | { 23 | throw new ArgumentNullException(nameof(inputString), "Value cannot be null"); 24 | } 25 | 26 | int numSpaces = 0; 27 | 28 | for (int i = 0; i < length; i++) 29 | { 30 | if (inputString[i] == ' ') 31 | { 32 | numSpaces++; 33 | } 34 | } 35 | 36 | int offset = 2 * numSpaces; 37 | 38 | for (int i = length - 1; i >= 0; i--) 39 | { 40 | if (inputString[i] == ' ') 41 | { 42 | inputString[i + offset] = '0'; 43 | inputString[i + offset - 1] = '2'; 44 | inputString[i + offset - 2] = '%'; 45 | offset -= 2; 46 | } 47 | else 48 | { 49 | inputString[i + offset] = inputString[i]; 50 | } 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 1/Question1_4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Code 5 | { 6 | public static class Question1_4 7 | { 8 | // 1.4 Palindrome Permutation: Given a string, write a function to check if it is a permutation of a palindrome. A palindrome is a word or phrase that is the same forwards and backwards.A permutation is a rearrangement of letters.The palindrome does not need to be limited to just dictionary words. 9 | // EXAMPLE 10 | // Input: Tact Coa 11 | // Output: True (permutations: "taco cat", "atco cta", etc.) 12 | 13 | // Space: O(N) (where N is the number of unique characters in the string, not the length of the string) 14 | // Time: O(N) 15 | public static bool IsPalindromePermutation(string input) 16 | { 17 | if (string.IsNullOrEmpty(input)) 18 | { 19 | throw new ArgumentException("Input cannot be null/empty", nameof(input)); 20 | } 21 | 22 | var occurances = new Dictionary(); 23 | 24 | foreach (var c in input) 25 | { 26 | bool value; 27 | occurances.TryGetValue(c, out value); 28 | 29 | occurances[c] = !value; 30 | } 31 | 32 | bool hasOdd = false; 33 | foreach (var key in occurances.Keys) 34 | { 35 | if (occurances[key]) 36 | { 37 | if (hasOdd) 38 | { 39 | return false; 40 | } 41 | else 42 | { 43 | hasOdd = true; 44 | } 45 | } 46 | } 47 | 48 | return true; 49 | } 50 | 51 | // Space: O(1) 52 | // Time: O(N log N) 53 | public static bool IsPalindromePermutationNoAdditionalSpace(string input) 54 | { 55 | if (string.IsNullOrEmpty(input)) 56 | { 57 | throw new ArgumentException("Input cannot be null/empty", nameof(input)); 58 | } 59 | 60 | var inputArray = input.ToCharArray(); 61 | 62 | Array.Sort(inputArray); 63 | 64 | char prevChar = inputArray[0]; 65 | var count = 0; 66 | bool hasOdd = false; 67 | 68 | foreach (var c in inputArray) 69 | { 70 | if (c != prevChar) 71 | { 72 | if (count % 2 == 1) 73 | { 74 | if (hasOdd) 75 | { 76 | return false; 77 | } 78 | else 79 | { 80 | hasOdd = true; 81 | } 82 | } 83 | 84 | count = 1; 85 | prevChar = c; 86 | } 87 | else 88 | { 89 | count++; 90 | } 91 | } 92 | 93 | if (hasOdd && count % 2 == 1) 94 | { 95 | return false; 96 | } 97 | 98 | return true; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 1/Question1_5.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public static class Question1_5 6 | { 7 | // 1.5 One Away: There are three types of edits that can be performed on strings: insert a character, remove a character, or replace a character. Given two strings, write a function to check if they are one dit (or zero edits) away. 8 | // EXAMPLE 9 | // pale, ple -> true 10 | // pales, pale -> true 11 | // pale, bale -> true 12 | // pale, bake -> false 13 | 14 | // Space: O(1) 15 | // Time: O(N) 16 | public static bool IsOneAway(string string1, string string2) 17 | { 18 | if (string.IsNullOrEmpty(string1) || string.IsNullOrEmpty(string2)) 19 | { 20 | throw new ArgumentException("Input must not be null/empty"); 21 | } 22 | 23 | return string.Equals(string1, string2) 24 | || IsAddOrRemoveCharacter(string1, string2) 25 | || IsReplaceCharacter(string1, string2); 26 | } 27 | 28 | private static bool IsAddOrRemoveCharacter(string s1, string s2) 29 | { 30 | string longStr; 31 | string shortStr; 32 | 33 | if (s1.Length > s2.Length) 34 | { 35 | longStr = s1; 36 | shortStr = s2; 37 | } 38 | else 39 | { 40 | longStr = s2; 41 | shortStr = s1; 42 | } 43 | 44 | if (longStr.Length - shortStr.Length != 1) 45 | { 46 | return false; 47 | } 48 | 49 | bool foundMissing = false; 50 | int shortIndex = 0; 51 | int longIndex = 0; 52 | 53 | while (shortIndex < shortStr.Length) 54 | { 55 | if (shortStr[shortIndex] != longStr[longIndex]) 56 | { 57 | if (foundMissing) 58 | { 59 | return false; 60 | } 61 | else 62 | { 63 | foundMissing = true; 64 | longIndex++; 65 | } 66 | } 67 | else 68 | { 69 | shortIndex++; 70 | longIndex++; 71 | } 72 | } 73 | 74 | return true; 75 | } 76 | 77 | private static bool IsReplaceCharacter(string s1, string s2) 78 | { 79 | if (s1.Length != s2.Length) 80 | { 81 | return false; 82 | } 83 | 84 | bool foundReplacement = false; 85 | 86 | for (int i = 0; i < s1.Length; i++) 87 | { 88 | if (s1[i] != s2[i]) 89 | { 90 | if (foundReplacement) 91 | { 92 | return false; 93 | } 94 | else 95 | { 96 | foundReplacement = true; 97 | } 98 | } 99 | } 100 | 101 | return true; 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 1/Question1_6.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace Code 5 | { 6 | public static class Question1_6 7 | { 8 | // 1.6 String Compression: Implement a method to perform basic string compression using the counts of repeated characters. For example, the string aabcccccaaa would become a2b1c5a3. If the "compressed" string would not become smaller than the original string, your method should return the original string. 9 | // Space: O(N) 10 | // Time: O(N) 11 | public static string Compress(string inputString) 12 | { 13 | if (string.IsNullOrEmpty(inputString)) 14 | { 15 | throw new ArgumentException("Input cannot be null or empty", nameof(inputString)); 16 | } 17 | 18 | if (inputString.Length == 1) 19 | { 20 | return inputString; 21 | } 22 | 23 | var curChar = inputString[0]; 24 | var curCount = 1; 25 | var result = new StringBuilder(); 26 | 27 | for (int i = 1; i < inputString.Length; i++) 28 | { 29 | if (curChar == inputString[i]) 30 | { 31 | curCount++; 32 | } 33 | else 34 | { 35 | result.Append(curChar); 36 | result.Append(curCount); 37 | curChar = inputString[i]; 38 | curCount = 1; 39 | } 40 | } 41 | 42 | result.Append(curChar); 43 | result.Append(curCount); 44 | 45 | var resultString = result.ToString(); 46 | 47 | return resultString.Length < inputString.Length 48 | ? resultString 49 | : inputString; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 1/Question1_7.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public static class Question1_7 6 | { 7 | // 1.7 Rotate Matrix: Given an image represented by an NxN matrix, where each pixel in the image is 4 bytes, write a method to rotate the image by 90 degrees. Can you do this in place? 8 | 9 | // Space: O(N^2) 10 | // Time: O(N^2) 11 | public static int[,] RotateMatrix(int[,] matrix) 12 | { 13 | if (matrix == null) 14 | { 15 | throw new ArgumentNullException(nameof(matrix)); 16 | } 17 | 18 | if (matrix.GetLength(0) != matrix.GetLength(1)) 19 | { 20 | throw new ArgumentException("Matrix needs to be square", nameof(matrix)); 21 | } 22 | 23 | var size = matrix.GetLength(0); 24 | var result = new int[size, size]; 25 | 26 | for (int row = 0; row < size; row++) 27 | { 28 | for (int col = 0; col < size; col++) 29 | { 30 | result[col, size - 1 - row] = matrix[row, col]; 31 | } 32 | } 33 | 34 | return result; 35 | } 36 | 37 | // Space: O(1) 38 | // Time: O(N^2) 39 | public static void RotateMatrixInPlace(int[,] matrix) 40 | { 41 | if (matrix == null) 42 | { 43 | throw new ArgumentNullException(nameof(matrix)); 44 | } 45 | 46 | if (matrix.GetLength(0) != matrix.GetLength(1)) 47 | { 48 | throw new ArgumentException("Matrix needs to be square", nameof(matrix)); 49 | } 50 | 51 | var size = matrix.GetLength(0); 52 | var offset = 0; 53 | 54 | while (size > 1) 55 | { 56 | for (int i = 0; i < size - 1; i++) 57 | { 58 | var orig = matrix[offset, i + offset]; 59 | 60 | // Top left 61 | matrix[offset, i + offset] = matrix[size - 1 - i + offset, offset]; 62 | 63 | // Bottom left 64 | matrix[size - 1 - i + offset, offset] = matrix[size - 1 + offset, size - 1 - i + offset]; 65 | 66 | // Bottom right 67 | matrix[size - 1 + offset, size - 1 - i + offset] = matrix[i + offset, size - 1 + offset]; 68 | 69 | // Top right 70 | matrix[i + offset, size - 1 + offset] = orig; 71 | } 72 | 73 | size -= 2; 74 | offset++; 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 1/Question1_8.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public static class Question1_8 6 | { 7 | // 1.8 Zero Matrix: Write an algorithm such that if an element in an MxN matrix is 0, its entire row and column are set to 0. 8 | 9 | // Space: O(N + M) 10 | // Time: O(N * M) 11 | public static void ZeroMatrix(int[,] matrix) 12 | { 13 | if (matrix == null) 14 | { 15 | throw new ArgumentNullException(nameof(matrix)); 16 | } 17 | 18 | var rowLength = matrix.GetLength(0); 19 | var colLength = matrix.GetLength(1); 20 | 21 | var zerosInRow = new bool[rowLength]; 22 | var zerosInCol = new bool[colLength]; 23 | 24 | for (int i = 0; i < rowLength; i++) 25 | { 26 | for (int j = 0; j < colLength; j++) 27 | { 28 | zerosInRow[i] |= matrix[i, j] == 0; 29 | zerosInCol[j] |= matrix[i, j] == 0; 30 | } 31 | } 32 | 33 | for (int i = 0; i < rowLength; i++) 34 | { 35 | for (int j = 0; j < colLength; j++) 36 | { 37 | if (zerosInRow[i] || zerosInCol[j]) 38 | { 39 | matrix[i, j] = 0; 40 | } 41 | } 42 | } 43 | } 44 | 45 | // Space: O(1) 46 | // Time: O(N * M) 47 | public static void ZeroMatrixNoAdditionalSpace(int[,] matrix) 48 | { 49 | // Find out if there's a zero in the first row/column 50 | // Use the first row/column to store the values instead of the additional arrays created above 51 | // Zero the matrix where needed 52 | if (matrix == null) 53 | { 54 | throw new ArgumentNullException(nameof(matrix)); 55 | } 56 | 57 | var rowLength = matrix.GetLength(0); 58 | var colLength = matrix.GetLength(1); 59 | 60 | bool zeroInFirstRow = false; 61 | 62 | for (int i = 0; i < colLength; i++) 63 | { 64 | zeroInFirstRow |= matrix[0, i] == 0; 65 | } 66 | 67 | bool zeroInFirstCol = false; 68 | 69 | for (int i = 0; i < rowLength; i++) 70 | { 71 | zeroInFirstCol |= matrix[i, 0] == 0; 72 | } 73 | 74 | for (int i = 0; i < rowLength; i++) 75 | { 76 | for (int j = 0; j < colLength; j++) 77 | { 78 | if (matrix[i, j] == 0) 79 | { 80 | matrix[i, 0] = 0; 81 | matrix[0, j] = 0; 82 | } 83 | } 84 | } 85 | 86 | for (int i = 1; i < rowLength; i++) 87 | { 88 | for (int j = 1; j < colLength; j++) 89 | { 90 | if (matrix[i, 0] == 0 || matrix[0, j] == 0) 91 | { 92 | matrix[i, j] = 0; 93 | } 94 | } 95 | } 96 | 97 | if (zeroInFirstRow) 98 | { 99 | for (int i = 0; i < colLength; i++) 100 | { 101 | matrix[0, i] = 0; 102 | } 103 | } 104 | 105 | if (zeroInFirstCol) 106 | { 107 | for (int i = 0; i < rowLength; i++) 108 | { 109 | matrix[i, 0] = 0; 110 | } 111 | } 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 1/Question1_9.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public static class Question1_9 6 | { 7 | // 1.9 String Rotation: Assume you have a method isSubstring which checks if one word is a substring of another. Given two strings, s1 and s2, write code to check if s2 is a rotation of s1 using only one call to isSubstring (e.g.,"waterbottle" is a rotation of "erbottlewat"). 8 | 9 | // Space: O(N) 10 | // Time: O(N) 11 | public static bool IsRotation(string string1, string string2) 12 | { 13 | if (string.IsNullOrEmpty(string1) || string.IsNullOrEmpty(string2)) 14 | { 15 | throw new ArgumentException("Input cannot be null or empty"); 16 | } 17 | 18 | if (string1.Length != string2.Length) 19 | { 20 | return false; 21 | } 22 | 23 | var doubledS1 = string1 + string1; 24 | 25 | return doubledS1.Contains(string2); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 16/Question16_1.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace Code 4 | { 5 | public static class Question16_1 6 | { 7 | // 16.1 Number Swapper: Write a function to swap a number in place (that is, without 8 | // temporary variables). 9 | 10 | // Space: O(1) 11 | // Time: O(1) 12 | [SuppressMessage("Microsoft.Design", "CA1045")] 13 | public static void SwapNumbers(ref int first, ref int second) 14 | { 15 | // first = first ^ second 16 | first ^= second; 17 | 18 | // second = second ^ first 19 | // = second ^ (first ^ second) 20 | // = first 21 | second ^= first; 22 | 23 | // first = first ^ second 24 | // = (first ^ second) ^ (first) 25 | // = second 26 | first ^= second; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 16/Question16_2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Code 5 | { 6 | public static class Question16_2 7 | { 8 | private static Dictionary _words; 9 | 10 | // 16.2 Word Frequencies: Design a method to find the frequency of occurances of any 11 | // given word in a book. What if we were running this algorithm multiple times? 12 | 13 | // Space: O(1) 14 | // Time: O(N) 15 | public static int WordFrequency(IEnumerable book, string targetWord) 16 | { 17 | book = book ?? throw new ArgumentNullException(nameof(book)); 18 | targetWord = targetWord ?? throw new ArgumentNullException(nameof(targetWord)); 19 | 20 | var result = 0; 21 | 22 | foreach (var word in book) 23 | { 24 | // This treats different cases as different words 25 | if (word == targetWord) 26 | { 27 | result++; 28 | } 29 | } 30 | 31 | return result; 32 | } 33 | 34 | // Space: O(UW) where UW is the number of unique words 35 | // Time: O(W) where W is the number of words 36 | public static void PreprocessBook(IEnumerable book) 37 | { 38 | book = book ?? throw new ArgumentNullException(nameof(book)); 39 | 40 | _words = new Dictionary(); 41 | 42 | foreach (var word in book) 43 | { 44 | // Thsi treats different cases as different words 45 | if (!_words.ContainsKey(word)) 46 | { 47 | _words[word] = 0; 48 | } 49 | 50 | _words[word]++; 51 | } 52 | } 53 | 54 | // This implemention does not support concurrency because of the Dictionary that isn't concurrent and is static 55 | // Space: O(1) 56 | // Time: O(1) 57 | public static int WordFrequencyPreprocessed(string word) 58 | { 59 | word = word ?? throw new ArgumentNullException(nameof(word)); 60 | _words = _words ?? throw new InvalidOperationException("The preprocess book method must be called first"); 61 | 62 | if (_words.ContainsKey(word)) 63 | { 64 | return _words[word]; 65 | } 66 | 67 | return 0; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 16/Question16_4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public static class Question16_4 6 | { 7 | // 16.4 Tic Tac Win: Design an algorithm to figure out if someone has won a game 8 | // of tic-tac-toe. 9 | 10 | // Space: O(1) 11 | // Time: O(N^2) where N is the size of one dimension of the board 12 | public static bool HasWinner(int?[,] board) 13 | { 14 | board = board ?? throw new ArgumentNullException(nameof(board)); 15 | 16 | const int numDimensions = 3; 17 | 18 | // Check horizontal 19 | for (int i = 0; i < numDimensions; i++) 20 | { 21 | if (!board[0, i].HasValue) 22 | { 23 | continue; 24 | } 25 | 26 | var value = board[0, i]; 27 | bool hasWinner = true; 28 | 29 | for (int j = 1; j < numDimensions; j++) 30 | { 31 | if (board[j, i] != value) 32 | { 33 | hasWinner = false; 34 | break; 35 | } 36 | } 37 | 38 | if (hasWinner) 39 | { 40 | return true; 41 | } 42 | } 43 | 44 | // Check vertical 45 | for (int i = 0; i < numDimensions; i++) 46 | { 47 | if (!board[i, 0].HasValue) 48 | { 49 | continue; 50 | } 51 | 52 | var value = board[i, 0]; 53 | bool hasWinner = true; 54 | 55 | for (int j = 1; j < numDimensions; j++) 56 | { 57 | if (board[i, j] != value) 58 | { 59 | hasWinner = false; 60 | break; 61 | } 62 | } 63 | 64 | if (hasWinner) 65 | { 66 | return true; 67 | } 68 | } 69 | 70 | // Check diagonal top left to bottom right 71 | if (board[0, 0].HasValue) 72 | { 73 | var value = board[0, 0]; 74 | var hasWinner = true; 75 | 76 | for (int i = 1; i < numDimensions; i++) 77 | { 78 | if (board[i, i] != value) 79 | { 80 | hasWinner = false; 81 | break; 82 | } 83 | } 84 | 85 | if (hasWinner) 86 | { 87 | return true; 88 | } 89 | } 90 | 91 | // Check diagonal top right to bottom left 92 | if (board[numDimensions - 1, 0].HasValue) 93 | { 94 | var value = board[numDimensions - 1, 0]; 95 | var hasWinner = true; 96 | 97 | for (int i = 1; i < numDimensions; i++) 98 | { 99 | if (board[numDimensions - 1 - i, i] != value) 100 | { 101 | hasWinner = false; 102 | break; 103 | } 104 | } 105 | 106 | if (hasWinner) 107 | { 108 | return true; 109 | } 110 | } 111 | 112 | return false; 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 2/Question2_1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Code 5 | { 6 | public static class Question2_1 7 | { 8 | // 2.1 Remove Dups: Write code to remove duplicates from an unsorted linked list. FOLLOW UP How would you solve this problem if a temporary buffer is not allowed? 9 | 10 | // Space: O(N) 11 | // Time: O(N) 12 | public static void RemoveDuplicates(Node head) 13 | where T : IEquatable 14 | { 15 | if (head == null) 16 | { 17 | throw new ArgumentNullException(nameof(head)); 18 | } 19 | 20 | var nodes = new HashSet(); 21 | nodes.Add(head.Data); 22 | 23 | while (head.Next != null) 24 | { 25 | if (nodes.Add(head.Next.Data)) 26 | { 27 | head = head.Next; 28 | } 29 | else 30 | { 31 | head.Next = head.Next.Next; 32 | } 33 | } 34 | } 35 | 36 | // Space: O(1) 37 | // Time: O(N^2) 38 | public static void RemoveDuplicatesNoSpace(Node head) 39 | where T : IEquatable 40 | { 41 | if (head == null) 42 | { 43 | throw new ArgumentNullException(nameof(head)); 44 | } 45 | 46 | while (head != null) 47 | { 48 | var prev = head; 49 | var next = head.Next; 50 | while (next != null) 51 | { 52 | if (next.Data.Equals(head.Data)) 53 | { 54 | prev.Next = next.Next; 55 | next = next.Next; 56 | } 57 | else 58 | { 59 | prev = next; 60 | next = next.Next; 61 | } 62 | } 63 | 64 | head = head.Next; 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 2/Question2_2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace Code 5 | { 6 | public static class Question2_2 7 | { 8 | // 2.2 Return Kth to Last: Implement an algorithm to find the kth to last element of a singly linked list. 9 | 10 | // Space: O(1) 11 | // Time: O(N) 12 | [SuppressMessage("Microsoft.Naming", "CA1704")] 13 | public static Node FindKthToLast(Node head, int k) 14 | where T : IEquatable 15 | { 16 | if (head == null) 17 | { 18 | throw new ArgumentNullException(nameof(head)); 19 | } 20 | 21 | if (k < 0) 22 | { 23 | throw new ArgumentOutOfRangeException(nameof(k), "Value must be greater than or equal to zero"); 24 | } 25 | 26 | var result = head; 27 | 28 | for (int i = 0; i < k; i++) 29 | { 30 | head = head.Next; 31 | 32 | if (head == null) 33 | { 34 | throw new ArgumentOutOfRangeException(nameof(k), "There must be at least k elements in the list"); 35 | } 36 | } 37 | 38 | while (head.Next != null) 39 | { 40 | head = head.Next; 41 | result = result.Next; 42 | } 43 | 44 | return result; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 2/Question2_3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public static class Question2_3 6 | { 7 | // 2.3 Delete Middle Node: Implement an algorithm to delete a node in the middle of a singly linked list, given only access to that node. 8 | // EXAMPLE 9 | // Input: the node c from the linked list a->b->c->d->e 10 | // Result: nothing is returned, but the new linked list looks like a->b->d->e 11 | 12 | // Space: O(1) 13 | // Time: O(1) 14 | // NOTE: this algorithm will not work if the element to be removed is the last one in the list 15 | public static void RemoveNode(Node node) 16 | where T : IEquatable 17 | { 18 | if (node == null || node.Next == null) 19 | { 20 | throw new ArgumentException("Node cannot be null/last element in list"); 21 | } 22 | 23 | node.Data = node.Next.Data; 24 | node.Next = node.Next.Next; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 2/Question2_4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace Code 5 | { 6 | public static class Question2_4 7 | { 8 | // 2.4 Partition: Write code to parition a linked list around a value x, such that all nodes less than x come before all nodes greater than or equal to x. 9 | 10 | // Space: O(1) 11 | // Time: O(N) 12 | // This solution is stable meaning that items less than and greater than/equal to x keep their relative order 13 | [SuppressMessage("Microsoft.Naming", "CA1704")] 14 | public static Node PartitionList(Node head, T x) 15 | where T : IEquatable, IComparable 16 | { 17 | if (head == null) 18 | { 19 | throw new ArgumentNullException(nameof(head)); 20 | } 21 | 22 | Node smallerHead = null; 23 | Node smallerLast = null; 24 | Node biggerHead = null; 25 | Node biggerLast = null; 26 | 27 | while (head != null) 28 | { 29 | var nodeToAdd = new Node(head.Data); 30 | 31 | if (head.Data.CompareTo(x) < 0) 32 | { 33 | if (smallerLast == null) 34 | { 35 | smallerHead = nodeToAdd; 36 | smallerLast = nodeToAdd; 37 | } 38 | else 39 | { 40 | smallerLast.Next = nodeToAdd; 41 | smallerLast = nodeToAdd; 42 | } 43 | } 44 | else 45 | { 46 | if (biggerLast == null) 47 | { 48 | biggerHead = nodeToAdd; 49 | biggerLast = nodeToAdd; 50 | } 51 | else 52 | { 53 | biggerLast.Next = nodeToAdd; 54 | biggerLast = nodeToAdd; 55 | } 56 | } 57 | 58 | head = head.Next; 59 | } 60 | 61 | if (smallerHead == null) 62 | { 63 | return biggerHead; 64 | } 65 | else 66 | { 67 | smallerLast.Next = biggerHead; 68 | return smallerHead; 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 2/Question2_5.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public static class Question2_5 6 | { 7 | // 2.5. Sum Lists: You have two numbers represented by a linked list, where each node contains a single digit.The digits are stored in reverse order, such that the 1's digit is at the head of the list. Write a function that adds the two numbers and returns the sum as a linked list. 8 | // EXAMPLE 9 | // Input: (7 -> 1 -> 6) + (5 -> 9 -> 2). that is, 617 + 295. 10 | // Output: 2 -> 1 -> 9. That is, 912. 11 | // FOLLOW UP 12 | // Suppose the digits are stored in forward order.Repeat the above problem. 13 | // EXAMPLE 14 | // Input: (6 -> 1 -> 7) + (2 -> 9 -> 5). That is 617 + 295. 15 | // Output: 9 -> 1 -> 2. That is, 912. 16 | 17 | // Space: O(N) 18 | // Time: O(N) 19 | public static Node Add(Node firstNumber, Node secondNumber) 20 | { 21 | if (firstNumber == null) 22 | { 23 | throw new ArgumentNullException(nameof(firstNumber)); 24 | } 25 | 26 | if (secondNumber == null) 27 | { 28 | throw new ArgumentNullException(nameof(secondNumber)); 29 | } 30 | 31 | Node result = null; 32 | Node resultTail = null; 33 | bool carryOver = false; 34 | 35 | while (firstNumber != null || secondNumber != null || carryOver) 36 | { 37 | int value = firstNumber?.Data + secondNumber?.Data + (carryOver ? 1 : 0); 38 | 39 | if (value >= 10) 40 | { 41 | carryOver = true; 42 | value -= 10; 43 | } 44 | else 45 | { 46 | carryOver = false; 47 | } 48 | 49 | if (result == null) 50 | { 51 | result = new Node(new Digit(value)); 52 | resultTail = result; 53 | } 54 | else 55 | { 56 | resultTail.Next = new Node(new Digit(value)); 57 | resultTail = resultTail.Next; 58 | } 59 | 60 | firstNumber = firstNumber?.Next; 61 | secondNumber = secondNumber?.Next; 62 | } 63 | 64 | return result; 65 | } 66 | 67 | // Space: O(N) 68 | // Time: O(N) 69 | public static Node AddNotReversed(Node firstNumber, Node secondNumber) 70 | { 71 | firstNumber = ReverseList(firstNumber); 72 | secondNumber = ReverseList(secondNumber); 73 | 74 | var result = Add(firstNumber, secondNumber); 75 | return ReverseList(result); 76 | } 77 | 78 | private static Node ReverseList(Node head) 79 | where T : IEquatable 80 | { 81 | if (head == null) 82 | { 83 | throw new ArgumentNullException(nameof(head)); 84 | } 85 | 86 | Node prev = null; 87 | Node cur = head; 88 | 89 | while (cur != null) 90 | { 91 | var tmp = cur.Next; 92 | cur.Next = prev; 93 | prev = cur; 94 | cur = tmp; 95 | } 96 | 97 | return prev; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 2/Question2_6.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public static class Question2_6 6 | { 7 | // 2.6 Palindrome: Implement a funciton to check if a linked lits is a palindrome. 8 | 9 | // Space: O(N) 10 | // Time: O(N) 11 | public static bool IsPalindrome(Node head) 12 | where T : IEquatable 13 | { 14 | if (head == null) 15 | { 16 | throw new ArgumentNullException(nameof(head)); 17 | } 18 | 19 | var reverse = ReverseAndClone(head); 20 | 21 | while (head != null && reverse != null) 22 | { 23 | if (!head.Data.Equals(reverse.Data)) 24 | { 25 | return false; 26 | } 27 | 28 | head = head.Next; 29 | reverse = reverse.Next; 30 | } 31 | 32 | return head == null && reverse == null; 33 | } 34 | 35 | private static Node ReverseAndClone(Node head) 36 | where T : IEquatable 37 | { 38 | if (head == null) 39 | { 40 | throw new ArgumentNullException(nameof(head)); 41 | } 42 | 43 | Node next = null; 44 | 45 | while (head != null) 46 | { 47 | var tmp = new Node(head.Data); 48 | tmp.Next = next; 49 | next = tmp; 50 | 51 | head = head.Next; 52 | } 53 | 54 | return next; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 2/Question2_7.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public static class Question2_7 6 | { 7 | // 2.7 Intersection: Given two (singly) linked lists, determine if the two lists intersect. Return th eintersection node. Node that the intersection is defined based on reference, not value. That is if the kth node of the first linked list is exactly the same node (by reference) as the jth node of the second linked list, then they are intersecting. 8 | 9 | // Space: O(1) 10 | // Time: O(N) 11 | public static Node FindIntersection(Node list1, Node list2) 12 | where T : IEquatable 13 | { 14 | if (list1 == null) 15 | { 16 | throw new ArgumentNullException(nameof(list1)); 17 | } 18 | 19 | if (list2 == null) 20 | { 21 | throw new ArgumentNullException(nameof(list2)); 22 | } 23 | 24 | var list1Length = GetLength(list1); 25 | var list2Length = GetLength(list2); 26 | 27 | if (list1Length > list2Length) 28 | { 29 | for (int i = 0; i < list1Length - list2Length; i++) 30 | { 31 | list1 = list1.Next; 32 | } 33 | } 34 | else 35 | { 36 | for (int i = 0; i < list2Length - list1Length; i++) 37 | { 38 | list2 = list2.Next; 39 | } 40 | } 41 | 42 | while (list1 != null) 43 | { 44 | if (ReferenceEquals(list1, list2)) 45 | { 46 | return list1; 47 | } 48 | 49 | list1 = list1.Next; 50 | list2 = list2.Next; 51 | } 52 | 53 | // If not finding an intersection is a valid case then it makes sense to return null here, 54 | // otherwise if we always expected an intersection, it would make more sense to throw an exception. 55 | return null; 56 | } 57 | 58 | private static int GetLength(Node head) 59 | where T : IEquatable 60 | { 61 | if (head == null) 62 | { 63 | throw new ArgumentNullException(nameof(head)); 64 | } 65 | 66 | int length = 0; 67 | 68 | while (head != null) 69 | { 70 | length++; 71 | head = head.Next; 72 | } 73 | 74 | return length; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 2/Question2_8.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Code 5 | { 6 | public static class Question2_8 7 | { 8 | // 2.8 Loop Detection: Given a circular linked list, implement an algorithm that returns the node at the beginning of the loop. 9 | // DEFINITION 10 | // Circular linked list: A(corrupt) linked list in which a node's next pointer points to an earlier node, so as to make a loop in the linked list. 11 | // EXAMPLE 12 | // Input: A -> B -> C -> D -> E -> C[the same C as earlier] 13 | // Output: C 14 | 15 | // Space: O(N) 16 | // Time: O(N) 17 | public static Node FindLoopStart(Node head) 18 | where T : IEquatable 19 | { 20 | if (head == null) 21 | { 22 | throw new ArgumentNullException(nameof(head)); 23 | } 24 | 25 | var set = new HashSet>(new ReferenceComparer>()); 26 | 27 | while (head != null && set.Add(head)) 28 | { 29 | head = head.Next; 30 | } 31 | 32 | return head; 33 | } 34 | 35 | // Loop detection using the Hare Tortoise approach (no additional memory). 36 | 37 | // Space: O(1) 38 | // Time: O(N) 39 | public static Node FindLoopStartHareTortoise(Node head) 40 | where T : IEquatable 41 | { 42 | if (head == null) 43 | { 44 | throw new ArgumentNullException(nameof(head)); 45 | } 46 | 47 | Node tortoise = head; 48 | Node hare = head; 49 | 50 | // Detect cycle (tortoise and hare approach) 51 | while (hare?.Next != null) 52 | { 53 | tortoise = tortoise.Next; 54 | hare = hare.Next.Next; 55 | 56 | if (ReferenceEquals(tortoise, hare)) 57 | { 58 | break; // Cycle detected 59 | } 60 | } 61 | 62 | // No cycle if hare reached the end 63 | if (hare?.Next == null) 64 | { 65 | return null; 66 | } 67 | 68 | // Move tortoise to the head and advance both pointers at the same speed 69 | tortoise = head; 70 | while (!ReferenceEquals(tortoise, hare)) 71 | { 72 | tortoise = tortoise.Next; 73 | hare = hare.Next; 74 | } 75 | 76 | return tortoise; // Starting node of the loop 77 | } 78 | 79 | private class ReferenceComparer : IEqualityComparer 80 | { 81 | public bool Equals(T x, T y) 82 | { 83 | return ReferenceEquals(x, y); 84 | } 85 | 86 | public int GetHashCode(T obj) 87 | { 88 | return obj.GetHashCode(); 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 3/Question3_2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace Code 5 | { 6 | // 3.2 Stack Min: How would you design a stack which, in addition to push and pop, has a function min which returns the minimum element? 7 | // Push, pop, and min should all operate in O(1) time. 8 | [SuppressMessage("Documentation Rules", "SA1649")] 9 | [SuppressMessage("Microsoft.Naming", "CA1711")] 10 | public class MinStack 11 | where T : IComparable 12 | { 13 | // NOTE: a better implemention would grow the size dynamically when more space was needed 14 | private const int MaxSize = 100; 15 | 16 | private readonly T[] _stackValues; 17 | private readonly T[] _minValues; 18 | 19 | private int _numItems; 20 | 21 | public MinStack() 22 | { 23 | _stackValues = new T[MaxSize]; 24 | _minValues = new T[MaxSize]; 25 | } 26 | 27 | // Space: O(1) 28 | // Time: O(1) 29 | public T Pop() 30 | { 31 | if (_numItems == 0) 32 | { 33 | throw new InvalidOperationException("Stack does not contain any elements"); 34 | } 35 | 36 | var result = _stackValues[_numItems - 1]; 37 | _numItems--; 38 | 39 | return result; 40 | } 41 | 42 | // Space: O(1) 43 | // Time: O(1) 44 | public void Push(T item) 45 | { 46 | if (_numItems == MaxSize) 47 | { 48 | throw new InvalidOperationException("No more space in the stack"); 49 | } 50 | 51 | _stackValues[_numItems] = item; 52 | 53 | var curMin = _numItems == 0 54 | ? item 55 | : _minValues[_numItems - 1]; 56 | 57 | _minValues[_numItems] = item.CompareTo(curMin) < 0 58 | ? item 59 | : curMin; 60 | 61 | _numItems++; 62 | } 63 | 64 | // Space: O(1) 65 | // Time: O(1) 66 | public T Min() 67 | { 68 | if (_numItems == 0) 69 | { 70 | throw new InvalidOperationException("Stack does not contain any elements"); 71 | } 72 | 73 | return _minValues[_numItems - 1]; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 3/Question3_3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | 5 | namespace Code 6 | { 7 | // 3.3 Stack of Plates: Imagine a (literal) stack of plates. If the stack gets too high, it might topple. Therefore, in real life, 8 | // we would likely start a new stack when the previous stack exceeds some threshold. Implement a data structure SetOfStacks that mimics 9 | // this. SetOfStacks should be composed of several stacks and should create a new stack once the previous one exceeds capacity. 10 | // SetOfStacks.push() and SetOfStacks.pop() should behave identically to a single stack (that is, pop() should return the same values as 11 | // it would if there were just a single stack). 12 | // FOLLOW UP 13 | // Implement a function popAt(int index) which performans a pop operation on a specific sub-stack. 14 | [SuppressMessage("Documentation Rules", "SA1649")] 15 | public class SetOfStacks 16 | { 17 | // Small value for testing purposes 18 | private const int MaxSizePerStack = 2; 19 | 20 | private readonly List _setOfStacks; 21 | private int _numItems; 22 | 23 | public SetOfStacks() 24 | { 25 | _setOfStacks = new List(); 26 | } 27 | 28 | // Space: O(N) where N is the size of a sub-stack 29 | // Time: O(1) 30 | public void Push(T item) 31 | { 32 | if (_numItems % MaxSizePerStack == 0) 33 | { 34 | // have to create a new stack 35 | _setOfStacks.Add(new T[MaxSizePerStack]); 36 | } 37 | 38 | var stackNumber = _numItems / MaxSizePerStack; 39 | var itemNumber = _numItems % MaxSizePerStack; 40 | 41 | _setOfStacks[stackNumber][itemNumber] = item; 42 | 43 | _numItems++; 44 | } 45 | 46 | // Space: O(1) 47 | // Time: O(1) 48 | public T Pop() 49 | { 50 | if (_numItems == 0) 51 | { 52 | throw new InvalidOperationException("Stack is empty"); 53 | } 54 | 55 | _numItems--; 56 | var stackNumber = _numItems / MaxSizePerStack; 57 | var itemNumber = _numItems % MaxSizePerStack; 58 | 59 | var result = _setOfStacks[stackNumber][itemNumber]; 60 | 61 | if (itemNumber == 0) 62 | { 63 | _setOfStacks.RemoveAt(stackNumber); 64 | } 65 | 66 | return result; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 3/Question3_4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | 5 | namespace Code 6 | { 7 | // 3.4 Queue via Stacks: Implement a MyQueue class which implements a queue using two stacks. 8 | [SuppressMessage("Documentation Rules", "SA1649")] 9 | [SuppressMessage("Microsoft.Naming", "CA1711")] 10 | public class MyQueue 11 | { 12 | private readonly Stack _stackStack; 13 | private readonly Stack _queueStack; 14 | private bool _isQueue; 15 | private int _numItems; 16 | 17 | public MyQueue() 18 | { 19 | _stackStack = new Stack(); 20 | _queueStack = new Stack(); 21 | } 22 | 23 | // Space: 0(1) 24 | // Time: O(N) when the previous operation was a remove 25 | public void Add(T item) 26 | { 27 | if (_isQueue) 28 | { 29 | _isQueue = false; 30 | while (_queueStack.Count != 0) 31 | { 32 | _stackStack.Push(_queueStack.Pop()); 33 | } 34 | 35 | _stackStack.Push(item); 36 | } 37 | else 38 | { 39 | _stackStack.Push(item); 40 | } 41 | 42 | _numItems++; 43 | } 44 | 45 | // Space: O(1) 46 | // Time: O(N) when the previous operation was an add 47 | public T Remove() 48 | { 49 | if (_numItems == 0) 50 | { 51 | throw new InvalidOperationException("No items in the queue"); 52 | } 53 | 54 | _numItems--; 55 | 56 | if (_isQueue) 57 | { 58 | return _queueStack.Pop(); 59 | } 60 | else 61 | { 62 | _isQueue = true; 63 | while (_stackStack.Count != 0) 64 | { 65 | _queueStack.Push(_stackStack.Pop()); 66 | } 67 | 68 | return _queueStack.Pop(); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 3/Question3_5.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Code 5 | { 6 | // 3.5 Sort Stack: Write a program to sort a stack such that the smallest items are on the top. You can use an 7 | // additional temporary stack, but you may not copy the elements into any other data structure (such as an array). 8 | // The stack supports the following operations: push, pop, peek, and isEmpty. 9 | public static class Question3_5 10 | { 11 | // Time: O(N) 12 | // Space: O(N) 13 | public static void SortStack(Stack stack) 14 | where T : IComparable 15 | { 16 | if (stack == null) 17 | { 18 | throw new ArgumentNullException(nameof(stack)); 19 | } 20 | 21 | var tmp = new Stack(); 22 | 23 | while (stack.Count != 0) 24 | { 25 | var item = stack.Pop(); 26 | 27 | while (tmp.Count != 0 && item.CompareTo(tmp.Peek()) < 0) 28 | { 29 | stack.Push(tmp.Pop()); 30 | } 31 | 32 | tmp.Push(item); 33 | } 34 | 35 | while (tmp.Count != 0) 36 | { 37 | stack.Push(tmp.Pop()); 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 3/Question3_6.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Diagnostics.CodeAnalysis; 5 | 6 | namespace Code 7 | { 8 | // 3.6 Animal Shelter: An animal shelter, which holds only dogs and cats, operates on a strictly "first in, first out" basis. People must 9 | // adopt either the "oldest" (based on arrival time) of all animals at the shelter, or they can select whether they would prefer a dog or a 10 | // cat (and will receive the oldest animal of that type). They cannot select which specific animal they would like. Create the data structures 11 | // to maintain this system and implement operations such as enqueue, dequeueAny, dequeueDog, and dequeueCat. You may use the built-in LinkedList 12 | // data structure. 13 | 14 | // For all methods: 15 | // Space: O(N) where N is the number of animals in the shelter 16 | // Time: O(1) 17 | [SuppressMessage("Documentation Rules", "SA1649")] 18 | public class AnimalShelter 19 | { 20 | private readonly LinkedList _cats; 21 | private readonly LinkedList _dogs; 22 | 23 | public AnimalShelter() 24 | { 25 | _cats = new LinkedList(); 26 | _dogs = new LinkedList(); 27 | } 28 | 29 | public void Enqueue(Animal animal) 30 | { 31 | var cat = animal as Cat; 32 | var dog = animal as Dog; 33 | 34 | if (cat != null) 35 | { 36 | _cats.AddLast(cat); 37 | } 38 | else if (dog != null) 39 | { 40 | _dogs.AddLast(dog); 41 | } 42 | else 43 | { 44 | throw new InvalidOperationException("The shelter does not accept this type of animal"); 45 | } 46 | } 47 | 48 | public Animal DequeueAny() 49 | { 50 | if (_cats.Count == 0 && _dogs.Count == 0) 51 | { 52 | throw new InvalidOperationException("There are no animals in the shelter"); 53 | } 54 | 55 | var catEnqueueTime = _cats?.First?.Value?.ArrivalTime ?? DateTimeOffset.MaxValue; 56 | var dogEnqueueTime = _dogs?.First?.Value?.ArrivalTime ?? DateTimeOffset.MaxValue; 57 | 58 | // NOTE: this will favor a dog in the event that two animals were enqueued exactly at the same time although I doubt LinkedList is 59 | // thread safe, so if we wanted to support that scenario, we'd have to use a thread safe class or add locks around the accesses. 60 | if (catEnqueueTime < dogEnqueueTime) 61 | { 62 | return DequeueCat(); 63 | } 64 | else 65 | { 66 | return DequeueDog(); 67 | } 68 | } 69 | 70 | public Cat DequeueCat() 71 | { 72 | if (_cats.Count == 0) 73 | { 74 | throw new InvalidOperationException("There are no cats in the shelter"); 75 | } 76 | 77 | var result = _cats.First.Value; 78 | _cats.RemoveFirst(); 79 | 80 | return result; 81 | } 82 | 83 | public Dog DequeueDog() 84 | { 85 | if (_dogs.Count == 0) 86 | { 87 | throw new InvalidOperationException("There are no dogs in the shelter"); 88 | } 89 | 90 | var result = _dogs.First.Value; 91 | _dogs.RemoveFirst(); 92 | 93 | return result; 94 | } 95 | } 96 | 97 | [SuppressMessage("Maintainability Rules", "SA1402")] 98 | public class Cat : Animal 99 | { 100 | public Cat(int id) 101 | : base(id) 102 | { 103 | } 104 | } 105 | 106 | [SuppressMessage("Maintainability Rules", "SA1402")] 107 | public class Dog : Animal 108 | { 109 | public Dog(int id) 110 | : base(id) 111 | { 112 | } 113 | } 114 | 115 | [SuppressMessage("Maintainability Rules", "SA1402")] 116 | [DebuggerDisplay("Id = {Id}, ArrivalTime = {DebuggerDisplay,nq}")] 117 | public abstract class Animal 118 | { 119 | protected Animal(int id) 120 | { 121 | Id = id; 122 | ArrivalTime = DateTimeOffset.UtcNow; 123 | } 124 | 125 | public int Id { get; } 126 | 127 | public DateTimeOffset ArrivalTime { get; } 128 | 129 | [SuppressMessage("Microsoft.Performance", "CA1811")] 130 | private string DebuggerDisplay => $"{ArrivalTime:HH:mm:ss.fff}"; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 3/SortedStack.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | 5 | namespace Code 6 | { 7 | // I originally misread question 3.5 as asking to write a stack that stays sorted as you add elements not sorting an existing stack. 8 | // I had finished this implementation before I realized my mistake, so I left it here. 9 | [SuppressMessage("Microsoft.Naming", "CA1711")] 10 | public class SortedStack 11 | where T : IComparable 12 | { 13 | private readonly Stack _stack; 14 | private readonly Stack _tmpStack; 15 | private int _numItems; 16 | 17 | public SortedStack() 18 | { 19 | _stack = new Stack(); 20 | _tmpStack = new Stack(); 21 | } 22 | 23 | // Time: O(N) 24 | // Space: O(1) -> no additional space besides the items in the stack 25 | public void Push(T item) 26 | { 27 | while (_stack.Count != 0 && item.CompareTo(_stack.Peek()) > 0) 28 | { 29 | _tmpStack.Push(_stack.Pop()); 30 | } 31 | 32 | while (_tmpStack.Count != 0 && item.CompareTo(_tmpStack.Peek()) < 0) 33 | { 34 | _stack.Push(_tmpStack.Pop()); 35 | } 36 | 37 | _stack.Push(item); 38 | 39 | _numItems++; 40 | } 41 | 42 | // Time: O(N) 43 | // Space: O(1) -> no additional space besides the items in the stack 44 | public T Pop() 45 | { 46 | Peek(); 47 | _numItems--; 48 | 49 | return _stack.Pop(); 50 | } 51 | 52 | // Time: O(N) 53 | // Space: O(1) -> no additional space besides the items in the stack 54 | public T Peek() 55 | { 56 | if (_numItems == 0) 57 | { 58 | throw new InvalidOperationException("Stack has no elements"); 59 | } 60 | 61 | while (_tmpStack.Count != 0) 62 | { 63 | _stack.Push(_tmpStack.Pop()); 64 | } 65 | 66 | return _stack.Peek(); 67 | } 68 | 69 | // Time: O(1) 70 | // Space: O(1) 71 | public bool IsEmpty() 72 | { 73 | return _numItems == 0; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 4/Question4_1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Code 5 | { 6 | // 4.1 Route Between Nodes: Given a directed graph, design an algorithm to find out whether there is a route between two nodes. 7 | 8 | // Space: O(N) 9 | // Time: O(N) 10 | public static class Question4_1 11 | { 12 | public static bool AreConnected(TreeNode start, TreeNode end) 13 | where T : IEquatable 14 | { 15 | if (start == null) 16 | { 17 | throw new ArgumentNullException(nameof(start)); 18 | } 19 | 20 | if (end == null) 21 | { 22 | throw new ArgumentNullException(nameof(end)); 23 | } 24 | 25 | var processedNodes = new HashSet>(); 26 | var nodesToVisit = new Queue>(); 27 | nodesToVisit.Enqueue(start); 28 | 29 | while (nodesToVisit.Count != 0) 30 | { 31 | var node = nodesToVisit.Dequeue(); 32 | 33 | if (node.Data.Equals(end.Data)) 34 | { 35 | return true; 36 | } 37 | 38 | processedNodes.Add(node); 39 | 40 | if (node.Children != null) 41 | { 42 | foreach (var child in node.Children) 43 | { 44 | if (!processedNodes.Contains(child)) 45 | { 46 | nodesToVisit.Enqueue(child); 47 | } 48 | } 49 | } 50 | } 51 | 52 | return false; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 4/Question4_2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public static class Question4_2 6 | { 7 | // 4.2 Minimal Tree: Given a sorted (increasing order) array with unique integer elements, write an algorithm to create a 8 | // binary search tree with minimal height. 9 | 10 | // Space: O(N) 11 | // Time: O(N) 12 | public static BinaryTreeNode MakeMinimalBinarySearchTree(int[] input) 13 | { 14 | if (input == null) 15 | { 16 | throw new ArgumentNullException(nameof(input)); 17 | } 18 | 19 | return MakeMinimalBinarySearchTree(input, 0, input.Length - 1); 20 | } 21 | 22 | private static BinaryTreeNode MakeMinimalBinarySearchTree(int[] input, int start, int end) 23 | { 24 | if (end < start) 25 | { 26 | return null; 27 | } 28 | 29 | var middle = (start + end) / 2; 30 | var left = MakeMinimalBinarySearchTree(input, start, middle - 1); 31 | var right = MakeMinimalBinarySearchTree(input, middle + 1, end); 32 | 33 | return new BinaryTreeNode(input[middle], left, right); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 4/Question4_3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics.CodeAnalysis; 4 | 5 | namespace Code 6 | { 7 | public static class Question4_3 8 | { 9 | // 4.3 List of Depths: Given a binary tree, design an algorithm which creates a linked list of all of the nodes at 10 | // each depth (e.g., if you have a tree with depth D, you'll have D linked lists). 11 | 12 | // Space: O(N) 13 | // Time: O(N) 14 | [SuppressMessage("Microsoft.Design", "CA1006")] 15 | public static List>> FindDepths(BinaryTreeNode root) 16 | where T : IEquatable 17 | { 18 | if (root == null) 19 | { 20 | throw new ArgumentNullException(nameof(root)); 21 | } 22 | 23 | var result = new List>>(); 24 | var curList = new List> 25 | { 26 | root 27 | }; 28 | 29 | while (curList.Count > 0) 30 | { 31 | var nextList = new List>(); 32 | var curResult = new List>(); 33 | 34 | while (curList.Count > 0) 35 | { 36 | var cur = curList[0]; 37 | curList.RemoveAt(0); 38 | curResult.Add(cur); 39 | 40 | if (cur.Left != null) 41 | { 42 | nextList.Add(cur.Left); 43 | } 44 | 45 | if (cur.Right != null) 46 | { 47 | nextList.Add(cur.Right); 48 | } 49 | } 50 | 51 | result.Add(curResult); 52 | curList = nextList; 53 | } 54 | 55 | return result; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 4/Question4_4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public static class Question4_4 6 | { 7 | // 4.4 Check Balanced: Implement a function to check if a binary tree is balanced. For the purpose 8 | // of this question, a balanced tree is defined to be a tree such that the heights of the two subtrees 9 | // of any node never differ by more than one 10 | 11 | // Space: O(1) 12 | // Time: O(N log N) 13 | public static bool IsBalanced(BinaryTreeNode root) 14 | where T : IEquatable 15 | { 16 | if (root == null) 17 | { 18 | return true; 19 | } 20 | 21 | var leftHeight = GetHeight(root.Left); 22 | var rightHeight = GetHeight(root.Right); 23 | 24 | return Math.Abs(leftHeight - rightHeight) <= 1 25 | && IsBalanced(root.Left) 26 | && IsBalanced(root.Right); 27 | } 28 | 29 | private static int GetHeight(BinaryTreeNode root) 30 | where T : IEquatable 31 | { 32 | if (root == null) 33 | { 34 | return 0; 35 | } 36 | 37 | return 1 + Math.Max(GetHeight(root.Left), GetHeight(root.Right)); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 5/Question5_1.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace Code 4 | { 5 | public static class Question5_1 6 | { 7 | // 5.1. Insertion: You are given two 32-bit numbers, N and M, and two bit positions, i and j. 8 | // Write a method to insert M into N such that M starts at bit j and ends at bit i. You can 9 | // assume that the bits j through i have enough space to fit all of M. That is, if M = 10011, 10 | // you can assume that there are at least 5 bits between j and i. You would not, for example, 11 | // have j = 3 and i = 2, because M coudl nto fully fit between bit 3 and bit 2. 12 | // EXAMPLE 13 | // Input: N = 10000000000, M = 10011, i = 2, j = 6 14 | // Output: N = 10001001100 15 | 16 | // Space: O(1) 17 | // Time: O(1) 18 | [SuppressMessage("Microsoft.Naming", "CA1704")] 19 | public static int Insertion(int n, int m, int i, int j) 20 | { 21 | // Create mask to remove bits i through j in N 22 | var left = ~0 << j; 23 | var right = (1 << i) - 1; 24 | var mask = left | right; 25 | 26 | // Remove bits in N 27 | n &= mask; 28 | 29 | // Align bits in M 30 | m <<= i; 31 | 32 | // Add bits from M into N 33 | return m | n; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Chapter 5/Question5_2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | 4 | namespace Code 5 | { 6 | public static class Question5_2 7 | { 8 | // 5.2. Binary to String: Given a real number between 0 and 1 (e.g., 0.72) that is 9 | // passed in as a double, print the binary representation. If the number cannot be 10 | // represented accurately in binary with at most 32 characters, print "ERROR". 11 | 12 | // Space: O(1) 13 | // Time: O(1) 14 | public static string BinaryToString(double number) 15 | { 16 | if (number <= 0 || number >= 1) 17 | { 18 | throw new ArgumentOutOfRangeException(nameof(number)); 19 | } 20 | 21 | var result = new StringBuilder(); 22 | result.Append("0."); 23 | 24 | int numCharacters = 0; 25 | 26 | while (number != 0 && numCharacters < 30) 27 | { 28 | number *= 2; 29 | 30 | if (number >= 1) 31 | { 32 | result.Append(1); 33 | number -= 1; 34 | } 35 | else 36 | { 37 | result.Append(0); 38 | } 39 | } 40 | 41 | // This condition never is true due to rounding precision in the previous 42 | // calculations 43 | if (number != 0) 44 | { 45 | return "ERROR"; 46 | } 47 | 48 | return result.ToString(); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Data structures/BinaryTreeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Code 5 | { 6 | // This BinaryTreeNode implementation is adapted from the TreeNode implementation in the book 7 | [DebuggerDisplay("Data = {Data}, Left = {Left?.Data}, Right = {Right?.Data}")] 8 | public class BinaryTreeNode 9 | where T : IEquatable 10 | { 11 | public BinaryTreeNode(T data) 12 | { 13 | Data = data; 14 | } 15 | 16 | public BinaryTreeNode(T data, BinaryTreeNode left, BinaryTreeNode right) 17 | { 18 | Data = data; 19 | Left = left; 20 | Right = right; 21 | } 22 | 23 | public T Data { get; set; } 24 | 25 | public BinaryTreeNode Left { get; set; } 26 | 27 | public BinaryTreeNode Right { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Data structures/Digit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Code 5 | { 6 | [DebuggerDisplay("Value = {value}")] 7 | public class Digit : IEquatable 8 | { 9 | private readonly int _value; 10 | 11 | public Digit(int value) 12 | { 13 | if (value < 0 || value > 9) 14 | { 15 | throw new ArgumentOutOfRangeException(nameof(value), "Value must be between 0 and 9 inclusive"); 16 | } 17 | 18 | _value = value; 19 | } 20 | 21 | public static implicit operator int(Digit digit) 22 | { 23 | return digit?._value ?? 0; 24 | } 25 | 26 | public static int ToInt(Digit digit) 27 | { 28 | return digit; 29 | } 30 | 31 | public override bool Equals(object obj) 32 | { 33 | return Equals(obj as Digit); 34 | } 35 | 36 | public override int GetHashCode() 37 | { 38 | return _value; 39 | } 40 | 41 | public bool Equals(Digit other) 42 | { 43 | return other != null && _value == other._value; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Data structures/Node.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Code 5 | { 6 | // This Node implementation is directly from the book (modified as needed) 7 | [DebuggerDisplay("Data = {Data}")] 8 | public class Node 9 | where T : IEquatable 10 | { 11 | public Node(T data) 12 | { 13 | Data = data; 14 | } 15 | 16 | public T Data { get; set; } 17 | 18 | public Node Next { get; set; } 19 | 20 | public void AppendToTail(T data) 21 | { 22 | var end = new Node(data); 23 | Node n = this; 24 | 25 | while (n.Next != null) 26 | { 27 | n = n.Next; 28 | } 29 | 30 | n.Next = end; 31 | } 32 | 33 | public Node DeleteNode(Node head, T data) 34 | { 35 | if (head == null) 36 | { 37 | throw new ArgumentNullException(nameof(head)); 38 | } 39 | 40 | Node n = head; 41 | 42 | if (n.Data.Equals(data)) 43 | { 44 | return head.Next; // Moved head 45 | } 46 | 47 | while (n.Next != null) 48 | { 49 | if (n.Next.Data.Equals(data)) 50 | { 51 | n.Next = n.Next.Next; 52 | return head; // head didn't change 53 | } 54 | 55 | n = n.Next; 56 | } 57 | 58 | return head; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Data structures/TreeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Diagnostics.CodeAnalysis; 5 | using System.Linq; 6 | 7 | namespace Code 8 | { 9 | // This TreeNode implementation is directly from the book (modified as needed) 10 | [DebuggerDisplay("Data = {Data}, Children = {DebuggerDisplay}")] 11 | public class TreeNode 12 | where T : IEquatable 13 | { 14 | public TreeNode(T data) 15 | { 16 | Data = data; 17 | Children = new TreeNode[0]; 18 | } 19 | 20 | [SuppressMessage("Microsoft.Design", "CA1006")] 21 | public TreeNode(T data, IEnumerable> children) 22 | { 23 | Data = data; 24 | Children = children?.ToArray() ?? new TreeNode[0]; 25 | } 26 | 27 | public T Data { get; set; } 28 | 29 | [SuppressMessage("Microsoft.Performance", "CA1819")] 30 | public TreeNode[] Children { get; set; } 31 | 32 | private string DebuggerDisplay => string.Join("_", Children.Select(c => c?.Data.ToString() ?? "null")); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/MeetingScheduler/Meeting.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Code 5 | { 6 | [DebuggerDisplay("StartHour = {StartHour}, EndHour = {EndHour}")] 7 | public class Meeting 8 | { 9 | public Meeting(int startHour, int endHour) 10 | { 11 | if (startHour < 0 || endHour > 23 || endHour <= startHour) 12 | { 13 | throw new ArgumentException("Invalid meeting hours"); 14 | } 15 | 16 | StartHour = startHour; 17 | EndHour = endHour; 18 | } 19 | 20 | public int StartHour { get; private set; } 21 | 22 | public int EndHour { get; private set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/MeetingScheduler/MeetingScheduler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Code 5 | { 6 | // You have n people and each has meetings booked in their calendars. The goal is to determine when all n people can meet. Assume the question is for a limited interval, like the work day. Write unit tests for your implementation. 7 | 8 | // Work day: (8, 17) 9 | // Person1: (8,10), (10, 12), (15,16) 10 | // Person2: (11, 14) 11 | // Result: (14, 15), (16, 17) 12 | public static class MeetingScheduler 13 | { 14 | public static List FindMeetingTimes(int workStartHour, int workEndHour, List people) 15 | { 16 | if (workStartHour < 0 || workEndHour > 23 || workEndHour <= workStartHour) 17 | { 18 | throw new ArgumentException("Invalid meeting hours"); 19 | } 20 | 21 | if (people == null || people.Count == 0) 22 | { 23 | throw new ArgumentException("No people for this meeting", nameof(people)); 24 | } 25 | 26 | var results = new List(); 27 | 28 | // The space of this array could be optimized 29 | var isBooked = new bool[24]; 30 | 31 | foreach (var person in people) 32 | { 33 | foreach (var meeting in person.Schedule) 34 | { 35 | for (int i = meeting.StartHour; i < meeting.EndHour; i++) 36 | { 37 | isBooked[i] = true; 38 | } 39 | } 40 | } 41 | 42 | var meetingStartHour = workStartHour; 43 | 44 | while (meetingStartHour < workEndHour) 45 | { 46 | if (!isBooked[meetingStartHour]) 47 | { 48 | var meetingEndHour = meetingStartHour + 1; 49 | 50 | while (meetingEndHour < workEndHour && !isBooked[meetingEndHour]) 51 | { 52 | meetingEndHour++; 53 | } 54 | 55 | results.Add(new Meeting(meetingStartHour, meetingEndHour)); 56 | 57 | meetingStartHour = meetingEndHour; 58 | } 59 | else 60 | { 61 | meetingStartHour++; 62 | } 63 | } 64 | 65 | return results; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/MeetingScheduler/Person.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Code 4 | { 5 | public class Person 6 | { 7 | public Person(List schedule) 8 | { 9 | Schedule = schedule; 10 | } 11 | 12 | public List Schedule { get; private set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Misc/BitHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public static class BitHelpers 6 | { 7 | public static string ToBinaryString(int value) 8 | { 9 | return Convert.ToString(value, 2); 10 | } 11 | 12 | public static int FromBinaryString(string value) 13 | { 14 | return Convert.ToInt32(value, 2); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Misc/CountingIslands.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public static class CountingIslands 6 | { 7 | // Given a map indicating land (value 1) and water (value 0) determine the number 8 | // of islands that exist on the map. Islands are composed of adjacent land blocks 9 | // either directly north, west, east, or south but not diagonally. 10 | 11 | // Space: O(1) 12 | // Time: O(N^2) where N is one dimension of the map 13 | public static int CountIslands(bool[,] map) 14 | { 15 | if (map == null) 16 | { 17 | throw new ArgumentNullException(nameof(map)); 18 | } 19 | 20 | var numIslands = 0; 21 | 22 | for (int y = 0; y < map.GetLength(1); y++) 23 | { 24 | for (int x = 0; x < map.GetLength(0); x++) 25 | { 26 | if (map[x, y]) 27 | { 28 | numIslands++; 29 | MarkVisited(map, x, y); 30 | } 31 | } 32 | } 33 | 34 | return numIslands; 35 | } 36 | 37 | private static void MarkVisited(bool[,] map, int x, int y) 38 | { 39 | if (x >= 0 && y >= 0 && x < map.GetLength(0) && y < map.GetLength(1) 40 | && map[x, y]) 41 | { 42 | map[x, y] = false; 43 | MarkVisited(map, x - 1, y); 44 | MarkVisited(map, x + 1, y); 45 | MarkVisited(map, x, y - 1); 46 | MarkVisited(map, x, y + 1); 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Misc/LeastRecentlyUsedCache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Code 5 | { 6 | /// 7 | /// Implements a LRU (least recently used) cache 8 | /// 9 | /// The type of item stored in the cache 10 | public class LeastRecentlyUsedCache 11 | { 12 | private static readonly object _lockObj = new object(); 13 | 14 | private readonly int _capacity; 15 | private readonly Dictionary> _objects; 16 | private int _count; 17 | private KeyValueNode _head; 18 | private KeyValueNode _tail; 19 | 20 | public LeastRecentlyUsedCache(int capacity) 21 | { 22 | if (capacity <= 0) 23 | { 24 | throw new ArgumentOutOfRangeException(nameof(capacity), "Capacity must be positive"); 25 | } 26 | 27 | _capacity = capacity; 28 | _objects = new Dictionary>(capacity); 29 | 30 | // Create dummy nodes for head/tail to make insertion/removal easier 31 | _head = new KeyValueNode(null, default(T)); 32 | _tail = new KeyValueNode(null, default(T)); 33 | 34 | _head.Next = _tail; 35 | _tail.Previous = _head; 36 | } 37 | 38 | public T Get(string key) 39 | { 40 | lock (_lockObj) 41 | { 42 | if (!_objects.ContainsKey(key)) 43 | { 44 | return default(T); 45 | } 46 | 47 | var node = _objects[key]; 48 | DeleteNode(node); 49 | AddToHead(node); 50 | 51 | return node.Value; 52 | } 53 | } 54 | 55 | public void Set(string key, T value) 56 | { 57 | lock (_lockObj) 58 | { 59 | if (_objects.TryGetValue(key, out KeyValueNode node)) 60 | { 61 | node.Value = value; 62 | DeleteNode(node); 63 | AddToHead(node); 64 | } 65 | else 66 | { 67 | node = new KeyValueNode(key, value); 68 | _objects[key] = node; 69 | 70 | if (_count < _capacity) 71 | { 72 | _count++; 73 | AddToHead(node); 74 | } 75 | else 76 | { 77 | _objects.Remove(_tail.Previous.Key); 78 | DeleteNode(_tail.Previous); 79 | AddToHead(node); 80 | } 81 | } 82 | } 83 | } 84 | 85 | private static void DeleteNode(KeyValueNode node) 86 | { 87 | node.Previous.Next = node.Next; 88 | node.Next.Previous = node.Previous; 89 | } 90 | 91 | private void AddToHead(KeyValueNode node) 92 | { 93 | node.Next = _head.Next; 94 | node.Next.Previous = node; 95 | node.Previous = _head; 96 | _head.Next = node; 97 | } 98 | 99 | private class KeyValueNode 100 | { 101 | public KeyValueNode(string key, U value) 102 | { 103 | Key = key; 104 | Value = value; 105 | } 106 | 107 | public string Key { get; } 108 | 109 | public U Value { get; set; } 110 | 111 | public KeyValueNode Previous { get; set; } 112 | 113 | public KeyValueNode Next { get; set; } 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Misc/SubstringSearch.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | // This is an implementation of the Rabin-Karp algorithm which can determine if a string is a substring of another in linear time 6 | // with respect to the larger string. Details of the algorithm can be found here: 7 | // https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm 8 | 9 | // Space: O(1) 10 | // Time: O(N) where N is the length of the larger string 11 | public static class SubstringSearch 12 | { 13 | public static bool IsSubstring(string toMatch, string toTest) 14 | { 15 | if (string.IsNullOrEmpty(toMatch)) 16 | { 17 | throw new ArgumentException("Input cannot be null/empty", nameof(toMatch)); 18 | } 19 | 20 | if (string.IsNullOrEmpty(toTest)) 21 | { 22 | throw new ArgumentException("Input cannot be null/empty", nameof(toTest)); 23 | } 24 | 25 | // Short circut to save calculation in the case it's impossible to match 26 | if (toTest.Length < toMatch.Length) 27 | { 28 | return false; 29 | } 30 | 31 | var hash = 0; 32 | 33 | foreach (var c in toMatch) 34 | { 35 | hash ^= c; 36 | } 37 | 38 | var rollingHash = 0; 39 | 40 | for (int i = 0; i < toTest.Length; i++) 41 | { 42 | if (i >= toMatch.Length) 43 | { 44 | rollingHash ^= toTest[i - toMatch.Length]; 45 | } 46 | 47 | rollingHash ^= toTest[i]; 48 | 49 | if (hash == rollingHash 50 | && i >= toMatch.Length - 1 51 | && toTest.Substring(i - toMatch.Length + 1, toMatch.Length) == toMatch) 52 | { 53 | return true; 54 | } 55 | } 56 | 57 | return false; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Misc/WordFrequencies.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace Code 7 | { 8 | // This class computes the nth most occurring word(s) in a word document. It's been optimized to query multiple times over the same data 9 | // set. In the case where you're only interested in querying once there would be no reason to build the final dictionary and store it. 10 | // 11 | // The complexity of this algorithm is: 12 | // Time: O(w) + O(uw log uw) where w is the number of words and uw is the number of unique words 13 | // Space: O(uw) where uw is the number of unique words 14 | // I've separated the time complexity here because while the n log n sort of the unique words dominates the linear search through all of 15 | // the words in the worst case, in practical cases where processing large amounts of text in a given language (ex: a book) there are going 16 | // to be many repeated words and the ratio of the number of unique words to the number of words is going to grow logarithmically. 17 | public class WordFrequencies 18 | { 19 | private readonly IReadOnlyDictionary> _nthMostDictionary; 20 | 21 | public WordFrequencies(IEnumerable words) 22 | { 23 | if (words == null) 24 | { 25 | throw new ArgumentNullException(nameof(words)); 26 | } 27 | 28 | var frequencies = BuildFrequencyDictionary(words); 29 | _nthMostDictionary = BuildNthMostDictionary(frequencies); 30 | } 31 | 32 | // There are at least two different ways that could be considered valid orderings here for the following sample case: 33 | // A exists 2 times 34 | // B exists 2 times 35 | // C exists 1 time 36 | // 37 | // 1. Return a monotonically increasing list 38 | // n = 1 -> { A, B } 39 | // n = 2 -> { C } 40 | // 41 | // 2. "Olympic style" ordering 42 | // n = 1 -> { A, B } 43 | // n = 3 -> { C } 44 | // 45 | // There is also the choice of zero or one based indexing. For this problem I've gone with one based "Olympic style" ordering 46 | // as it seemed to be more fun and challenging to implement 47 | public List GetNthMostOccurring(int nth) 48 | { 49 | if (nth <= 0) 50 | { 51 | throw new ArgumentOutOfRangeException(nameof(nth)); 52 | } 53 | 54 | List result; 55 | 56 | if (!_nthMostDictionary.TryGetValue(nth, out result)) 57 | { 58 | result = null; 59 | } 60 | 61 | return result; 62 | } 63 | 64 | private static Dictionary BuildFrequencyDictionary(IEnumerable words) 65 | { 66 | var frequencies = new Dictionary(); 67 | 68 | foreach (var word in words) 69 | { 70 | int frequency; 71 | 72 | if (!frequencies.TryGetValue(word, out frequency)) 73 | { 74 | frequency = 0; 75 | } 76 | 77 | frequencies[word] = frequency + 1; 78 | } 79 | 80 | return frequencies; 81 | } 82 | 83 | private static IReadOnlyDictionary> BuildNthMostDictionary(Dictionary frequencyDictionary) 84 | { 85 | var results = new Dictionary>(); 86 | 87 | foreach (var frequency in frequencyDictionary) 88 | { 89 | List values; 90 | 91 | if (!results.TryGetValue(frequency.Value, out values)) 92 | { 93 | values = new List(); 94 | results[frequency.Value] = values; 95 | } 96 | 97 | values.Add(frequency.Key); 98 | } 99 | 100 | // Use a ConcurrentDictionary here to ensure thread safety for reads later on 101 | var finalDictionary = new ConcurrentDictionary>(); 102 | 103 | int index = 1; 104 | 105 | foreach (var values in results.OrderByDescending(kv => kv.Key)) 106 | { 107 | // No need to check the return value as the adds will always be successful since the algorithm ensures uniqueness at this point 108 | finalDictionary.TryAdd(index, values.Value.OrderBy(v => v).ToList()); 109 | index += values.Value.Count; 110 | } 111 | 112 | return finalDictionary; 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/OverlappingParties/OverlappingParties.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Code 6 | { 7 | public static class OverlappingParties 8 | { 9 | // Given a list of parties with a start and end time find the start time when 10 | // the most number of concurrent parties are happening. If one party starts at 11 | // the exact same time when another party ends those parties are considered to 12 | // not be overlapping. 13 | 14 | // Space: O(N) 15 | // Time: O(N^2) 16 | public static DateTime FindMostOverlappingParties(IEnumerable parties) 17 | { 18 | if (parties == null) 19 | { 20 | throw new ArgumentNullException(nameof(parties)); 21 | } 22 | 23 | if (!parties.Any()) 24 | { 25 | throw new ArgumentException("There must be at least one party", nameof(parties)); 26 | } 27 | 28 | var changes = new List>(); 29 | 30 | foreach (var party in parties) 31 | { 32 | if (party.End <= party.Start) 33 | { 34 | throw new ArgumentOutOfRangeException(nameof(parties), "Party end date must be after the start date"); 35 | } 36 | 37 | changes.Add(new Tuple(party.Start, 1)); 38 | changes.Add(new Tuple(party.End, 0)); 39 | } 40 | 41 | changes = changes 42 | .OrderBy(e => e.Item1) 43 | .ThenBy(e => e.Item2) 44 | .ToList(); 45 | 46 | var result = DateTime.MinValue; 47 | var maxOverlappingParties = int.MinValue; 48 | var numOverlappingParties = 0; 49 | 50 | foreach (var change in changes) 51 | { 52 | if (change.Item2 == 1) 53 | { 54 | // Party start 55 | numOverlappingParties++; 56 | if (numOverlappingParties > maxOverlappingParties) 57 | { 58 | maxOverlappingParties = numOverlappingParties; 59 | result = change.Item1; 60 | } 61 | } 62 | else 63 | { 64 | // Party end 65 | numOverlappingParties--; 66 | } 67 | } 68 | 69 | return result; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/OverlappingParties/Party.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Code 4 | { 5 | public class Party 6 | { 7 | public Party(DateTime start, DateTime end) 8 | { 9 | Start = start; 10 | End = end; 11 | } 12 | 13 | public DateTime Start { get; } 14 | 15 | public DateTime End { get; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("Code")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("Code")] 12 | [assembly: AssemblyCopyright("Copyright © 2016")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("e965dea4-89d4-46ba-af5f-711141ea91c8")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/Settings.StyleCop: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | False 8 | 9 | 10 | 11 | 12 | False 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | False 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | False 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Code/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/CodeFSharp/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | namespace CodeFSharp.AssemblyInfo 2 | 3 | open System.Reflection 4 | open System.Runtime.CompilerServices 5 | open System.Runtime.InteropServices 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [] 11 | [] 12 | [] 13 | [] 14 | [] 15 | [] 16 | [] 17 | [] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | [] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Build and Revision Numbers 35 | // by using the '*' as shown below: 36 | // [] 37 | [] 38 | [] 39 | 40 | do 41 | () -------------------------------------------------------------------------------- /CrackingTheCodingInterview/CodeFSharp/CodeFSharp.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | 2.0 8 | 0de770d0-c23c-4280-8f8b-5de25e6f1042 9 | Library 10 | CodeFSharp 11 | CodeFSharp 12 | v4.6.1 13 | 4.4.0.0 14 | true 15 | CodeFSharp 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | 3 26 | bin\Debug\CodeFSharp.XML 27 | 28 | 29 | pdbonly 30 | true 31 | true 32 | bin\Release\ 33 | TRACE 34 | 3 35 | bin\Release\CodeFSharp.XML 36 | 37 | 38 | 39 | 40 | True 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 11 53 | 54 | 55 | 56 | 57 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets 58 | 59 | 60 | 61 | 62 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets 63 | 64 | 65 | 66 | 67 | 74 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/CodeFSharp/Question1_1.fs: -------------------------------------------------------------------------------- 1 | namespace CodeFSharp 2 | 3 | // 1.1 Is Unique: Implement an algorithm to determine if a string has all unique characters. 4 | // What if you cannot use additional data structures? 5 | module Question1_1 = 6 | let private CountUniqueCharacters string = 7 | string 8 | |> Seq.distinct 9 | |> Seq.length 10 | 11 | // Space: O(N) 12 | // Time: O(N) 13 | let AreAllCharactersUnique string = 14 | Seq.length string = CountUniqueCharacters string -------------------------------------------------------------------------------- /CrackingTheCodingInterview/CodeFSharp/Script.fsx: -------------------------------------------------------------------------------- 1 | // Learn more about F# at http://fsharp.org. See the 'F# Tutorial' project 2 | // for more guidance on F# programming. 3 | 4 | #load "Library1.fs" 5 | open CodeFSharp 6 | 7 | // Define your library scripting code here 8 | 9 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/CrackingTheCodingInterview.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {8796B62C-BD45-4BEE-B2C5-F64FA0FC285D} 8 | Exe 9 | Properties 10 | CrackingTheCodingInterview 11 | CrackingTheCodingInterview 12 | v4.5.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 60 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/CrackingTheCodingInterview.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25123.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "..\Tests\Tests.csproj", "{EF9B082C-2CAD-4EBF-8BBD-635FE8144620}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Code", "Code\Code.csproj", "{E965DEA4-89D4-46BA-AF5F-711141EA91C8}" 9 | EndProject 10 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "CodeFSharp", "CodeFSharp\CodeFSharp.fsproj", "{0DE770D0-C23C-4280-8F8B-5DE25E6F1042}" 11 | EndProject 12 | Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TestsFSharp", "TestsFSharp\TestsFSharp.fsproj", "{0B835540-9CB0-45DB-BF56-22E2E7F44FE6}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {EF9B082C-2CAD-4EBF-8BBD-635FE8144620}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {EF9B082C-2CAD-4EBF-8BBD-635FE8144620}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {EF9B082C-2CAD-4EBF-8BBD-635FE8144620}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {EF9B082C-2CAD-4EBF-8BBD-635FE8144620}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {E965DEA4-89D4-46BA-AF5F-711141EA91C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {E965DEA4-89D4-46BA-AF5F-711141EA91C8}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {E965DEA4-89D4-46BA-AF5F-711141EA91C8}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {E965DEA4-89D4-46BA-AF5F-711141EA91C8}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {0DE770D0-C23C-4280-8F8B-5DE25E6F1042}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {0DE770D0-C23C-4280-8F8B-5DE25E6F1042}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {0DE770D0-C23C-4280-8F8B-5DE25E6F1042}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {0DE770D0-C23C-4280-8F8B-5DE25E6F1042}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {0B835540-9CB0-45DB-BF56-22E2E7F44FE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {0B835540-9CB0-45DB-BF56-22E2E7F44FE6}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {0B835540-9CB0-45DB-BF56-22E2E7F44FE6}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {0B835540-9CB0-45DB-BF56-22E2E7F44FE6}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("CrackingTheCodingInterview")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("CrackingTheCodingInterview")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("8796b62c-bd45-4bee-b2c5-f64fa0fc285d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/TestsFSharp/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | namespace TestsFSharp.AssemblyInfo 2 | 3 | open System.Reflection 4 | open System.Runtime.CompilerServices 5 | open System.Runtime.InteropServices 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [] 11 | [] 12 | [] 13 | [] 14 | [] 15 | [] 16 | [] 17 | [] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | [] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Build and Revision Numbers 35 | // by using the '*' as shown below: 36 | // [] 37 | [] 38 | [] 39 | 40 | do 41 | () -------------------------------------------------------------------------------- /CrackingTheCodingInterview/TestsFSharp/Script.fsx: -------------------------------------------------------------------------------- 1 | // Learn more about F# at http://fsharp.org. See the 'F# Tutorial' project 2 | // for more guidance on F# programming. 3 | 4 | #load "Library1.fs" 5 | open TestsFSharp 6 | 7 | // Define your library scripting code here 8 | 9 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/TestsFSharp/Test1_1.fs: -------------------------------------------------------------------------------- 1 | module Test1_1 2 | 3 | open CodeFSharp.Question1_1 4 | open NUnit.Framework 5 | open FsUnit 6 | 7 | [] 8 | let ``No Duplicate returns true`` () = 9 | // Arrange 10 | let expected = true 11 | let input = "abc" 12 | 13 | // Act 14 | let actual = AreAllCharactersUnique input 15 | 16 | // Assert 17 | Assert.AreEqual (expected, actual) 18 | 19 | [] 20 | let ``Duplicates returns false`` () = 21 | // Arrange 22 | let expected = false 23 | let input = "aba" 24 | 25 | // Act 26 | let actual = AreAllCharactersUnique input 27 | 28 | // Assert 29 | Assert.AreEqual (expected, actual) 30 | 31 | [] 32 | let ``Casing difference returns true`` () = 33 | // Arrange 34 | let expected = true 35 | let input = "Aa" 36 | 37 | // Act 38 | let actual = AreAllCharactersUnique input 39 | 40 | // Assert 41 | Assert.AreEqual (expected, actual) -------------------------------------------------------------------------------- /CrackingTheCodingInterview/TestsFSharp/TestsFSharp.fsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | 2.0 8 | 0b835540-9cb0-45db-bf56-22e2e7f44fe6 9 | Library 10 | TestsFSharp 11 | TestsFSharp 12 | v4.6.1 13 | 4.4.0.0 14 | true 15 | TestsFSharp 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | false 23 | bin\Debug\ 24 | DEBUG;TRACE 25 | 3 26 | bin\Debug\TestsFSharp.XML 27 | 28 | 29 | pdbonly 30 | true 31 | true 32 | bin\Release\ 33 | TRACE 34 | 3 35 | bin\Release\TestsFSharp.XML 36 | 37 | 38 | 11 39 | 40 | 41 | 42 | 43 | $(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets 44 | 45 | 46 | 47 | 48 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | ..\packages\FSharp.Core.3.1.2.5\lib\net40\FSharp.Core.dll 62 | True 63 | 64 | 65 | ..\packages\FsUnit.2.3.0\lib\net45\FsUnit.NUnit.dll 66 | True 67 | 68 | 69 | 70 | ..\packages\FsUnit.2.3.0\lib\net45\NHamcrest.dll 71 | True 72 | 73 | 74 | ..\packages\NUnit.3.4.0\lib\net45\nunit.framework.dll 75 | True 76 | 77 | 78 | 79 | 80 | 81 | CodeFSharp 82 | {0de770d0-c23c-4280-8f8b-5de25e6f1042} 83 | True 84 | 85 | 86 | 93 | -------------------------------------------------------------------------------- /CrackingTheCodingInterview/TestsFSharp/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Tests/AssemblyAttributes.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using System.Reflection; 4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6.1", FrameworkDisplayName = ".NET Framework 4.6.1")] 5 | -------------------------------------------------------------------------------- /Tests/Chapter 1/Test1_1.cs: -------------------------------------------------------------------------------- 1 | using Code; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace Tests 5 | { 6 | [TestClass] 7 | public class Test1_1 8 | { 9 | [TestMethod] 10 | public void ImplementationOne_NoDuplicates_ReturnsTrue() 11 | { 12 | // Arrange 13 | const bool expected = true; 14 | const string input = "abc"; 15 | 16 | // Act 17 | var actual = Question1_1.AreAllCharactersUnique(input); 18 | 19 | // Assert 20 | Assert.AreEqual(expected, actual); 21 | } 22 | 23 | [TestMethod] 24 | public void ImplementationTwo_NoDuplicates_ReturnsTrue() 25 | { 26 | // Arrange 27 | const bool expected = true; 28 | const string input = "abc"; 29 | 30 | // Act 31 | var actual = Question1_1.AreAllCharactersUniqueNoAdditionalMemory(input); 32 | 33 | // Assert 34 | Assert.AreEqual(expected, actual); 35 | } 36 | 37 | [TestMethod] 38 | public void ImplementationOne_Duplicates_ReturnsFalse() 39 | { 40 | // Arrange 41 | const bool expected = false; 42 | const string input = "aba"; 43 | 44 | // Act 45 | var actual = Question1_1.AreAllCharactersUnique(input); 46 | 47 | // Assert 48 | Assert.AreEqual(expected, actual); 49 | } 50 | 51 | [TestMethod] 52 | public void ImplementationTwo_Duplicates_ReturnsFalse() 53 | { 54 | // Arrange 55 | const bool expected = false; 56 | const string input = "aba"; 57 | 58 | // Act 59 | var actual = Question1_1.AreAllCharactersUniqueNoAdditionalMemory(input); 60 | 61 | // Assert 62 | Assert.AreEqual(expected, actual); 63 | } 64 | 65 | [TestMethod] 66 | public void ImplementationOne_CasingDifference_ReturnsTrue() 67 | { 68 | // Arrange 69 | const bool expected = true; 70 | const string input = "Aa"; 71 | 72 | // Act 73 | var actual = Question1_1.AreAllCharactersUnique(input); 74 | 75 | // Assert 76 | Assert.AreEqual(expected, actual); 77 | } 78 | 79 | [TestMethod] 80 | public void ImplementationTwo_CasingDifference_ReturnsTrue() 81 | { 82 | // Arrange 83 | const bool expected = true; 84 | const string input = "Aa"; 85 | 86 | // Act 87 | var actual = Question1_1.AreAllCharactersUniqueNoAdditionalMemory(input); 88 | 89 | // Assert 90 | Assert.AreEqual(expected, actual); 91 | } 92 | 93 | [TestMethod] 94 | public void ImplementationOne_NullString_ReturnsTrue() 95 | { 96 | // Arrange 97 | const bool expected = true; 98 | const string input = null; 99 | 100 | // Act 101 | var actual = Question1_1.AreAllCharactersUnique(input); 102 | 103 | // Assert 104 | Assert.AreEqual(expected, actual); 105 | } 106 | 107 | [TestMethod] 108 | public void ImplementationTwo_NullString_ReturnsTrue() 109 | { 110 | // Arrange 111 | const bool expected = true; 112 | const string input = null; 113 | 114 | // Act 115 | var actual = Question1_1.AreAllCharactersUniqueNoAdditionalMemory(input); 116 | 117 | // Assert 118 | Assert.AreEqual(expected, actual); 119 | } 120 | 121 | [TestMethod] 122 | public void ImplementationOne_EmptyString_ReturnsTrue() 123 | { 124 | // Arrange 125 | const bool expected = true; 126 | var input = string.Empty; 127 | 128 | // Act 129 | var actual = Question1_1.AreAllCharactersUnique(input); 130 | 131 | // Assert 132 | Assert.AreEqual(expected, actual); 133 | } 134 | 135 | [TestMethod] 136 | public void ImplementationTwo_EmptyString_ReturnsTrue() 137 | { 138 | // Arrange 139 | const bool expected = true; 140 | var input = string.Empty; 141 | 142 | // Act 143 | var actual = Question1_1.AreAllCharactersUniqueNoAdditionalMemory(input); 144 | 145 | // Assert 146 | Assert.AreEqual(expected, actual); 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /Tests/Chapter 1/Test1_2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test1_2 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | // Permutations 14 | ValidateResult("abc", "abc", true); 15 | ValidateResult("abc", "bca", true); 16 | 17 | // Not permutations 18 | ValidateResult("abc", "abca", false); 19 | ValidateResult("abc", "xyz", false); 20 | } 21 | 22 | [TestMethod] 23 | public void CaseSensitivityTest() 24 | { 25 | // 'A' and 'a' are considered different characters 26 | ValidateResult("A", "a", false); 27 | } 28 | 29 | [TestMethod] 30 | public void NullAndEmptyStringsTest() 31 | { 32 | // Null 33 | string str1 = null; 34 | string str2 = null; 35 | ValidateResult(str1, str2, typeof(ArgumentException)); 36 | 37 | // Empty string 38 | str1 = string.Empty; 39 | str2 = string.Empty; 40 | ValidateResult(str1, str2, typeof(ArgumentException)); 41 | 42 | // One one argument invalid 43 | str1 = "abc"; 44 | str2 = null; 45 | ValidateResult(str1, str2, typeof(ArgumentException)); 46 | 47 | str2 = string.Empty; 48 | ValidateResult(str1, str2, typeof(ArgumentException)); 49 | 50 | str1 = null; 51 | str2 = "abc"; 52 | ValidateResult(str1, str2, typeof(ArgumentException)); 53 | 54 | str1 = string.Empty; 55 | ValidateResult(str1, str2, typeof(ArgumentException)); 56 | } 57 | 58 | private static void ValidateResult(string str1, string str2, bool expectedResult) 59 | { 60 | Assert.AreEqual(expectedResult, Question1_2.AreStringsPermutation(str1, str2)); 61 | Assert.AreEqual(expectedResult, Question1_2.AreStringsPermutationNoSort(str1, str2)); 62 | } 63 | 64 | private static void ValidateResult(string str1, string str2, Type expectedException) 65 | { 66 | TestHelpers.AssertExceptionThrown(() => { Question1_2.AreStringsPermutation(str1, str2); }, expectedException); 67 | TestHelpers.AssertExceptionThrown(() => { Question1_2.AreStringsPermutationNoSort(str1, str2); }, expectedException); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Tests/Chapter 1/Test1_3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test1_3 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | // Sample case given in the problem 14 | ValideResult("Mr John Smith ", "Mr%20John%20Smith"); 15 | } 16 | 17 | [TestMethod] 18 | public void EdgeCasesTest() 19 | { 20 | // No spaces 21 | ValideResult("abc", "abc"); 22 | 23 | // First letter is a space 24 | ValideResult(" abc ", "%20abc"); 25 | 26 | // Last letter is a space 27 | ValideResult("abc ", "abc%20", 4); 28 | 29 | // Empty string 30 | ValideResult(string.Empty, string.Empty); 31 | } 32 | 33 | [TestMethod] 34 | public void InvalidInputsTest() 35 | { 36 | // Invalid length 37 | var str = "foo".ToCharArray(); 38 | TestHelpers.AssertExceptionThrown(() => { Question1_3.ReplaceSpaces(str, -1); }, typeof(ArgumentOutOfRangeException)); 39 | 40 | // Null input string 41 | str = null; 42 | TestHelpers.AssertExceptionThrown(() => { Question1_3.ReplaceSpaces(str, 0); }, typeof(ArgumentNullException)); 43 | } 44 | 45 | private static void ValideResult(string input, string expectedResult, int? inputLength = null) 46 | { 47 | if (input.Length != expectedResult.Length) 48 | { 49 | throw new ArgumentException("Input and expected result must be the same length"); 50 | } 51 | 52 | var str = input.ToCharArray(); 53 | var length = inputLength ?? input.TrimEnd(" ".ToCharArray()).Length; 54 | 55 | Question1_3.ReplaceSpaces(str, length); 56 | 57 | for (int i = 0; i < expectedResult.Length; i++) 58 | { 59 | Assert.AreEqual(expectedResult[i], str[i]); 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Tests/Chapter 1/Test1_4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test1_4 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | // Given sample 14 | ValidateResult("tactcoa", true); 15 | 16 | // Input is already a palindrome 17 | ValidateResult("abcba", true); 18 | 19 | // Even number of characters 20 | ValidateResult("abab", true); 21 | 22 | // Odd number of characters 23 | ValidateResult("aab", true); 24 | 25 | // One character 26 | ValidateResult("a", true); 27 | 28 | // Two characters 29 | ValidateResult("aa", true); 30 | ValidateResult("ab", false); 31 | } 32 | 33 | [TestMethod] 34 | public void CaseSensitivityTest() 35 | { 36 | // 'A' and 'a' are considered different characters 37 | ValidateResult("Aa", false); 38 | } 39 | 40 | [TestMethod] 41 | public void NullAndEmptyStringsTest() 42 | { 43 | ValidateResult(null, typeof(ArgumentException)); 44 | ValidateResult(string.Empty, typeof(ArgumentException)); 45 | } 46 | 47 | private static void ValidateResult(string input, bool expectedResult) 48 | { 49 | Assert.AreEqual(expectedResult, Question1_4.IsPalindromePermutation(input)); 50 | Assert.AreEqual(expectedResult, Question1_4.IsPalindromePermutationNoAdditionalSpace(input)); 51 | } 52 | 53 | private static void ValidateResult(string input, Type expectedException) 54 | { 55 | TestHelpers.AssertExceptionThrown(() => { Question1_4.IsPalindromePermutation(input); }, expectedException); 56 | TestHelpers.AssertExceptionThrown(() => { Question1_4.IsPalindromePermutationNoAdditionalSpace(input); }, expectedException); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Tests/Chapter 1/Test1_5.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test1_5 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | // Use the samples given in the problem 14 | ValidateResult("pale", "ple", true); 15 | ValidateResult("pales", "pale", true); 16 | ValidateResult("pale", "bale", true); 17 | ValidateResult("pale", "bake", false); 18 | } 19 | 20 | [TestMethod] 21 | public void EdgeCaseTest() 22 | { 23 | // The algorithm is case sensitive 24 | ValidateResult("foo", "Foo", true); 25 | ValidateResult("foo", "FOO", false); 26 | 27 | // Using the same string twice 28 | ValidateResult("foo", "foo", true); 29 | } 30 | 31 | [TestMethod] 32 | public void NullAndEmptyStringsTest() 33 | { 34 | // First argument 35 | TestHelpers.AssertExceptionThrown(() => { Question1_5.IsOneAway(null, "foo"); }, typeof(ArgumentException)); 36 | TestHelpers.AssertExceptionThrown(() => { Question1_5.IsOneAway(string.Empty, "foo"); }, typeof(ArgumentException)); 37 | 38 | // Second argument 39 | TestHelpers.AssertExceptionThrown(() => { Question1_5.IsOneAway("foo", null); }, typeof(ArgumentException)); 40 | TestHelpers.AssertExceptionThrown(() => { Question1_5.IsOneAway("foo", string.Empty); }, typeof(ArgumentException)); 41 | } 42 | 43 | private static void ValidateResult(string s1, string s2, bool expectedResult) 44 | { 45 | Assert.AreEqual(expectedResult, Question1_5.IsOneAway(s1, s2)); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Tests/Chapter 1/Test1_6.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test1_6 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | // Sample case given in the problem 14 | ValidateResult("aabcccccaaa", "a2b1c5a3"); 15 | 16 | ValidateResult("aaaaaaa", "a7"); 17 | 18 | // Return original string is returned as compressed string would be larger/same size 19 | ValidateResult("a", "a"); 20 | ValidateResult("aa", "aa"); 21 | } 22 | 23 | [TestMethod] 24 | public void CaseSensitivityTest() 25 | { 26 | // 'A' and 'a' are considered different characters 27 | ValidateResult("AAaaa", "A2a3"); 28 | } 29 | 30 | [TestMethod] 31 | public void InvalidInputsTest() 32 | { 33 | // Null input 34 | TestHelpers.AssertExceptionThrown(() => { Question1_6.Compress(null); }, typeof(ArgumentException)); 35 | 36 | // Empty input 37 | TestHelpers.AssertExceptionThrown(() => { Question1_6.Compress(string.Empty); }, typeof(ArgumentException)); 38 | } 39 | 40 | private static void ValidateResult(string input, string expectedResult) 41 | { 42 | Assert.AreEqual(expectedResult, Question1_6.Compress(input)); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Tests/Chapter 1/Test1_7.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test1_7 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | // 2x2 14 | var input = MatrixHelpers.CreateTwoDimensionalMatrix(1, 2, 3, 4); 15 | var expectedResult = MatrixHelpers.CreateTwoDimensionalMatrix(3, 1, 4, 2); 16 | ValidateResult(input, expectedResult); 17 | 18 | // 3x3 19 | input = MatrixHelpers.CreateTwoDimensionalMatrix(1, 2, 3, 4, 5, 6, 7, 8, 9); 20 | expectedResult = MatrixHelpers.CreateTwoDimensionalMatrix(7, 4, 1, 8, 5, 2, 9, 6, 3); 21 | ValidateResult(input, expectedResult); 22 | 23 | // 4x4 24 | input = MatrixHelpers.CreateTwoDimensionalMatrix(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); 25 | expectedResult = MatrixHelpers.CreateTwoDimensionalMatrix(13, 9, 5, 1, 14, 10, 6, 2, 15, 11, 7, 3, 16, 12, 8, 4); 26 | ValidateResult(input, expectedResult); 27 | 28 | // 5x5 29 | input = MatrixHelpers.CreateTwoDimensionalMatrix(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25); 30 | expectedResult = MatrixHelpers.CreateTwoDimensionalMatrix(21, 16, 11, 6, 1, 22, 17, 12, 7, 2, 23, 18, 13, 8, 3, 24, 19, 14, 9, 4, 25, 20, 15, 10, 5); 31 | ValidateResult(input, expectedResult); 32 | } 33 | 34 | [TestMethod] 35 | public void EdgeCaseTest() 36 | { 37 | // 1x1 38 | var input = MatrixHelpers.CreateTwoDimensionalMatrix(1); 39 | var expectedResult = MatrixHelpers.CreateTwoDimensionalMatrix(1); 40 | ValidateResult(input, expectedResult); 41 | } 42 | 43 | [TestMethod] 44 | public void InvalidInputsTest() 45 | { 46 | // Null matrix 47 | TestHelpers.AssertExceptionThrown(() => { Question1_7.RotateMatrix(null); }, typeof(ArgumentNullException)); 48 | TestHelpers.AssertExceptionThrown(() => { Question1_7.RotateMatrixInPlace(null); }, typeof(ArgumentNullException)); 49 | 50 | // Non-square matrix 51 | var matrix = new[,] 52 | { 53 | { 1, 2, 3 }, 54 | { 4, 5, 6 } 55 | }; 56 | 57 | TestHelpers.AssertExceptionThrown(() => { Question1_7.RotateMatrix(matrix); }, typeof(ArgumentException)); 58 | TestHelpers.AssertExceptionThrown(() => { Question1_7.RotateMatrixInPlace(matrix); }, typeof(ArgumentException)); 59 | } 60 | 61 | private static void ValidateResult(int[,] input, int[,] expectedResult) 62 | { 63 | var size = input.GetLength(0); 64 | 65 | var result1 = new int[size, size]; 66 | var result2 = new int[size, size]; 67 | 68 | // Perform deep-copies of the original array 69 | for (int i = 0; i < size; i++) 70 | { 71 | for (int j = 0; j < size; j++) 72 | { 73 | result1[i, j] = input[i, j]; 74 | result2[i, j] = input[i, j]; 75 | } 76 | } 77 | 78 | result1 = Question1_7.RotateMatrix(result1); 79 | Question1_7.RotateMatrixInPlace(result2); 80 | 81 | for (int i = 0; i < size; i++) 82 | { 83 | for (int j = 0; j < size; j++) 84 | { 85 | Assert.AreEqual(expectedResult[i, j], result1[i, j]); 86 | Assert.AreEqual(expectedResult[i, j], result2[i, j]); 87 | } 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Tests/Chapter 1/Test1_9.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test1_9 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | // Sample given in problem 14 | ValidateResult("waterbottle", "erbottlewat", true); 15 | 16 | // Different length input 17 | ValidateResult("abc", "abcd", false); 18 | } 19 | 20 | [TestMethod] 21 | public void EdgeCaseTest() 22 | { 23 | // Same string two times 24 | ValidateResult("abc", "abc", true); 25 | 26 | // Case differences 27 | ValidateResult("abc", "ABC", false); 28 | } 29 | 30 | [TestMethod] 31 | public void InvalidInputTest() 32 | { 33 | // Null input 34 | TestHelpers.AssertExceptionThrown(() => { Question1_9.IsRotation("abc", null); }, typeof(ArgumentException)); 35 | TestHelpers.AssertExceptionThrown(() => { Question1_9.IsRotation(null, "abc"); }, typeof(ArgumentException)); 36 | TestHelpers.AssertExceptionThrown(() => { Question1_9.IsRotation(null, null); }, typeof(ArgumentException)); 37 | 38 | // Empty input 39 | TestHelpers.AssertExceptionThrown(() => { Question1_9.IsRotation("abc", string.Empty); }, typeof(ArgumentException)); 40 | TestHelpers.AssertExceptionThrown(() => { Question1_9.IsRotation(string.Empty, "abc"); }, typeof(ArgumentException)); 41 | TestHelpers.AssertExceptionThrown(() => { Question1_9.IsRotation(string.Empty, string.Empty); }, typeof(ArgumentException)); 42 | } 43 | 44 | private static void ValidateResult(string s1, string s2, bool expectedResult) 45 | { 46 | Assert.AreEqual(expectedResult, Question1_9.IsRotation(s1, s2)); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Tests/Chapter 16/Tests16_1.cs: -------------------------------------------------------------------------------- 1 | using Code; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace Tests 5 | { 6 | [TestClass] 7 | public class Tests16_1 8 | { 9 | [TestMethod] 10 | public void SwapNumbers_ReturnsCorrectValue_ForTwoPositiveNumbers() 11 | { 12 | // Arrange 13 | var num1 = 1; 14 | var num2 = 2; 15 | 16 | // Act 17 | Question16_1.SwapNumbers(ref num1, ref num2); 18 | 19 | // Assert 20 | Assert.AreEqual(2, num1); 21 | Assert.AreEqual(1, num2); 22 | } 23 | 24 | [TestMethod] 25 | public void SwapNumbers_ReturnsCorrectValue_ForNegativeNumber() 26 | { 27 | // Arrange 28 | var num1 = -1; 29 | var num2 = 2; 30 | 31 | // Act 32 | Question16_1.SwapNumbers(ref num1, ref num2); 33 | 34 | // Assert 35 | Assert.AreEqual(2, num1); 36 | Assert.AreEqual(-1, num2); 37 | } 38 | 39 | [TestMethod] 40 | public void SwapNumbers_ReturnsCorrectValue_ForNumbersWithSameValue() 41 | { 42 | // Arrange 43 | var num1 = 1; 44 | var num2 = 1; 45 | 46 | // Act 47 | Question16_1.SwapNumbers(ref num1, ref num2); 48 | 49 | // Assert 50 | Assert.AreEqual(1, num1); 51 | Assert.AreEqual(1, num2); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Tests/Chapter 16/Tests16_4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Tests16_4 9 | { 10 | [TestMethod] 11 | public void HasWinner_ReturnsFalse_ForEmptyBoard() 12 | { 13 | // Arrange 14 | var board = new int?[3, 3]; 15 | 16 | // Act 17 | var result = Question16_4.HasWinner(board); 18 | 19 | // Assert 20 | Assert.IsFalse(result); 21 | } 22 | 23 | [TestMethod] 24 | public void HasWinner_ReturnsTrue_ForHorizontalWin() 25 | { 26 | // Arrange 27 | var board = new int?[3, 3]; 28 | board[0, 0] = 1; 29 | board[1, 0] = 1; 30 | board[2, 0] = 1; 31 | 32 | // Act 33 | var result = Question16_4.HasWinner(board); 34 | 35 | // Assert 36 | Assert.IsTrue(result); 37 | } 38 | 39 | [TestMethod] 40 | public void HasWinner_ReturnsTrue_ForVerticalWin() 41 | { 42 | // Arrange 43 | var board = new int?[3, 3]; 44 | board[0, 0] = 1; 45 | board[0, 1] = 1; 46 | board[0, 2] = 1; 47 | 48 | // Act 49 | var result = Question16_4.HasWinner(board); 50 | 51 | // Assert 52 | Assert.IsTrue(result); 53 | } 54 | 55 | [TestMethod] 56 | public void HasWinner_ReturnsTrue_ForTopLeftToBottomRightWin() 57 | { 58 | // Arrange 59 | var board = new int?[3, 3]; 60 | board[0, 0] = 1; 61 | board[1, 1] = 1; 62 | board[2, 2] = 1; 63 | 64 | // Act 65 | var result = Question16_4.HasWinner(board); 66 | 67 | // Assert 68 | Assert.IsTrue(result); 69 | } 70 | 71 | [TestMethod] 72 | public void HasWinner_ReturnsTrue_ForTopRightToBottomLeftWin() 73 | { 74 | // Arrange 75 | var board = new int?[3, 3]; 76 | board[0, 2] = 1; 77 | board[1, 1] = 1; 78 | board[2, 0] = 1; 79 | 80 | // Act 81 | var result = Question16_4.HasWinner(board); 82 | 83 | // Assert 84 | Assert.IsTrue(result); 85 | } 86 | 87 | [TestMethod] 88 | public void HasWinner_ReturnsFalse_WithMultiplePlayersInSameRow() 89 | { 90 | // Arrange 91 | var board = new int?[3, 3]; 92 | board[0, 0] = 1; 93 | board[0, 1] = 1; 94 | board[0, 2] = 2; 95 | 96 | // Act 97 | var result = Question16_4.HasWinner(board); 98 | 99 | // Assert 100 | Assert.IsFalse(result); 101 | } 102 | 103 | [TestMethod] 104 | public void HasWinner_ThrowsArgumentInvalidException_WhenBoardIsNull() 105 | { 106 | // Act 107 | void action() => Question16_4.HasWinner(null); 108 | 109 | // Assert 110 | TestHelpers.AssertExceptionThrown(action, typeof(ArgumentNullException)); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Tests/Chapter 2/Test2_1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test2_1 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | // Single duplicate 14 | var list = ListHelpers.CreateLinkedList(1, 2, 2, 3); 15 | ValidateResult(list, 1, 2, 3); 16 | 17 | // No duplicates 18 | list = ListHelpers.CreateLinkedList(1, 2, 3); 19 | ValidateResult(list, 1, 2, 3); 20 | 21 | // Three of the same values in the row 22 | list = ListHelpers.CreateLinkedList(1, 2, 2, 2, 3); 23 | ValidateResult(list, 1, 2, 3); 24 | 25 | // Duplicates not next to each other 26 | list = ListHelpers.CreateLinkedList(1, 2, 3, 2); 27 | ValidateResult(list, 1, 2, 3); 28 | 29 | // Duplicates next to each other with a third later in the list 30 | list = ListHelpers.CreateLinkedList(1, 2, 2, 3, 2); 31 | ValidateResult(list, 1, 2, 3); 32 | 33 | // Several duplicates throughout the list 34 | list = ListHelpers.CreateLinkedList(1, 2, 2, 3, 2, 4, 3, 5, 5, 6); 35 | ValidateResult(list, 1, 2, 3, 4, 5, 6); 36 | } 37 | 38 | [TestMethod] 39 | public void EdgeCasesTest() 40 | { 41 | // First item duplicated 42 | var list = ListHelpers.CreateLinkedList(1, 1, 2, 3); 43 | ValidateResult(list, 1, 2, 3); 44 | 45 | // Last item duplciated 46 | list = ListHelpers.CreateLinkedList(1, 2, 3, 3); 47 | ValidateResult(list, 1, 2, 3); 48 | 49 | // List with only one element 50 | list = ListHelpers.CreateLinkedList(1); 51 | ValidateResult(list, 1); 52 | } 53 | 54 | [TestMethod] 55 | public void InvalidInputsTest() 56 | { 57 | // Null input string 58 | TestHelpers.AssertExceptionThrown(() => { Question2_1.RemoveDuplicates(null); }, typeof(ArgumentNullException)); 59 | TestHelpers.AssertExceptionThrown(() => { Question2_1.RemoveDuplicatesNoSpace(null); }, typeof(ArgumentNullException)); 60 | } 61 | 62 | private static void ValidateResult(Node input, params T[] expectedResult) 63 | where T : IEquatable 64 | { 65 | var input1 = ListHelpers.CloneList(input); 66 | var input2 = ListHelpers.CloneList(input); 67 | 68 | Question2_1.RemoveDuplicates(input1); 69 | Question2_1.RemoveDuplicatesNoSpace(input2); 70 | 71 | ListHelpers.ValidateLinkedListContent(input1, expectedResult); 72 | ListHelpers.ValidateLinkedListContent(input2, expectedResult); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Tests/Chapter 2/Test2_2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Code; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace Tests 7 | { 8 | [TestClass] 9 | public class Test2_2 10 | { 11 | [TestMethod] 12 | public void BasicTest() 13 | { 14 | const int NumElements = 5; 15 | 16 | var list = ListHelpers.CreateLinkedList(Enumerable.Range(0, NumElements).Reverse().ToArray()); 17 | 18 | for (int i = 0; i < NumElements; i++) 19 | { 20 | var input = ListHelpers.CloneList(list); 21 | var result = Question2_2.FindKthToLast(input, i); 22 | 23 | Assert.AreEqual(i, result.Data); 24 | } 25 | } 26 | 27 | [TestMethod] 28 | public void InvalidInputsTest() 29 | { 30 | // Null input 31 | TestHelpers.AssertExceptionThrown(() => { Question2_2.FindKthToLast(null, 0); }, typeof(ArgumentNullException)); 32 | 33 | // K invalid 34 | var list = ListHelpers.CreateLinkedList(1, 2, 3); 35 | TestHelpers.AssertExceptionThrown(() => { Question2_2.FindKthToLast(list, -1); }, typeof(ArgumentOutOfRangeException)); 36 | 37 | list = ListHelpers.CreateLinkedList(1, 2, 3); 38 | TestHelpers.AssertExceptionThrown(() => { Question2_2.FindKthToLast(list, 4); }, typeof(ArgumentOutOfRangeException)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Tests/Chapter 2/Test2_3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test2_3 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | // Test case given in the problem 14 | var demoList = ListHelpers.CreateLinkedList('a', 'b', 'c', 'd', 'e'); 15 | ValidateResult(demoList, demoList.Next.Next, 'a', 'b', 'd', 'e'); 16 | 17 | // Remove first node 18 | var list = ListHelpers.CreateLinkedList(1, 2, 3); 19 | ValidateResult(list, list, 2, 3); 20 | 21 | // Remove middle node 22 | list = ListHelpers.CreateLinkedList(1, 2, 3); 23 | ValidateResult(list, list.Next, 1, 3); 24 | } 25 | 26 | [TestMethod] 27 | public void InvalidInputsTest() 28 | { 29 | // Null node 30 | TestHelpers.AssertExceptionThrown(() => { Question2_3.RemoveNode(null); }, typeof(ArgumentException)); 31 | 32 | // Node without next 33 | var node = new Node(1); 34 | TestHelpers.AssertExceptionThrown(() => { Question2_3.RemoveNode(node); }, typeof(ArgumentException)); 35 | } 36 | 37 | private static void ValidateResult(Node list, Node nodeToRemove, params T[] expectedResult) 38 | where T : IEquatable 39 | { 40 | Question2_3.RemoveNode(nodeToRemove); 41 | ListHelpers.ValidateLinkedListContent(list, expectedResult); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Tests/Chapter 2/Test2_4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test2_4 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | var list = ListHelpers.CreateLinkedList(3, 2, 1); 14 | ValidateResult(2, list, 1, 3, 2); 15 | 16 | // No change needed (x is smaller) 17 | list = ListHelpers.CreateLinkedList(1, 2, 3); 18 | ValidateResult(0, list, 1, 2, 3); 19 | 20 | // No change needed (x is larger) 21 | list = ListHelpers.CreateLinkedList(1, 2, 3); 22 | ValidateResult(4, list, 1, 2, 3); 23 | 24 | list = ListHelpers.CreateLinkedList(1, 3, 3, 1); 25 | ValidateResult(2, list, 1, 1, 3, 3); 26 | } 27 | 28 | [TestMethod] 29 | public void EdgeCasesTest() 30 | { 31 | // One node 32 | var list = ListHelpers.CreateLinkedList(1); 33 | ValidateResult(0, list, 1); 34 | 35 | list = ListHelpers.CreateLinkedList(1); 36 | ValidateResult(1, list, 1); 37 | 38 | list = ListHelpers.CreateLinkedList(1); 39 | ValidateResult(2, list, 1); 40 | } 41 | 42 | [TestMethod] 43 | public void InvalidInputsTest() 44 | { 45 | // Null node 46 | TestHelpers.AssertExceptionThrown(() => { Question2_4.PartitionList(null, 3); }, typeof(ArgumentNullException)); 47 | } 48 | 49 | private static void ValidateResult(T x, Node list, params T[] expectedResult) 50 | where T : IEquatable, IComparable 51 | { 52 | var result = Question2_4.PartitionList(list, x); 53 | ListHelpers.ValidateLinkedListContent(result, expectedResult); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Tests/Chapter 2/Test2_5.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Code; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | 7 | namespace Tests 8 | { 9 | [TestClass] 10 | public class Test2_5 11 | { 12 | [TestMethod] 13 | public void BasicTest() 14 | { 15 | // Sample case 16 | // Input: (7 -> 1 -> 6) + (5 -> 9 -> 2). that is, 617 + 295. 17 | // Output: 2 -> 1 -> 9. That is, 912. 18 | Validate(617, 295, 912); 19 | } 20 | 21 | [TestMethod] 22 | public void EdgeCasesTest() 23 | { 24 | // Zero 25 | Validate(42, 0, 42); 26 | 27 | // Last digit is a carry 28 | Validate(9, 9, 18); 29 | 30 | // Different length inputs 31 | Validate(1100, 22, 1122); 32 | } 33 | 34 | [TestMethod] 35 | public void InvalidInputTest() 36 | { 37 | var node = new Node(new Digit(0)); 38 | 39 | // Null node 40 | TestHelpers.AssertExceptionThrown(() => { Question2_5.Add(node, null); }, typeof(ArgumentNullException)); 41 | TestHelpers.AssertExceptionThrown(() => { Question2_5.Add(null, node); }, typeof(ArgumentNullException)); 42 | TestHelpers.AssertExceptionThrown(() => { Question2_5.Add(null, null); }, typeof(ArgumentNullException)); 43 | 44 | TestHelpers.AssertExceptionThrown(() => { Question2_5.AddNotReversed(node, null); }, typeof(ArgumentNullException)); 45 | TestHelpers.AssertExceptionThrown(() => { Question2_5.AddNotReversed(null, node); }, typeof(ArgumentNullException)); 46 | TestHelpers.AssertExceptionThrown(() => { Question2_5.AddNotReversed(null, null); }, typeof(ArgumentNullException)); 47 | } 48 | 49 | private static void Validate(int num1, int num2, int expectedResult) 50 | { 51 | // Reversed 52 | ValidateHelper(num1, num2, expectedResult); 53 | ValidateHelper(num2, num1, expectedResult); 54 | 55 | // Not reversed 56 | ValidateNotReversedHelper(num1, num2, expectedResult); 57 | ValidateNotReversedHelper(num2, num1, expectedResult); 58 | } 59 | 60 | private static void ValidateHelper(int num1, int num2, int expectedResult) 61 | { 62 | var expectedResultArray = CreateList(expectedResult, reversed: true); 63 | var list1 = CreateDigitList(num1, reversed: true); 64 | var list2 = CreateDigitList(num2, reversed: true); 65 | var result = Question2_5.Add(list1, list2); 66 | ListHelpers.ValidateLinkedListContent(result, expectedResultArray.Select(r => new Digit(r)).ToArray()); 67 | } 68 | 69 | private static void ValidateNotReversedHelper(int num1, int num2, int expectedResult) 70 | { 71 | var expectedResultArray = CreateList(expectedResult); 72 | var list1 = CreateDigitList(num1); 73 | var list2 = CreateDigitList(num2); 74 | var result = Question2_5.AddNotReversed(list1, list2); 75 | ListHelpers.ValidateLinkedListContent(result, expectedResultArray.Select(r => new Digit(r)).ToArray()); 76 | } 77 | 78 | private static Node CreateDigitList(int num, bool reversed = false) 79 | { 80 | var result = CreateList(num, reversed); 81 | return ListHelpers.CreateLinkedList(result.Select(item => new Digit(item)).ToArray()); 82 | } 83 | 84 | private static List CreateList(int num, bool reversed = false) 85 | { 86 | var digits = new List(); 87 | 88 | do 89 | { 90 | digits.Add(num % 10); 91 | num /= 10; 92 | } 93 | while (num > 0); 94 | 95 | if (!reversed) 96 | { 97 | digits.Reverse(); 98 | } 99 | 100 | return digits; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /Tests/Chapter 2/Test2_6.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test2_6 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | Validate(true, 1); 14 | Validate(true, 1, 1); 15 | Validate(true, 1, 2, 1); 16 | Validate(true, 1, 2, 2, 1); 17 | 18 | Validate(false, 1, 2); 19 | Validate(false, 1, 2, 3); 20 | Validate(false, 1, 2, 1, 2); 21 | } 22 | 23 | [TestMethod] 24 | public void InvalidInputTest() 25 | { 26 | TestHelpers.AssertExceptionThrown(() => { Question2_6.IsPalindrome(null); }, typeof(ArgumentNullException)); 27 | } 28 | 29 | private static void Validate(bool expectedResult, params int[] values) 30 | { 31 | var head = ListHelpers.CreateLinkedList(values); 32 | Assert.AreEqual(expectedResult, Question2_6.IsPalindrome(head)); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Tests/Chapter 2/Test2_7.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test2_7 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | var list1 = ListHelpers.CreateLinkedList(1, 2, 3); 14 | var list2 = ListHelpers.CreateLinkedList(4, 5, 6); 15 | var intersection = ListHelpers.CreateLinkedList(7, 8, 9); 16 | AddIntersection(list1, list2, intersection); 17 | Validate(list1, list2, intersection); 18 | 19 | // Different sized lists 20 | list1 = ListHelpers.CreateLinkedList(1); 21 | list2 = ListHelpers.CreateLinkedList(2, 3); 22 | intersection = ListHelpers.CreateLinkedList(4, 5, 6); 23 | AddIntersection(list1, list2, intersection); 24 | Validate(list1, list2, intersection); 25 | 26 | // Intersection is last node 27 | list1 = ListHelpers.CreateLinkedList(1, 2); 28 | list2 = ListHelpers.CreateLinkedList(3, 4, 5); 29 | intersection = ListHelpers.CreateLinkedList(6); 30 | AddIntersection(list1, list2, intersection); 31 | Validate(list1, list2, intersection); 32 | 33 | // Repeated values (to ensure references are being computed) 34 | list1 = ListHelpers.CreateLinkedList(1, 3); 35 | list2 = ListHelpers.CreateLinkedList(2, 2, 2); 36 | intersection = ListHelpers.CreateLinkedList(2); 37 | AddIntersection(list1, list2, intersection); 38 | Validate(list1, list2, intersection); 39 | 40 | // No intersection 41 | list1 = ListHelpers.CreateLinkedList(1, 2, 3); 42 | list2 = ListHelpers.CreateLinkedList(4, 5, 6); 43 | Validate(list1, list2, null); 44 | } 45 | 46 | [TestMethod] 47 | public void InvalidInputsTest() 48 | { 49 | var head = new Node(1); 50 | 51 | TestHelpers.AssertExceptionThrown(() => Question2_7.FindIntersection(null, head), typeof(ArgumentNullException)); 52 | TestHelpers.AssertExceptionThrown(() => Question2_7.FindIntersection(head, null), typeof(ArgumentNullException)); 53 | TestHelpers.AssertExceptionThrown(() => Question2_7.FindIntersection(null, null), typeof(ArgumentNullException)); 54 | } 55 | 56 | private static void AddIntersection(Node list1, Node list2, Node intersection) 57 | where T : IEquatable 58 | { 59 | while (list1.Next != null) 60 | { 61 | list1 = list1.Next; 62 | } 63 | 64 | list1.Next = intersection; 65 | 66 | while (list2.Next != null) 67 | { 68 | list2 = list2.Next; 69 | } 70 | 71 | list2.Next = intersection; 72 | } 73 | 74 | private static void Validate(Node list1, Node list2, Node intersection) 75 | where T : IEquatable 76 | { 77 | Assert.IsTrue(ReferenceEquals(intersection, Question2_7.FindIntersection(list1, list2))); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Tests/Chapter 2/Test2_8.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test2_8 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | var list = ListHelpers.CreateLinkedList(1, 2, 3); 14 | var loopStart = AddLoop(list, 4, 5, 6); 15 | Validate(list, loopStart); 16 | 17 | // Loop of size one 18 | list = ListHelpers.CreateLinkedList(1, 2, 3); 19 | loopStart = AddLoop(list, 4); 20 | Validate(list, loopStart); 21 | 22 | // Loop is first item in the list 23 | loopStart = AddLoop(null, 1, 2, 3); 24 | Validate(loopStart, loopStart); 25 | } 26 | 27 | [TestMethod] 28 | public void EdgeCaseTest() 29 | { 30 | var list = ListHelpers.CreateLinkedList(1, 2, 3); 31 | Validate(list, null); 32 | } 33 | 34 | [TestMethod] 35 | public void InvalidInputTest() 36 | { 37 | TestHelpers.AssertExceptionThrown(() => Question2_8.FindLoopStart(null), typeof(ArgumentNullException)); 38 | TestHelpers.AssertExceptionThrown(() => Question2_8.FindLoopStartHareTortoise(null), typeof(ArgumentNullException)); 39 | } 40 | 41 | private static Node AddLoop(Node head, params T[] loop) 42 | where T : IEquatable 43 | { 44 | while (head?.Next != null) 45 | { 46 | head = head.Next; 47 | } 48 | 49 | var loopStart = ListHelpers.CreateLinkedList(loop); 50 | var loopEnd = loopStart; 51 | 52 | while (loopEnd.Next != null) 53 | { 54 | loopEnd = loopEnd.Next; 55 | } 56 | 57 | if (head != null) 58 | { 59 | head.Next = loopStart; 60 | } 61 | 62 | loopEnd.Next = loopStart; 63 | 64 | return loopStart; 65 | } 66 | 67 | private static void Validate(Node head, Node loopStart) 68 | where T : IEquatable 69 | { 70 | Assert.AreEqual(loopStart, Question2_8.FindLoopStart(head)); 71 | Assert.AreEqual(loopStart, Question2_8.FindLoopStartHareTortoise(head)); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Tests/Chapter 3/SortedStackTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Code; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace Tests 7 | { 8 | [TestClass] 9 | public class SortedStackTests 10 | { 11 | [TestMethod] 12 | public void BasicTest() 13 | { 14 | var stack = new SortedStack(); 15 | 16 | PushMany(stack, 1, 3, 7, 6, 2, 9, 4, 0, 8, 5); 17 | Validate(stack, Enumerable.Range(0, 10).ToArray()); 18 | 19 | // Repeated values 20 | PushMany(stack, 2, 1, 3, 2, 2); 21 | Validate(stack, 1, 2, 2, 2, 3); 22 | } 23 | 24 | [TestMethod] 25 | public void InvalidInputTest() 26 | { 27 | var stack = new SortedStack(); 28 | 29 | TestHelpers.AssertExceptionThrown(() => stack.Peek(), typeof(InvalidOperationException)); 30 | TestHelpers.AssertExceptionThrown(() => stack.Pop(), typeof(InvalidOperationException)); 31 | } 32 | 33 | private static void PushMany(SortedStack stack, params T[] values) 34 | where T : IComparable 35 | { 36 | foreach (var value in values) 37 | { 38 | stack.Push(value); 39 | } 40 | } 41 | 42 | private static void Validate(SortedStack stack, params T[] expectedValues) 43 | where T : IComparable 44 | { 45 | foreach (var value in expectedValues) 46 | { 47 | Assert.IsFalse(stack.IsEmpty()); 48 | Assert.AreEqual(value, stack.Pop()); 49 | } 50 | 51 | Assert.IsTrue(stack.IsEmpty()); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Tests/Chapter 3/Test3_2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test3_2 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | var stack = new MinStack(); 14 | 15 | // Build stack 16 | PushAndValidateMin(stack, 1, 1); 17 | PushAndValidateMin(stack, 2, 1); 18 | 19 | // Empty stack 20 | PopAndValidateMin(stack, 2, 1); 21 | Assert.AreEqual(1, stack.Pop()); 22 | 23 | // Build stack 24 | PushAndValidateMin(stack, 3, 3); 25 | PushAndValidateMin(stack, 2, 2); 26 | PushAndValidateMin(stack, 4, 2); 27 | PushAndValidateMin(stack, 1, 1); 28 | 29 | // Empty stack 30 | PopAndValidateMin(stack, 1, 2); 31 | PopAndValidateMin(stack, 4, 2); 32 | PopAndValidateMin(stack, 2, 3); 33 | Assert.AreEqual(3, stack.Pop()); 34 | } 35 | 36 | [TestMethod] 37 | public void InvalidOperationsTest() 38 | { 39 | var stack = new MinStack(); 40 | 41 | TestHelpers.AssertExceptionThrown(() => stack.Min(), typeof(InvalidOperationException)); 42 | TestHelpers.AssertExceptionThrown(() => stack.Pop(), typeof(InvalidOperationException)); 43 | } 44 | 45 | private static void PushAndValidateMin(MinStack stack, T item, T minAfterPush) 46 | where T : IComparable 47 | { 48 | stack.Push(item); 49 | Assert.AreEqual(minAfterPush, stack.Min()); 50 | } 51 | 52 | private static void PopAndValidateMin(MinStack stack, T poppedItem, T minAfterPop) 53 | where T : IComparable 54 | { 55 | Assert.AreEqual(poppedItem, stack.Pop()); 56 | Assert.AreEqual(minAfterPop, stack.Min()); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Tests/Chapter 3/Test3_3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test3_3 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | var stack = new SetOfStacks(); 14 | 15 | const int N = 100; 16 | for (int i = 0; i < 100; i++) 17 | { 18 | stack.Push(i); 19 | } 20 | 21 | for (int i = N; i > 0; i--) 22 | { 23 | Assert.AreEqual(i - 1, stack.Pop()); 24 | } 25 | 26 | stack.Push(0); 27 | Assert.AreEqual(0, stack.Pop()); 28 | } 29 | 30 | [TestMethod] 31 | public void InvalidOperationsTest() 32 | { 33 | var stack = new SetOfStacks(); 34 | 35 | TestHelpers.AssertExceptionThrown(() => stack.Pop(), typeof(InvalidOperationException)); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Tests/Chapter 3/Test3_4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test3_4 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | var queue = new MyQueue(); 14 | 15 | queue.Add(1); 16 | queue.Add(2); 17 | 18 | Assert.AreEqual(1, queue.Remove()); 19 | Assert.AreEqual(2, queue.Remove()); 20 | 21 | queue.Add(3); 22 | Assert.AreEqual(3, queue.Remove()); 23 | 24 | queue.Add(4); 25 | queue.Add(5); 26 | 27 | Assert.AreEqual(4, queue.Remove()); 28 | Assert.AreEqual(5, queue.Remove()); 29 | } 30 | 31 | [TestMethod] 32 | public void InvalidOperationsTest() 33 | { 34 | var queue = new MyQueue(); 35 | 36 | TestHelpers.AssertExceptionThrown(() => queue.Remove(), typeof(InvalidOperationException)); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Tests/Chapter 3/Test3_5.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Code; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | 7 | namespace Tests 8 | { 9 | [TestClass] 10 | public class Test3_5 11 | { 12 | [TestMethod] 13 | public void BasicTest() 14 | { 15 | var stack = CreateStack(1, 4, 5, 3, 2); 16 | Question3_5.SortStack(stack); 17 | Validate(stack, 1, 2, 3, 4, 5); 18 | 19 | // Duplicated values 20 | stack = CreateStack(3, 4, 1, 2, 3); 21 | Question3_5.SortStack(stack); 22 | Validate(stack, 1, 2, 3, 3, 4); 23 | } 24 | 25 | [TestMethod] 26 | public void InvalidInputTest() 27 | { 28 | TestHelpers.AssertExceptionThrown(() => Question3_5.SortStack(null), typeof(ArgumentNullException)); 29 | } 30 | 31 | private static void Validate(Stack stack, params T[] expectedValues) 32 | { 33 | foreach (var value in expectedValues) 34 | { 35 | Assert.IsFalse(stack.Count == 0); 36 | Assert.AreEqual(value, stack.Pop()); 37 | } 38 | 39 | Assert.IsTrue(stack.Count == 0); 40 | } 41 | 42 | private static Stack CreateStack(params T[] stack) 43 | { 44 | var result = new Stack(stack.Length); 45 | stack = stack.Reverse().ToArray(); 46 | 47 | foreach (var item in stack) 48 | { 49 | result.Push(item); 50 | } 51 | 52 | return result; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Tests/Chapter 4/Test4_1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class Test4_1 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | var first = new TreeNode(0); 14 | var second = new TreeNode(0); 15 | ValidateResult(first, second, true); 16 | 17 | second = new TreeNode(1); 18 | ValidateResult(first, second, false); 19 | 20 | first = TreeHelpers.CreateTree(0, 1, 2, 3); 21 | second = TreeHelpers.CreateTree(3, 4, 5); 22 | ValidateResult(first, second, true); 23 | 24 | var tmp1 = TreeHelpers.CreateTree(1, 2, 3); 25 | var tmp2 = TreeHelpers.CreateTree(4, 5, 6); 26 | first = TreeHelpers.CreateTree(7, tmp1, tmp2); 27 | second = new TreeNode(6); 28 | ValidateResult(first, second, true); 29 | } 30 | 31 | [TestMethod] 32 | public void InvalidInputTest() 33 | { 34 | var tree = new TreeNode(0, null); 35 | 36 | TestHelpers.AssertExceptionThrown(() => { Question4_1.AreConnected(null, tree); }, typeof(ArgumentNullException)); 37 | TestHelpers.AssertExceptionThrown(() => { Question4_1.AreConnected(tree, null); }, typeof(ArgumentNullException)); 38 | } 39 | 40 | private static void ValidateResult(TreeNode first, TreeNode second, bool expectedValue) 41 | where T : IEquatable 42 | { 43 | Assert.AreEqual(expectedValue, Question4_1.AreConnected(first, second)); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Tests/Chapter 4/Test4_3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Code; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace Tests 7 | { 8 | [TestClass] 9 | public class Test4_3 10 | { 11 | [TestMethod] 12 | public void BasicTest() 13 | { 14 | // One node 15 | var root = new BinaryTreeNode(0); 16 | var result = new List> 17 | { 18 | ListHelpers.CreateList(0) 19 | }; 20 | ValidateResult(result, root); 21 | 22 | // One node with children 23 | root = TreeHelpers.CreateBinaryTree(0, 1, 2); 24 | result = new List> 25 | { 26 | ListHelpers.CreateList(0), 27 | ListHelpers.CreateList(1, 2) 28 | }; 29 | ValidateResult(result, root); 30 | 31 | // More complex tree 32 | var tmp1 = TreeHelpers.CreateBinaryTree(4, 5, 6); 33 | var tmp2 = TreeHelpers.CreateBinaryTree(7, 8, 9); 34 | var tmp3 = TreeHelpers.CreateBinaryTree(3, tmp1, tmp2); 35 | var tmp4 = TreeHelpers.CreateBinaryTree(2, tmp3, null); 36 | root = TreeHelpers.CreateBinaryTree(0, new BinaryTreeNode(1), tmp4); 37 | result = new List> 38 | { 39 | ListHelpers.CreateList(0), 40 | ListHelpers.CreateList(1, 2), 41 | ListHelpers.CreateList(3), 42 | ListHelpers.CreateList(4, 7), 43 | ListHelpers.CreateList(5, 6, 8, 9) 44 | }; 45 | ValidateResult(result, root); 46 | } 47 | 48 | [TestMethod] 49 | public void InvalidInputTest() 50 | { 51 | TestHelpers.AssertExceptionThrown(() => Question4_3.FindDepths(null), typeof(ArgumentNullException)); 52 | } 53 | 54 | private static void ValidateResult(List> expectedResults, BinaryTreeNode root) 55 | where T : IEquatable 56 | { 57 | var result = Question4_3.FindDepths(root); 58 | 59 | Assert.AreEqual(expectedResults.Count, result.Count); 60 | 61 | for (int i = 0; i < expectedResults.Count; i++) 62 | { 63 | Assert.AreEqual(expectedResults[i].Count, result[i].Count); 64 | 65 | for (int j = 0; j < expectedResults[i].Count; j++) 66 | { 67 | Assert.AreEqual(expectedResults[i][j], result[i][j].Data); 68 | } 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /Tests/Chapter 4/Test4_4.cs: -------------------------------------------------------------------------------- 1 | using Code; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace Tests 5 | { 6 | [TestClass] 7 | public class Test4_4 8 | { 9 | [TestMethod] 10 | public void SingleNode_IsBalanced_ReturnsTrue() 11 | { 12 | // Arrange 13 | var root = new BinaryTreeNode(0); 14 | 15 | // Act 16 | var result = Question4_4.IsBalanced(root); 17 | 18 | // Assert 19 | Assert.IsTrue(result); 20 | } 21 | 22 | [TestMethod] 23 | public void OneLevelDifference_IsBalanced_ReturnsTrue() 24 | { 25 | /* 26 | * 1 27 | * / 28 | * 0 29 | */ 30 | 31 | // Arrange 32 | var left = new BinaryTreeNode(0); 33 | var root = new BinaryTreeNode(1, left, null); 34 | 35 | // Act 36 | var result = Question4_4.IsBalanced(root); 37 | 38 | // Assert 39 | Assert.IsTrue(result); 40 | } 41 | 42 | [TestMethod] 43 | public void CompleteTree_IsBalanced_ReturnsTrue() 44 | { 45 | /* 46 | * 2 47 | * / \ 48 | * 0 1 49 | */ 50 | 51 | // Arrange 52 | var left = new BinaryTreeNode(0); 53 | var right = new BinaryTreeNode(1); 54 | var root = new BinaryTreeNode(2, left, right); 55 | 56 | // Act 57 | var result = Question4_4.IsBalanced(root); 58 | 59 | // Assert 60 | Assert.IsTrue(result); 61 | } 62 | 63 | [TestMethod] 64 | public void UnbalancedTreeAtRoot_IsBalanced_ReturnsFalse() 65 | { 66 | /* 67 | * 2 68 | * / 69 | * 1 70 | * / 71 | * 0 72 | */ 73 | 74 | // Arrange 75 | var left2 = new BinaryTreeNode(0); 76 | var left = new BinaryTreeNode(1, left2, null); 77 | var root = new BinaryTreeNode(2, left, null); 78 | 79 | // Act 80 | var result = Question4_4.IsBalanced(root); 81 | 82 | // Assert 83 | Assert.IsFalse(result); 84 | } 85 | 86 | [TestMethod] 87 | public void UnbalancedTreeAtLowerLevel_IsBalanced_ReturnsFalse() 88 | { 89 | /* 90 | * 6 91 | * / \ 92 | * 2 5 93 | * / \ 94 | * 1 4 95 | * / \ 96 | * 0 3 97 | */ 98 | // Arrange 99 | var left3 = new BinaryTreeNode(0); 100 | var left2 = new BinaryTreeNode(1, left3, null); 101 | var left = new BinaryTreeNode(2, left2, null); 102 | var right3 = new BinaryTreeNode(3); 103 | var right2 = new BinaryTreeNode(4, null, right3); 104 | var right = new BinaryTreeNode(5, null, right2); 105 | var root = new BinaryTreeNode(6, left, right); 106 | 107 | // Act 108 | var result = Question4_4.IsBalanced(root); 109 | 110 | // Assert 111 | Assert.IsFalse(result); 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Tests/Chapter 5/Test5_1.cs: -------------------------------------------------------------------------------- 1 | using Code; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace Tests 5 | { 6 | [TestClass] 7 | public class Test5_1 8 | { 9 | [TestMethod] 10 | public void InsertBits_ReturnsCorrectValue_ForSampleInput() 11 | { 12 | // Arrange 13 | var n = BitHelpers.FromBinaryString("10000000000"); 14 | var m = BitHelpers.FromBinaryString("10011"); 15 | var i = 2; 16 | var j = 6; 17 | var expected = BitHelpers.FromBinaryString("10001001100"); 18 | 19 | // Act 20 | var actual = Question5_1.Insertion(n, m, i, j); 21 | 22 | // Assert 23 | Assert.AreEqual(expected, actual); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Tests/Chapter 5/Tests5_2.cs: -------------------------------------------------------------------------------- 1 | using Code; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace Tests 5 | { 6 | [TestClass] 7 | public class Tests5_2 8 | { 9 | [TestMethod] 10 | public void BinaryToString_ReturnsCorrectValue_ForFiveTenths() 11 | { 12 | // Arrange 13 | var number = 0.5; 14 | var expected = "0.1"; 15 | 16 | // Act 17 | var actual = Question5_2.BinaryToString(number); 18 | 19 | // Assert 20 | Assert.AreEqual(expected, actual); 21 | } 22 | 23 | [TestMethod] 24 | public void BinaryToString_ReturnsCorrectValue_ForTwentyFiveHundreds() 25 | { 26 | // Arrange 27 | var number = 0.25; 28 | var expected = "0.01"; 29 | 30 | // Act 31 | var actual = Question5_2.BinaryToString(number); 32 | 33 | // Assert 34 | Assert.AreEqual(expected, actual); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Tests/Data structures/DigitTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using Code; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace Tests 7 | { 8 | [TestClass] 9 | public class DigitTests 10 | { 11 | [TestMethod] 12 | public void BasicTest() 13 | { 14 | for (int i = 0; i < 10; i++) 15 | { 16 | var digit = new Digit(i); 17 | Assert.AreEqual(i, digit); 18 | } 19 | } 20 | 21 | [TestMethod] 22 | [SuppressMessage("Microsoft.Usage", "CA1806")] 23 | public void InvalidInputTest() 24 | { 25 | // Negative number 26 | TestHelpers.AssertExceptionThrown(() => { new Digit(-1); }, typeof(ArgumentOutOfRangeException)); 27 | 28 | // Multiple digit number 29 | TestHelpers.AssertExceptionThrown(() => { new Digit(10); }, typeof(ArgumentOutOfRangeException)); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Tests/Data structures/NodeTests.cs: -------------------------------------------------------------------------------- 1 | using Code; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace Tests 5 | { 6 | [TestClass] 7 | public class NodeTests 8 | { 9 | [TestMethod] 10 | public void BasicTest() 11 | { 12 | // Add an element 13 | var head = new Node(1); 14 | ListHelpers.ValidateLinkedListContent(head, 1); 15 | 16 | // Add two more elements 17 | head.AppendToTail(2); 18 | head.AppendToTail(3); 19 | ListHelpers.ValidateLinkedListContent(head, 1, 2, 3); 20 | 21 | // Remove the middle element 22 | head = head.DeleteNode(head, 2); 23 | ListHelpers.ValidateLinkedListContent(head, 1, 3); 24 | } 25 | 26 | [TestMethod] 27 | public void RemoveTests() 28 | { 29 | // Add three elements 30 | var head = new Node(1); 31 | head.AppendToTail(2); 32 | head.AppendToTail(3); 33 | ListHelpers.ValidateLinkedListContent(head, 1, 2, 3); 34 | 35 | // Remove the middle one 36 | head = head.DeleteNode(head, 2); 37 | ListHelpers.ValidateLinkedListContent(head, 1, 3); 38 | 39 | // Remove the first one 40 | head = head.DeleteNode(head, 1); 41 | ListHelpers.ValidateLinkedListContent(head, 3); 42 | 43 | // Remove non-existent head 44 | head = head.DeleteNode(head, 4); 45 | ListHelpers.ValidateLinkedListContent(head, 3); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Tests/ListHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Code; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace Tests 7 | { 8 | public static class ListHelpers 9 | { 10 | public static Node CloneList(Node head) 11 | where T : IEquatable 12 | { 13 | if (head == null) 14 | { 15 | return null; 16 | } 17 | 18 | var result = new Node(head.Data); 19 | var curResult = result; 20 | head = head.Next; 21 | 22 | while (head != null) 23 | { 24 | curResult.AppendToTail(head.Data); 25 | curResult = result.Next; 26 | head = head.Next; 27 | } 28 | 29 | return result; 30 | } 31 | 32 | public static Node CreateLinkedList(params T[] values) 33 | where T : IEquatable 34 | { 35 | if (values == null) 36 | { 37 | throw new ArgumentNullException(nameof(values)); 38 | } 39 | 40 | var head = new Node(values[0]); 41 | Node cur = head; 42 | 43 | for (int i = 1; i < values.Length; i++) 44 | { 45 | var next = new Node(values[i]); 46 | cur.Next = next; 47 | cur = cur.Next; 48 | } 49 | 50 | return head; 51 | } 52 | 53 | public static void ValidateLinkedListContent(Node head, params T[] values) 54 | where T : IEquatable 55 | { 56 | if (values == null) 57 | { 58 | throw new ArgumentNullException(nameof(values)); 59 | } 60 | 61 | Assert.IsNotNull(head); 62 | 63 | var numElements = values.Length; 64 | var count = 0; 65 | 66 | while (count < numElements && head != null) 67 | { 68 | Assert.AreEqual(values[count], head.Data); 69 | count++; 70 | head = head.Next; 71 | } 72 | 73 | Assert.IsNull(head); 74 | Assert.AreEqual(numElements, count); 75 | } 76 | 77 | public static List CreateList(params T[] values) 78 | { 79 | return new List(values); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Tests/MatrixHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Tests 4 | { 5 | public static class MatrixHelpers 6 | { 7 | // Creates a two dimensional matrix from a one dimensional input 8 | // Example input: 9 | // 1 2 3 4 5 6 7 8 9 10 | // Example output: 11 | // 1 2 3 12 | // 4 5 6 13 | // 7 8 9 14 | public static T[,] CreateTwoDimensionalMatrix(params T[] list) 15 | { 16 | if (list == null) 17 | { 18 | throw new ArgumentNullException(nameof(list)); 19 | } 20 | 21 | var size = GetMatrixSize(list); 22 | 23 | var result = new T[size, size]; 24 | var counter = 0; 25 | 26 | for (int i = 0; i < size; i++) 27 | { 28 | for (int j = 0; j < size; j++) 29 | { 30 | result[i, j] = list[counter++]; 31 | } 32 | } 33 | 34 | return result; 35 | } 36 | 37 | private static int GetMatrixSize(params T[] list) 38 | { 39 | var length = Math.Sqrt(list.Length); 40 | 41 | if (length % 1 != 0) 42 | { 43 | throw new ArgumentException("Number of elements must be a perfect square to create an NxN matrix", nameof(list)); 44 | } 45 | 46 | return (int)length; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Tests/MeetingScheduler/MeetingSchedulerTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Code; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace Tests 7 | { 8 | [TestClass] 9 | public class MeetingSchedulerTests 10 | { 11 | [TestMethod] 12 | public void SampleTest() 13 | { 14 | // Work day: (8, 17) 15 | // Person1: (8,10), (10, 12), (15,16) 16 | // Person2: (11, 14) 17 | // Result: (14, 15), (16, 17) 18 | var people = new List(); 19 | people.Add(CreatePerson(8, 10, 10, 12, 15, 16)); 20 | people.Add(CreatePerson(11, 14)); 21 | 22 | var results = MeetingScheduler.FindMeetingTimes(8, 17, people); 23 | ValidateResults(results, 14, 15, 16, 17); 24 | } 25 | 26 | private static void ValidateResults(List meetings, params int[] expectedResults) 27 | { 28 | if (meetings.Count * 2 != expectedResults.Length) 29 | { 30 | Assert.Fail("Unexpected number of meetings"); 31 | } 32 | 33 | for (int i = 0; i < meetings.Count; i += 2) 34 | { 35 | Assert.AreEqual(expectedResults[i], meetings[i].StartHour); 36 | Assert.AreEqual(expectedResults[i + 1], meetings[i].EndHour); 37 | } 38 | } 39 | 40 | // Creates a person assuming pairs of meetings (start1, end1, start2, end2...) 41 | private static Person CreatePerson(params int[] meetingHours) 42 | { 43 | if (meetingHours.Length % 2 != 0) 44 | { 45 | throw new ArgumentException("Must provide and even number of meeting hours"); 46 | } 47 | 48 | var schedule = new List(); 49 | 50 | var count = 0; 51 | 52 | while (count < meetingHours.Length) 53 | { 54 | schedule.Add(new Meeting(meetingHours[count], meetingHours[count + 1])); 55 | 56 | count += 2; 57 | } 58 | 59 | return new Person(schedule); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Tests/Misc/CountingIslandsTests.cs: -------------------------------------------------------------------------------- 1 | using Code; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace Tests 5 | { 6 | [TestClass] 7 | public class CountingIslandsTests 8 | { 9 | [TestMethod] 10 | public void CountIslands_WithNoIslands_ReturnsZero() 11 | { 12 | // Arrange 13 | var map = new bool[2, 2]; 14 | 15 | // Act 16 | var actual = CountingIslands.CountIslands(map); 17 | 18 | // Assert 19 | Assert.AreEqual(0, actual); 20 | } 21 | 22 | [TestMethod] 23 | public void CountIslands_WithNoIslandsRectangularMap_ReturnsZero() 24 | { 25 | // Arrange 26 | var map = new bool[2, 1]; 27 | 28 | // Act 29 | var actual = CountingIslands.CountIslands(map); 30 | 31 | // Assert 32 | Assert.AreEqual(0, actual); 33 | } 34 | 35 | [TestMethod] 36 | public void CountIslands_WithOneIsland_ReturnsOne() 37 | { 38 | // Arrange 39 | var map = new bool[2, 2]; 40 | map[0, 0] = true; 41 | 42 | // Act 43 | var actual = CountingIslands.CountIslands(map); 44 | 45 | // Assert 46 | Assert.AreEqual(1, actual); 47 | } 48 | 49 | [TestMethod] 50 | public void CountIslands_WithOneIslandAdjacentSquares_ReturnsOne() 51 | { 52 | // Arrange 53 | var map = new bool[2, 2]; 54 | map[0, 0] = true; 55 | map[0, 1] = true; 56 | 57 | // Act 58 | var actual = CountingIslands.CountIslands(map); 59 | 60 | // Assert 61 | Assert.AreEqual(1, actual); 62 | } 63 | 64 | [TestMethod] 65 | public void CountIslands_WithTwoIslands_ReturnsTwo() 66 | { 67 | // Arrange 68 | var map = new bool[3, 3]; 69 | map[0, 0] = true; 70 | map[2, 2] = true; 71 | 72 | // Act 73 | var actual = CountingIslands.CountIslands(map); 74 | 75 | // Assert 76 | Assert.AreEqual(2, actual); 77 | } 78 | 79 | [TestMethod] 80 | public void CountIslands_WithTwoIslandsDiagonal_ReturnsTwo() 81 | { 82 | // Arrange 83 | var map = new bool[2, 2]; 84 | map[0, 0] = true; 85 | map[1, 1] = true; 86 | 87 | // Act 88 | var actual = CountingIslands.CountIslands(map); 89 | 90 | // Assert 91 | Assert.AreEqual(2, actual); 92 | } 93 | 94 | [TestMethod] 95 | public void CountIslands_WithOneIslandMultipleDirections_ReturnsOne() 96 | { 97 | // Arrange 98 | var map = new bool[3, 3]; 99 | map[0, 0] = true; 100 | map[0, 1] = true; 101 | map[0, 2] = true; 102 | map[1, 0] = true; 103 | map[2, 0] = true; 104 | 105 | // Act 106 | var actual = CountingIslands.CountIslands(map); 107 | 108 | // Assert 109 | Assert.AreEqual(1, actual); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /Tests/Misc/LeastRecentlyUsedCacheTests.cs: -------------------------------------------------------------------------------- 1 | using Code; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | 4 | namespace Tests 5 | { 6 | [TestClass] 7 | public class LeastRecentlyUsedCacheTests 8 | { 9 | private const string KeyOne = "K1"; 10 | private const string ValueOne = "V1"; 11 | private const string KeyTwo = "K2"; 12 | private const string ValueTwo = "V2"; 13 | private const string KeyThree = "K3"; 14 | private const string ValueThree = "V3"; 15 | 16 | [TestMethod] 17 | public void Get_ReturnsCachedItem() 18 | { 19 | // Arrange 20 | var cache = new LeastRecentlyUsedCache(1); 21 | cache.Set(KeyOne, ValueOne); 22 | 23 | // Act 24 | var result = cache.Get(KeyOne); 25 | 26 | // Assert 27 | Assert.AreEqual(ValueOne, result); 28 | } 29 | 30 | [TestMethod] 31 | public void Set_EvictsOldestElement() 32 | { 33 | // Arrange 34 | var cache = new LeastRecentlyUsedCache(1); 35 | cache.Set(KeyOne, ValueOne); 36 | cache.Set(KeyTwo, ValueTwo); 37 | 38 | // Act 39 | var result = cache.Get(KeyOne); 40 | 41 | // Assert 42 | Assert.IsNull(result); 43 | } 44 | 45 | [TestMethod] 46 | public void Get_MovesElementToFrontOfListForEviction() 47 | { 48 | // Arrange 49 | var cache = new LeastRecentlyUsedCache(2); 50 | cache.Set(KeyOne, ValueOne); 51 | cache.Set(KeyTwo, ValueTwo); 52 | cache.Get(KeyOne); 53 | cache.Set(KeyThree, ValueThree); 54 | 55 | // Act 56 | var result = cache.Get(KeyOne); 57 | 58 | // Assert 59 | Assert.AreEqual(ValueOne, result); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Tests/Misc/SubstringSearchTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Code; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class SubstringSearchTests 9 | { 10 | [TestMethod] 11 | public void BasicTest() 12 | { 13 | // Arrange 14 | var toMatch = "abc"; 15 | var toSearch = "_abc_"; 16 | var expected = true; 17 | 18 | // Act 19 | var actual = SubstringSearch.IsSubstring(toMatch, toSearch); 20 | 21 | // Assert 22 | Assert.AreEqual(expected, actual); 23 | } 24 | 25 | [TestMethod] 26 | public void StartsWithMatchTest() 27 | { 28 | // Arrange 29 | var toMatch = "abc"; 30 | var toSearch = "abc_"; 31 | var expected = true; 32 | 33 | // Act 34 | var actual = SubstringSearch.IsSubstring(toMatch, toSearch); 35 | 36 | // Assert 37 | Assert.AreEqual(expected, actual); 38 | } 39 | 40 | [TestMethod] 41 | public void EndsWithMatchTest() 42 | { 43 | // Arrange 44 | var toMatch = "abc"; 45 | var toSearch = "_abc"; 46 | var expected = true; 47 | 48 | // Act 49 | var actual = SubstringSearch.IsSubstring(toMatch, toSearch); 50 | 51 | // Assert 52 | Assert.AreEqual(expected, actual); 53 | } 54 | 55 | [TestMethod] 56 | public void MultipleMatchesTest() 57 | { 58 | // Arrange 59 | var toMatch = "abc"; 60 | var toSearch = "abcabc"; 61 | var expected = true; 62 | 63 | // Act 64 | var actual = SubstringSearch.IsSubstring(toMatch, toSearch); 65 | 66 | // Assert 67 | Assert.AreEqual(expected, actual); 68 | } 69 | 70 | [TestMethod] 71 | public void NoMatchForInvertedStringTest() 72 | { 73 | // Arrange 74 | var toMatch = "abc"; 75 | var toSearch = "cba"; 76 | var expected = false; 77 | 78 | // Act 79 | var actual = SubstringSearch.IsSubstring(toMatch, toSearch); 80 | 81 | // Assert 82 | Assert.AreEqual(expected, actual); 83 | } 84 | 85 | [TestMethod] 86 | public void NoMatchForNonadjacentStringTest() 87 | { 88 | // Arrange 89 | var toMatch = "abc"; 90 | var toSearch = "a_b_c"; 91 | var expected = false; 92 | 93 | // Act 94 | var actual = SubstringSearch.IsSubstring(toMatch, toSearch); 95 | 96 | // Assert 97 | Assert.AreEqual(expected, actual); 98 | } 99 | 100 | [TestMethod] 101 | public void NoMatchForDifferentCasingTest() 102 | { 103 | // Arrange 104 | var toMatch = "abc"; 105 | var toSearch = "ABC"; 106 | var expected = false; 107 | 108 | // Act 109 | var actual = SubstringSearch.IsSubstring(toMatch, toSearch); 110 | 111 | // Assert 112 | Assert.AreEqual(expected, actual); 113 | } 114 | 115 | [TestMethod] 116 | [ExpectedException(typeof(ArgumentException))] 117 | public void ExceptionForNullFirstArgumentTest() 118 | { 119 | // Arrange 120 | string toMatch = null; 121 | var toSearch = "abc"; 122 | 123 | // Act 124 | SubstringSearch.IsSubstring(toMatch, toSearch); 125 | } 126 | 127 | [TestMethod] 128 | [ExpectedException(typeof(ArgumentException))] 129 | public void ExceptionForNullSecondArgumentTest() 130 | { 131 | // Arrange 132 | var toMatch = "abc"; 133 | string toSearch = null; 134 | 135 | // Act 136 | SubstringSearch.IsSubstring(toMatch, toSearch); 137 | } 138 | 139 | [TestMethod] 140 | [ExpectedException(typeof(ArgumentException))] 141 | public void ExceptionForEmptyStringFirstArgumentTest() 142 | { 143 | // Arrange 144 | var toMatch = string.Empty; 145 | var toSearch = "abc"; 146 | 147 | // Act 148 | SubstringSearch.IsSubstring(toMatch, toSearch); 149 | } 150 | 151 | [TestMethod] 152 | [ExpectedException(typeof(ArgumentException))] 153 | public void ExceptionForEmptyStringSecondArgumentTest() 154 | { 155 | // Arrange 156 | var toMatch = "abc"; 157 | var toSearch = string.Empty; 158 | 159 | // Act 160 | SubstringSearch.IsSubstring(toMatch, toSearch); 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /Tests/OverlappingParties/OverlappingPartiesTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Code; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace Tests 7 | { 8 | [TestClass] 9 | public class OverlappingPartiesTests 10 | { 11 | private readonly DateTime _janFirst = new DateTime(2000, 1, 1); 12 | 13 | [TestMethod] 14 | public void FindMostOverlappingParties_WithOneParty_ReturnsStartDateOfFirstParty() 15 | { 16 | // Arrange 17 | var parties = new List 18 | { 19 | new Party(_janFirst, _janFirst.AddDays(1)) 20 | }; 21 | 22 | // Act 23 | var actual = OverlappingParties.FindMostOverlappingParties(parties); 24 | 25 | // Assert 26 | Assert.AreEqual(_janFirst, actual); 27 | } 28 | 29 | [TestMethod] 30 | public void FindMostOverlappingParties_WithOneOverlap_ReturnsStartDateOfOverlap() 31 | { 32 | // Arrange 33 | var parties = new List 34 | { 35 | new Party(_janFirst, _janFirst.AddDays(2)), 36 | new Party(_janFirst.AddDays(1), _janFirst.AddDays(3)) 37 | }; 38 | 39 | // Act 40 | var actual = OverlappingParties.FindMostOverlappingParties(parties); 41 | 42 | // Assert 43 | Assert.AreEqual(_janFirst.AddDays(1), actual); 44 | } 45 | 46 | [TestMethod] 47 | public void FindMostOverlappingParties_WithOverlapAtSameTime_DoesNotReturnOverlap() 48 | { 49 | // Arrange 50 | var parties = new List 51 | { 52 | new Party(_janFirst, _janFirst.AddDays(1)), 53 | new Party(_janFirst.AddDays(1), _janFirst.AddDays(2)) 54 | }; 55 | 56 | // Act 57 | var actual = OverlappingParties.FindMostOverlappingParties(parties); 58 | 59 | // Assert 60 | Assert.AreEqual(_janFirst, actual); 61 | } 62 | 63 | [TestMethod] 64 | public void FindMostOverlappingParties_WithSameDate_ReturnsStartDateOfParties() 65 | { 66 | // Arrange 67 | var parties = new List 68 | { 69 | new Party(_janFirst, _janFirst.AddDays(1)), 70 | new Party(_janFirst, _janFirst.AddDays(1)) 71 | }; 72 | 73 | // Act 74 | var actual = OverlappingParties.FindMostOverlappingParties(parties); 75 | 76 | // Assert 77 | Assert.AreEqual(_janFirst, actual); 78 | } 79 | 80 | [TestMethod] 81 | public void FindMostOverlappingParties_WithTwoDisjointPartyGroups_ReturnsStartDateOfLargerGroup() 82 | { 83 | // Arrange 84 | var parties = new List 85 | { 86 | new Party(_janFirst, _janFirst.AddDays(1)), 87 | new Party(_janFirst.AddDays(2), _janFirst.AddDays(4)), 88 | new Party(_janFirst.AddDays(3), _janFirst.AddDays(5)) 89 | }; 90 | 91 | // Act 92 | var actual = OverlappingParties.FindMostOverlappingParties(parties); 93 | 94 | // Assert 95 | Assert.AreEqual(_janFirst.AddDays(3), actual); 96 | } 97 | 98 | [TestMethod] 99 | public void FindMostOverlappingParties_NullInput_ThrowsException() 100 | { 101 | // Arrange 102 | 103 | // Act 104 | void action() => OverlappingParties.FindMostOverlappingParties(null); 105 | 106 | // Assert 107 | TestHelpers.AssertExceptionThrown(action, typeof(ArgumentNullException)); 108 | } 109 | 110 | [TestMethod] 111 | public void FindMostOverlappingParties_NoParties_ThrowsException() 112 | { 113 | // Arrange 114 | var parties = new List(); 115 | 116 | // Act 117 | void action() => OverlappingParties.FindMostOverlappingParties(parties); 118 | 119 | // Assert 120 | TestHelpers.AssertExceptionThrown(action, typeof(ArgumentException)); 121 | } 122 | 123 | [TestMethod] 124 | public void FindMostOverlappingParties_InvalidPartyDates_ThrowsException() 125 | { 126 | // Arrange 127 | var parties = new List 128 | { 129 | new Party(_janFirst, _janFirst.AddDays(-1)) 130 | }; 131 | 132 | // Act 133 | void action() => OverlappingParties.FindMostOverlappingParties(parties); 134 | 135 | // Assert 136 | TestHelpers.AssertExceptionThrown(action, typeof(ArgumentOutOfRangeException)); 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("Tests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("Tests")] 12 | [assembly: AssemblyCopyright("Copyright © 2016")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("ef9b082c-2cad-4ebf-8bbd-635fe8144620")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Tests/TestHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | public static class TestHelpers 8 | { 9 | // This is used instead of the ExpectedException test attribute to allow testing multiple exceptions 10 | // in the same test 11 | [SuppressMessage("Microsoft.Design", "CA1031")] 12 | public static void AssertExceptionThrown(Action action, Type type) 13 | { 14 | if (action == null) 15 | { 16 | throw new ArgumentNullException(nameof(action)); 17 | } 18 | 19 | try 20 | { 21 | action(); 22 | } 23 | catch (Exception e) 24 | { 25 | if (e.GetType() != type) 26 | { 27 | Assert.Fail("Unexpected type of exception={0}", e.GetType()); 28 | } 29 | 30 | return; 31 | } 32 | 33 | Assert.Fail("No exception thrown"); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Tests/TreeHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Linq; 4 | using Code; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | 7 | namespace Tests 8 | { 9 | public static class TreeHelpers 10 | { 11 | public static TreeNode CreateTree(T data, params T[] children) 12 | where T : IEquatable 13 | { 14 | var childrenNodes = children?.Select(c => new TreeNode(c, null)); 15 | return new TreeNode(data, childrenNodes); 16 | } 17 | 18 | public static TreeNode CreateTree(T data, params TreeNode[] children) 19 | where T : IEquatable 20 | { 21 | return new TreeNode(data, children); 22 | } 23 | 24 | [SuppressMessage("Microsoft.Design", "CA1062")] 25 | public static void AssertTreesAreEqual(TreeNode first, TreeNode second) 26 | where T : IEquatable 27 | { 28 | if (first == null && second == null) 29 | { 30 | return; 31 | } 32 | 33 | Assert.IsNotNull(first); 34 | Assert.IsNotNull(second); 35 | Assert.AreEqual(first.Data, second.Data); 36 | 37 | if (first.Children == null && second.Children == null) 38 | { 39 | return; 40 | } 41 | 42 | Assert.IsTrue(first != null && second != null && first.Children.Length == second.Children.Length); 43 | 44 | for (int i = 0; i < first.Children.Length; i++) 45 | { 46 | AssertTreesAreEqual(first.Children[i], second.Children[i]); 47 | } 48 | } 49 | 50 | [SuppressMessage("Microsoft.Design", "CA1062")] 51 | public static void AssertBinaryTreesAreEqual(BinaryTreeNode first, BinaryTreeNode second) 52 | where T : IEquatable 53 | { 54 | if (first == null && second == null) 55 | { 56 | return; 57 | } 58 | 59 | Assert.IsNotNull(first); 60 | Assert.IsNotNull(second); 61 | Assert.AreEqual(first.Data, second.Data); 62 | 63 | AssertBinaryTreesAreEqual(first.Left, second.Left); 64 | AssertBinaryTreesAreEqual(first.Right, second.Right); 65 | } 66 | 67 | public static BinaryTreeNode CreateBinaryTree(T data) 68 | where T : IEquatable 69 | { 70 | return new BinaryTreeNode(data); 71 | } 72 | 73 | public static BinaryTreeNode CreateBinaryTree(T data, T left, T right) 74 | where T : IEquatable 75 | { 76 | return CreateBinaryTree(data, new BinaryTreeNode(left), new BinaryTreeNode(right)); 77 | } 78 | 79 | public static BinaryTreeNode CreateBinaryTree(T data, BinaryTreeNode left, BinaryTreeNode right) 80 | where T : IEquatable 81 | { 82 | return new BinaryTreeNode(data, left, right); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | --------------------------------------------------------------------------------