├── .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