Skip to content

Commit 94732cd

Browse files
committed
Updated 4 solutions
1 parent 2191fd1 commit 94732cd

File tree

6 files changed

+67
-76
lines changed

6 files changed

+67
-76
lines changed

Chp. 04 - Trees and Graphs/_4_08_First_Common_Ancestor/FirstCommonAncestor.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@
1111
// 2) Recursive O(n) Favorite
1212

1313
public class FirstCommonAncestor {
14-
/* Solution 0: If Binary Search Tree, can go down the tree from the root to see where we need to diverge paths */
14+
// Solution 0: If Binary Search Tree, can go down the tree from the root to see where we need to diverge paths */
1515

16-
/* Book Solution 1: If we have links to parents, we can save all of node1's parents (ancestors) in a HashSet
17-
* and then see if node2's parents (ancestors) match any of those */
16+
// Book Solution 1: If we have links to parents, we can save all of node1's parents (ancestors) in a HashSet
17+
// and then see if node2's parents (ancestors) match any of those
1818

19-
/* Solution 2 - from: http://www.programcreek.com/2014/07/leetcode-lowest-common-ancestor-of-a-binary-tree-java/ */
19+
// Solution 2
2020
public static TreeNode commonAnc(TreeNode root, TreeNode p, TreeNode q) {
21+
return dfs(root, p, q);
22+
}
23+
24+
private static TreeNode dfs(TreeNode root, TreeNode p, TreeNode q) {
2125
if (root == null) {
2226
return null;
2327
} else if (root == p || root == q) {

Chp. 04 - Trees and Graphs/_4_10_Check_Subtree/CheckSubtree.java

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,8 @@
22

33
import common.TreeNode;
44

5-
// Tests if one tree is subtree of another
6-
//
7-
// Solution Runtime Preference
8-
// ------------------------------------------------------------------
9-
// 1) Preorder Traversal See analysis at bottom Worth mentioning
10-
// 2) Recursive search See analysis at bottom Favorite
11-
125
public class CheckSubtree {
13-
/* Solution 1
14-
* - Book says if T1's preorder traversal is substring of T2's preorder traversal,
15-
* and same is true for inorder traversals, then T2 is substring of T1
16-
* - During implementation, we can insert dummy "0" for nulls. This is necessary
17-
* to distinguish the 2 trees in book with duplicate values.
18-
*/
196

20-
/**************/
21-
/* Solution 2 */
22-
/**************/
237
public static boolean containsTree(TreeNode t1, TreeNode t2) {
248
if (t2 == null) { // the empty tree is always a subtree. We do this
259
// check here to avoid doing it every time in subTree.
@@ -56,11 +40,6 @@ public static boolean matchTree(TreeNode p, TreeNode q) {
5640
// Runtimes:
5741
// Let t1 have n nodes and t2 have m nodes
5842
//
59-
// ---------- Solution 1
60-
// Time Complexity: O(n + m) since .isSubstring() is linear time complexity
61-
// Space Complexity: O(n + m) since we copy the trees
62-
//
63-
// ---------- Solution 2
6443
// Time Complexity:
6544
// - O(nm) worst case, but average case is much better since matchTree() usually returns
6645
// false immediately, so it's O(n + km) where k is number of occurrences of T2's root in T1
Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,43 @@
11
package _16_18_Pattern_Matching;
22

33
// Algorithm:
4-
// 0) If pattern is all the same letter (aaaaa... or bbbbb...), treat it as a special case.
5-
// 1) Invert pattern (if necessary) to have it start with "a" instead of "b"
6-
// 2) count numAs, numBs
7-
// 3) try maxLengthA = 1 up to max it could validly be
4+
// 1) If pattern is all the same letter (aaaaa... or bbbbb...), treat it as a special case.
5+
// 2) Invert pattern (if necessary) to have it start with "a" instead of "b"
6+
// 3) count numAs, numBs
7+
// 4) try maxLengthA = 1 up to max it could validly be
88
// - for each maxLengthA, calculate maxLengthB
99
// - use a helper function: checkMatch(String value, String pattern, int aLength, int bLength)
1010

1111
public class PatternMatching {
1212

13-
public static boolean matches(String value, String pattern) {
14-
/* Special case: all same character in pattern */
15-
if (pattern.indexOf('a') == -1 || pattern.indexOf('b') == -1) {
16-
return value.length() % pattern.length() == 0; // wrong. must check if pattern properly repeats in value.
13+
public static boolean matches(String str, String pattern) {
14+
if (str == null || pattern == null || pattern.length() > str.length()) {
15+
return false;
16+
} else if (pattern.length() == 0) {
17+
return str.length() == 0;
18+
} else if (pattern.indexOf('a') == -1 || pattern.indexOf('b') == -1) {
19+
return checkMatchRepeatingWord(str, pattern);
1720
}
1821

19-
pattern = invert(pattern);
22+
pattern = invertIfNecessary(pattern);
2023
int numAs = countOf(pattern, 'a');
2124
int numBs = pattern.length() - numAs;
22-
int maxLengthA = value.length() / numAs;
25+
int maxLengthA = str.length() / numAs;
2326
for (int lengthA = 1; lengthA <= maxLengthA; lengthA++) {
24-
int charsForB = value.length() - lengthA * numAs;
27+
int charsForB = str.length() - lengthA * numAs;
2528
if (charsForB % numBs != 0) {
2629
continue;
2730
}
2831
int lengthB = charsForB / numBs;
29-
if (checkMatch(value, pattern, lengthA, lengthB)) {
32+
if (checkMatch(str, pattern, lengthA, lengthB)) {
3033
return true;
3134
}
3235
}
3336
return false;
3437
}
3538

36-
/* Changes pattern (if necessary) to start with 'a' instead of 'b'. Example: bbaba becomes aabab */
37-
private static String invert(String pattern) {
39+
// Changes pattern (if necessary) to start with 'a' instead of 'b'. Example: bbaba becomes aabab
40+
private static String invertIfNecessary(String pattern) {
3841
if (pattern.charAt(0) == 'a') {
3942
return pattern;
4043
}
@@ -59,22 +62,33 @@ private static int countOf(String str, char ch) {
5962
return count;
6063
}
6164

62-
private static boolean checkMatch(String value, String pattern, int aLength, int bLength) {
63-
/* Grab the 2 words matching "a" and "b" */
65+
private static boolean checkMatchRepeatingWord(String str, String pattern) {
66+
int wordLength = str.length() / pattern.length();
67+
String word = str.substring(0, wordLength);
68+
for (int i = 0; i < str.length(); i += word.length()) {
69+
if (!str.substring(i, i + word.length()).equals(word)) {
70+
return false;
71+
}
72+
}
73+
return true;
74+
}
75+
76+
private static boolean checkMatch(String str, String pattern, int aLength, int bLength) {
77+
// Grab the 2 words matching "a" and "b"
6478
int firstBinPattern = pattern.indexOf('b');
65-
int firstBinValue = firstBinPattern * aLength;
66-
String aWord = value.substring(0, aLength);
67-
String bWord = value.substring(firstBinValue, firstBinValue + bLength);
79+
int firstBinValue = firstBinPattern * aLength;
80+
String aWord = str.substring(0, aLength);
81+
String bWord = str.substring(firstBinValue, firstBinValue + bLength);
6882

6983
int i = 0;
7084
for (int j = 0; j < pattern.length(); j++) {
7185
if (pattern.charAt(j) == 'a') {
72-
if (!value.substring(i, i + aLength).equals(aWord)) {
86+
if (!str.substring(i, i + aLength).equals(aWord)) {
7387
return false;
7488
}
7589
i += aLength;
7690
} else if (pattern.charAt(j) == 'b') {
77-
if (!value.substring(i, i + bLength).equals(bWord)) {
91+
if (!str.substring(i, i + bLength).equals(bWord)) {
7892
return false;
7993
}
8094
i += bLength;
@@ -85,3 +99,4 @@ private static boolean checkMatch(String value, String pattern, int aLength, int
8599
}
86100

87101
// Time Complexity: O(n^2)
102+
// Space Complexity: O(n)

Chp. 16 - More Problems (Moderate)/_16_18_Pattern_Matching/Tester.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ public static void main(String[] args) {
55
System.out.println("*** Test 16.18: Pattern Matching");
66
test("catcatgocatgo", "aabab");
77
test("catcatgocatgo", "bab");
8-
8+
test("foodfoodfood", "a");
9+
test("foodfoodfood", "aa");
10+
test("foodfoodfood", "aaa");
911
}
1012

1113
private static void test(String value, String pattern) {

Chp. 17 - More Problems (Hard)/_17_09_Kth_Multiple/KthMultiple.java

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,33 @@
11
package _17_09_Kth_Multiple;
22

3-
import java.util.ArrayDeque;
3+
// Different than book's solution. Algorithm is Method 2 from: https://www.geeksforgeeks.org/ugly-numbers/
44

55
public class KthMultiple {
6-
public static int getKthMagicNumber(int k) { // assuming "k" counts from 1...
7-
if (k < 1) {
6+
public static int getKthMagicNumber(int k) {
7+
if (k < 0) {
88
return -1;
99
}
1010

11-
/* Use each deque as a queue */
12-
ArrayDeque<Integer> q3 = new ArrayDeque<>();
13-
ArrayDeque<Integer> q5 = new ArrayDeque<>();
14-
ArrayDeque<Integer> q7 = new ArrayDeque<>();
11+
int[] magic = new int[k];
12+
magic[0] = 1;
1513

16-
q3.addLast(3);
17-
q5.addLast(5);
18-
q7.addLast(7);
14+
int i3 = 0;
15+
int i5 = 0;
16+
int i7 = 0;
1917

20-
int val = 0;
21-
for (int i = 1; i <= k; i++) {
22-
int v3 = q3.peek();
23-
int v5 = q5.peek();
24-
int v7 = q7.peek();
25-
val = Math.min(v3, Math.min(v5, v7)); // minimum of 3 values
26-
/* We only add certain multiples to the queues (based on trick from book) to avoid duplicates */
27-
if (val == v3) {
28-
q3.removeFirst();
29-
q3.addLast(3 * val);
30-
q5.addLast(5 * val);
31-
} else if (val == v5) {
32-
q5.removeFirst();
33-
q5.addLast(5 * val);
34-
} else if (val == v7) {
35-
q7.removeFirst();
18+
for (int i = 1; i < k; i++) {
19+
magic[i] = Math.min(magic[i3] * 3, Math.min(magic[i5] * 5, magic[i7] * 7));
20+
if (magic[i] == magic[i3] * 3) {
21+
i3++;
22+
}
23+
if (magic[i] == magic[i5] * 5) {
24+
i5++;
25+
}
26+
if (magic[i] == magic[i7] * 7) {
27+
i7++;
3628
}
37-
q7.addLast(7 * val);
3829
}
39-
return val;
30+
return magic[k-1];
4031
}
4132
}
4233

Chp. 17 - More Problems (Hard)/_17_09_Kth_Multiple/Tester.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ public class Tester {
44
public static void main(String[] args) {
55
System.out.println("*** Test 17.9: Kth Multiple\n");
66
System.out.print("Magic numbers:");
7-
for (int i = 1; i <= 6; i++) {
7+
for (int i = 1; i <= 10; i++) {
88
System.out.print(" " + KthMultiple.getKthMagicNumber(i));
99
}
1010
}

0 commit comments

Comments
 (0)