Skip to content

Commit 4d96d32

Browse files
committed
Update
1 parent 2e23dc3 commit 4d96d32

File tree

7 files changed

+291
-5
lines changed

7 files changed

+291
-5
lines changed

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
This repository contains solutions for a couple hundred DSA problems from the [LeetCode](https://leetcode.com/)
66
website.
77

8-
Problems are separated into 18 topics:
8+
Problems are separated into 19 topics:
99

1010
| | Topic | Package |
1111
|---:|:--------------------|:-----------------------------------------------|
@@ -23,10 +23,11 @@ Problems are separated into 18 topics:
2323
| 12 | Linked List | [linked_list](src/linked_list) |
2424
| 13 | Math | [math](src/math) |
2525
| 14 | Matrix | [matrix](src/matrix) |
26-
| 15 | Recursion | [recursion](src/recursion) |
27-
| 16 | Stack | [stack](src/stack) |
28-
| 17 | String | [string](src/string) |
29-
| 18 | Trie | [trie](src/trie) |
26+
| 15 | Quad Tree | [quad_tree](src/quad_tree) |
27+
| 16 | Recursion | [recursion](src/recursion) |
28+
| 17 | Stack | [stack](src/stack) |
29+
| 18 | String | [string](src/string) |
30+
| 19 | Trie | [trie](src/trie) |
3031

3132
## Good places to start your own LeetCode journey
3233

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package graph;
2+
3+
/**
4+
* Description: https://leetcode.com/problems/number-of-increasing-paths-in-a-grid
5+
* Difficulty: Hard
6+
* Time complexity: O(m * n)
7+
* Space complexity: O(m * n)
8+
*/
9+
public class NumberOfIncreasingPathsInGrid {
10+
11+
// since the answer may be too large, return it modulo 10^9 + 7
12+
private static final int MOD = 1_000_000_007;
13+
14+
private final int[][] directions = new int[][]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
15+
16+
public int countPaths(int[][] grid) {
17+
int[][] cache = new int[grid.length][grid[0].length];
18+
int count = 0;
19+
20+
for (int i = 0; i < grid.length; i++) {
21+
for (int j = 0; j < grid[0].length; j++) {
22+
count += dfs(grid, cache, i, j);
23+
count %= MOD;
24+
}
25+
}
26+
27+
return count;
28+
}
29+
30+
private int dfs(int[][] grid, int[][] cache, int x, int y) {
31+
if (cache[x][y] != 0) return cache[x][y];
32+
33+
int count = 1;
34+
for (int[] dir : directions) {
35+
int x1 = x + dir[0];
36+
int y1 = y + dir[1];
37+
38+
if (x1 >= 0 && y1 >= 0 && x1 < grid.length && y1 < grid[0].length
39+
&& grid[x1][y1] < grid[x][y]) {
40+
count += dfs(grid, cache, x1, y1);
41+
count %= MOD;
42+
}
43+
}
44+
45+
cache[x][y] = count;
46+
return count;
47+
}
48+
}

src/math/DetectSquares.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package math;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
/**
7+
* Description: https://leetcode.com/problems/detect-squares
8+
* Difficulty: Medium
9+
* Time complexity: O(1) for add(), O(n) for count()
10+
* Space complexity: O(n)
11+
*/
12+
public class DetectSquares {
13+
14+
private static class CustomDetectSquares {
15+
16+
private final Map<Point, Integer> points;
17+
18+
public CustomDetectSquares() {
19+
this.points = new HashMap<>();
20+
}
21+
22+
public void add(int[] point) {
23+
points.merge(new Point(point[0], point[1]), 1, Integer::sum);
24+
}
25+
26+
public int count(int[] point) {
27+
int count = 0;
28+
for (Point p : points.keySet()) {
29+
// find points that form a square diagonal with the query point
30+
if (Math.abs(point[0] - p.x) != Math.abs(point[1] - p.y)
31+
// skip zero area squares
32+
|| point[0] == p.x
33+
|| point[1] == p.y) {
34+
continue;
35+
}
36+
37+
count += points.get(p) // diagonal point
38+
* points.getOrDefault(new Point(p.x, point[1]), 0) // top left point
39+
* points.getOrDefault(new Point(point[0], p.y), 0); // bottom right
40+
}
41+
42+
return count;
43+
}
44+
45+
private record Point(int x, int y) {
46+
}
47+
}
48+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package quad_tree;
2+
3+
/**
4+
* Description: https://leetcode.com/problems/construct-quad-tree
5+
* Difficulty: Medium
6+
* Time complexity: O(n^2)
7+
* Space complexity: O(log n)
8+
*/
9+
public class ConstructQuadTree {
10+
11+
public Node construct(int[][] grid) {
12+
return construct(grid, 0, 0, grid.length);
13+
}
14+
15+
private Node construct(int[][] grid, int x, int y, int length) {
16+
if (length == 1) {
17+
// single cell is always a leaf
18+
return new Node(grid[x][y] == 1, true);
19+
}
20+
21+
Node topLeft = construct(grid, x, y, length / 2);
22+
Node topRight = construct(grid, x, y + length / 2, length / 2);
23+
Node bottomLeft = construct(grid, x + length / 2, y, length / 2);
24+
Node bottomRight = construct(grid, x + length / 2, y + length / 2, length / 2);
25+
26+
if (topLeft.isLeaf && topRight.isLeaf && bottomLeft.isLeaf && bottomRight.isLeaf
27+
&& topLeft.val == topRight.val
28+
&& bottomLeft.val == bottomRight.val
29+
&& topLeft.val == bottomLeft.val) {
30+
// all children are leaves with the same value -> root is leaf
31+
return new Node(topLeft.val, true);
32+
}
33+
34+
return new Node(false, false, topLeft, topRight, bottomLeft, bottomRight);
35+
}
36+
37+
private static class Node {
38+
39+
private final boolean val;
40+
private final boolean isLeaf;
41+
private final Node topLeft;
42+
private final Node topRight;
43+
private final Node bottomLeft;
44+
private final Node bottomRight;
45+
46+
public Node(boolean val, boolean isLeaf) {
47+
this.val = val;
48+
this.isLeaf = isLeaf;
49+
this.topLeft = null;
50+
this.topRight = null;
51+
this.bottomLeft = null;
52+
this.bottomRight = null;
53+
}
54+
55+
public Node(boolean val, boolean isLeaf, Node topLeft, Node topRight, Node bottomLeft, Node bottomRight) {
56+
this.val = val;
57+
this.isLeaf = isLeaf;
58+
this.topLeft = topLeft;
59+
this.topRight = topRight;
60+
this.bottomLeft = bottomLeft;
61+
this.bottomRight = bottomRight;
62+
}
63+
}
64+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package recursion;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
/**
7+
* Description: https://leetcode.com/problems/distinct-subsequences
8+
* Difficulty: Hard
9+
* Time complexity: O(m * n)
10+
* Space complexity: O(m * n)
11+
*/
12+
public class DistinctSubsequences {
13+
14+
public int numDistinct(String s, String t) {
15+
if (s.length() < t.length()) return 0;
16+
return count(s, t, 0, 0, new HashMap<>());
17+
}
18+
19+
private int count(
20+
String original,
21+
String target,
22+
int originalPointer,
23+
int targetPointer,
24+
Map<String, Integer> memo) {
25+
if (originalPointer == original.length()
26+
|| targetPointer == target.length()
27+
|| original.length() - originalPointer < target.length() - targetPointer) {
28+
return targetPointer == target.length() ? 1 : 0;
29+
}
30+
31+
String key = originalPointer + ":" + targetPointer;
32+
if (memo.containsKey(key)) return memo.get(key);
33+
34+
// skip and move on
35+
int count = count(original, target, originalPointer + 1, targetPointer, memo);
36+
37+
// pick and move on
38+
if (original.charAt(originalPointer) == target.charAt(targetPointer)) {
39+
count += count(original, target, originalPointer + 1, targetPointer + 1, memo);
40+
}
41+
42+
memo.put(key, count);
43+
return count;
44+
}
45+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package recursion;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
/**
7+
* Description: https://leetcode.com/problems/regular-expression-matching
8+
* Difficulty: Hard
9+
* Time complexity: O(m * n)
10+
* Space complexity: O(m * n)
11+
*/
12+
public class RegularExpressionMatching {
13+
14+
public boolean isMatch(String s, String p) {
15+
return isMatch(s, p, 0, 0, new HashMap<>());
16+
}
17+
18+
private boolean isMatch(
19+
String original,
20+
String pattern,
21+
int originalPointer,
22+
int patternPointer,
23+
Map<String, Boolean> memo) {
24+
if (patternPointer == pattern.length()) return originalPointer == original.length();
25+
26+
String key = originalPointer + ":" + patternPointer;
27+
if (memo.containsKey(key)) return memo.get(key);
28+
29+
// check if current char matches
30+
boolean isCurrentMatch = originalPointer < original.length()
31+
&& (pattern.charAt(patternPointer) == original.charAt(originalPointer)
32+
|| pattern.charAt(patternPointer) == '.');
33+
34+
boolean result;
35+
if (isStarNext(pattern, patternPointer)) {
36+
// '*' means 0 or more matches -> we check for zero (skip) or for one (pick)
37+
boolean skip = isMatch(original, pattern, originalPointer, patternPointer + 2, memo);
38+
boolean pick = isCurrentMatch
39+
&& isMatch(original, pattern, originalPointer + 1, patternPointer, memo);
40+
result = skip || pick;
41+
} else {
42+
// move on
43+
result = isCurrentMatch
44+
&& isMatch(original, pattern, originalPointer + 1, patternPointer + 1, memo);
45+
}
46+
47+
memo.put(key, result);
48+
return result;
49+
}
50+
51+
private static boolean isStarNext(String pattern, int patternPointer) {
52+
return patternPointer + 1 < pattern.length() && pattern.charAt(patternPointer + 1) == '*';
53+
}
54+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package string;
2+
3+
/**
4+
* Description: https://leetcode.com/problems/greatest-common-divisor-of-strings
5+
* Difficulty: Easy
6+
* Time complexity: O(min(m, n) * (m + n))
7+
* Space complexity: O(min(m, n))
8+
*/
9+
public class GreatestCommonDivisorOfStrings {
10+
11+
public String gcdOfStrings(String str1, String str2) {
12+
for (int i = Math.min(str1.length(), str2.length()); i > 0; i--) {
13+
if (isGcd(str1, str2, i)) return str1.substring(0, i);
14+
}
15+
16+
return "";
17+
}
18+
19+
private boolean isGcd(String str1, String str2, int i) {
20+
if (str1.length() % i != 0 || str2.length() % i != 0) return false;
21+
22+
String candidate = str1.substring(0, i);
23+
return str1.replaceAll(candidate, "").isEmpty()
24+
&& str2.replaceAll(candidate, "").isEmpty();
25+
}
26+
}

0 commit comments

Comments
 (0)