├── .gitignore
├── README.md
├── pom.xml
└── src
└── main
└── java
└── dev
└── milikkan
└── grind75
├── BestTimeToBuyAndSellStock.java
├── BinarySearch.java
├── FirstBadVersion.java
├── FloodFill.java
├── ImplementQueueUsingStacks.java
├── InvertBinaryTree.java
├── LinkedListCycle.java
├── LowestCommonAncestorOfABinarySearchTree.java
├── MergeTwoSortedLists.java
├── RansomNote.java
├── TwoSum.java
├── ValidAnagram.java
├── ValidPalindrome.java
├── ValidParentheses.java
└── balancedbinarytree
└── Solution.java
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | !.mvn/wrapper/maven-wrapper.jar
3 | !**/src/main/**/target/
4 | !**/src/test/**/target/
5 |
6 | ### IntelliJ IDEA ###
7 | .idea/encodings.xml
8 | .idea/vcs.xml
9 | .idea/misc.xml
10 | .idea/modules.xml
11 | .idea/jarRepositories.xml
12 | .idea/compiler.xml
13 | .idea/libraries/
14 | *.iws
15 | *.iml
16 | *.ipr
17 |
18 | ### Eclipse ###
19 | .apt_generated
20 | .classpath
21 | .factorypath
22 | .project
23 | .settings
24 | .springBeans
25 | .sts4-cache
26 |
27 | ### NetBeans ###
28 | /nbproject/private/
29 | /nbbuild/
30 | /dist/
31 | /nbdist/
32 | /.nb-gradle/
33 | build/
34 | !**/src/main/**/build/
35 | !**/src/test/**/build/
36 |
37 | ### VS Code ###
38 | .vscode/
39 |
40 | ### Mac OS ###
41 | .DS_Store
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LeetCode - Grind75 Challenge
2 |
3 | This is the repo which contains my solutions to the **Grind75** study plan questions. I am using Java for this round.
4 |
5 | [Grind75](https://www.techinterviewhandbook.org/grind75) is a study plan that contains 75 LeetCode questions in an increasing difficulty order.
6 |
7 | My aim is to solve all the problems in 8 weeks, which is the default plan. (Number of questions and weekly time allocation can be customized but I chose to stick with the default one.)
8 |
9 | ## Main Challenge rules:
10 | 1. Solve at least one question every day.
11 | 2. Finish the plan at most in 8 weeks.
12 | 3. Tweet about your progress daily.
13 |
14 | ### Other rules:
15 | - On the first round, try to solve without taking any hints or looking at other solutions.
16 | - If you cannot come up with an optimized solution, try to do best. You can ignore time constraints in this case as long as all the tests pass.
17 | - If you get stuck on a question (for example trying for more than an hour), don't waste any more time and take a quick hint by looking at the example solutions, then try to solve again.
18 |
19 | ### Questions solve so far
20 | | Day | Date | Question | LeetCode link | My solution |
21 | |---|--------------|-------|---------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
22 | | 1 | Nov 7, 2022 |Two Sum| [LeetCode](https://leetcode.com/problems/two-sum) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/d6851fe91c2c5c938604f531827c2aa4fecaea07/src/main/java/dev/milikkan/grind75/TwoSum.java) |
23 | | 2 | Nov 8, 2022 |Valid Parentheses| [LeetCode](https://leetcode.com/problems/valid-parentheses/) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/main/src/main/java/dev/milikkan/grind75/ValidParentheses.java) |
24 | | 3 | Nov 9, 2022 |Merge Two Sorted Lists| [LeetCode](https://leetcode.com/problems/merge-two-sorted-lists/) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/main/src/main/java/dev/milikkan/grind75/MergeTwoSortedLists.java) |
25 | | | |Best Time to Buy and Sell Stock| [LeetCode](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/main/src/main/java/dev/milikkan/grind75/BestTimeToBuyAndSellStock.java) |
26 | | 4 | Nov 10, 2022 |Valid Palindrome| [LeetCode](https://leetcode.com/problems/valid-palindrome/) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/main/src/main/java/dev/milikkan/grind75/ValidPalindrome.java) |
27 | | | |Invert Binary Tree|[LeetCode](https://leetcode.com/problems/invert-binary-tree/) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/main/src/main/java/dev/milikkan/grind75/InvertBinaryTree.java) |
28 | | 5 | Nov 11, 2022 |Valid Anagram|[LeetCode](https://leetcode.com/problems/valid-anagram/) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/main/src/main/java/dev/milikkan/grind75/ValidAnagram.java) |
29 | | | |Binary Search|[LeetCode](https://leetcode.com/problems/binary-search/) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/main/src/main/java/dev/milikkan/grind75/BinarySearch.java) |
30 | | 6 | Nov 12, 2022 |Flood Fill|[LeetCode](https://leetcode.com/problems/flood-fill/) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/main/src/main/java/dev/milikkan/grind75/FloodFill.java) |
31 | | | |Lowest Common Ancestor of a Binary Search Tree|[LeetCode](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/main/src/main/java/dev/milikkan/grind75/LowestCommonAncestorOfABinarySearchTree.java) |
32 | | 7 | Nov 13, 2022 |Balanced Binary Tree|[LeetCode](https://leetcode.com/problems/balanced-binary-tree/) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/main/src/main/java/dev/milikkan/grind75/balancedbinarytree/Solution.java) |
33 | | | |Linked List Cycle|[LeetCode](https://leetcode.com/problems/linked-list-cycle/) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/main/src/main/java/dev/milikkan/grind75/LinkedListCycle.java) |
34 | | 8 | Nov 14, 2022 |Implement Queue using Stacks|[LeetCode](https://leetcode.com/problems/implement-queue-using-stacks/) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/main/src/main/java/dev/milikkan/grind75/ImplementQueueUsingStacks.java) |
35 | | 9 | Nov 15, 2022 | First Bad Version|[LeetCode](https://leetcode.com/problems/first-bad-version/) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/main/src/main/java/dev/milikkan/grind75/FirstBadVersion.java) |
36 | | | | Ransom Note|[LeetCode](https://leetcode.com/problems/ransom-note/) | [Java code](https://github.com/milikkan/grind75-leetcode/blob/main/src/main/java/dev/milikkan/grind75/RansomNote.java) |
37 |
38 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | dev.milikkan
8 | grind75
9 | 1.0-SNAPSHOT
10 |
11 |
12 | 17
13 | 17
14 | UTF-8
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/BestTimeToBuyAndSellStock.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75;
2 |
3 | // problem link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock/
4 | public class BestTimeToBuyAndSellStock {
5 | // time: O(n)
6 | // space: O(1)
7 | public static int maxProfit(int[] prices) {
8 | int minPrice = 0;
9 | int maxPrice = 0;
10 | int profit;
11 | int maxProfit = 0;
12 |
13 | while (minPrice < prices.length - 1 && maxPrice < prices.length - 1) {
14 | if (prices[maxPrice + 1] < prices[maxPrice] && prices[maxPrice + 1] <= prices[minPrice]) {
15 | maxPrice = maxPrice + 1;
16 | minPrice = maxPrice;
17 | } else {
18 | maxPrice = maxPrice + 1;
19 | profit = prices[maxPrice] - prices[minPrice];
20 | if (profit > maxProfit) maxProfit = profit;
21 | }
22 | }
23 | return maxProfit;
24 | }
25 |
26 | public static void main(String[] args) {
27 | int[] prices1 = {7, 1, 5, 3, 6, 4};
28 | System.out.println(maxProfit(prices1)); // 5
29 |
30 | int[] prices2 = {7, 6, 4, 3, 1};
31 | System.out.println(maxProfit(prices2)); // 0
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/BinarySearch.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75;
2 |
3 | // problem link: https://leetcode.com/problems/binary-search/
4 | public class BinarySearch {
5 | // time: O(log n)
6 | // space: O(1)
7 | public static int search(int[] nums, int target) {
8 | int minIndex = 0;
9 | int maxIndex = nums.length - 1;
10 |
11 | while (minIndex <= maxIndex) {
12 | int middleIndex = (maxIndex + minIndex) / 2;
13 | if (nums[middleIndex] == target) {
14 | return middleIndex;
15 | } else if (nums[middleIndex] < target) {
16 | minIndex = middleIndex + 1;
17 | } else {
18 | maxIndex = middleIndex - 1;
19 | }
20 | }
21 |
22 | return -1;
23 | }
24 |
25 | public static void main(String[] args) {
26 | int[] nums1 = {-1, 0, 3, 5, 9, 12, 25, 63};
27 | int target1 = 25;
28 |
29 | int[] nums2 = {-1, 0, 3, 5, 9, 12};
30 | int target2 = 2;
31 |
32 | int[] nums3 = {2, 5};
33 | int target3 = 2;
34 |
35 | int[] nums4 = {1};
36 | int target4 = 1;
37 |
38 | System.out.println(search(nums1, target1)); // 4
39 | System.out.println(search(nums2, target2)); // -1
40 | System.out.println(search(nums3, target3)); // 0
41 | System.out.println(search(nums4, target4)); // 0
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/FirstBadVersion.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75;
2 |
3 | // problem link: https://leetcode.com/problems/first-bad-version/
4 | public class FirstBadVersion {
5 | private int badVersion;
6 |
7 | // time: O(logn)
8 | // space: O(1)
9 | // using Binary Search
10 | public int firstBadVersion(int n) {
11 | if (isBadVersion(1)) return 1;
12 |
13 | long left = 1;
14 | long right = n;
15 |
16 | while (left < right) {
17 | // using long to prevent integer overflow
18 | long middle = (left + right) / 2;
19 | boolean isBad = isBadVersion((int) middle);
20 |
21 | if (isBad) right = middle;
22 | else left = middle;
23 |
24 | if (right - left == 1) return (int) right;
25 | }
26 | return (int) right;
27 | }
28 |
29 | public static void main(String[] args) {
30 | FirstBadVersion fbv = new FirstBadVersion();
31 | fbv.setBadVersion(4);
32 | System.out.println(fbv.firstBadVersion(5)); // 4
33 |
34 | fbv.setBadVersion(1);
35 | System.out.println(fbv.firstBadVersion(1)); // 1
36 | }
37 |
38 | public void setBadVersion(int version) {
39 | this.badVersion = version;
40 | }
41 |
42 | public boolean isBadVersion(int version) {
43 | return version == this.badVersion;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/FloodFill.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75;
2 |
3 | import java.util.LinkedList;
4 |
5 | // problem link: https://leetcode.com/problems/flood-fill/
6 | public class FloodFill {
7 | // time: O(n)
8 | // space: O(n)
9 | public static int[][] floodFill(int[][] image, int sr, int sc, int color) {
10 | LinkedList nodes = new LinkedList<>();
11 | nodes.offer(new Node(sr, sc));
12 | int initialColor = image[sr][sc];
13 | if (initialColor == color) return image;
14 |
15 | while (!nodes.isEmpty()) {
16 | Node current = nodes.poll();
17 | int x = current.x;
18 | int y = current.y;
19 | image[x][y] = color;
20 |
21 | if (x >= 1 && image[x - 1][y] == initialColor) {
22 | nodes.offer(new Node(x - 1, y));
23 | }
24 | if (y >= 1 && image[x][y - 1] == initialColor) {
25 | nodes.offer(new Node(x, y - 1));
26 | }
27 | if (y < image[x].length - 1 && image[x][y + 1] == initialColor) {
28 | nodes.offer(new Node(x, y + 1));
29 | }
30 | if (x < image.length - 1 && image[x + 1][y] == initialColor) {
31 | nodes.offer(new Node(x + 1, y));
32 | }
33 | }
34 | return image;
35 | }
36 |
37 | public static void main(String[] args) {
38 | int[][] image1 = {
39 | {1, 1, 1},
40 | {1, 1, 0},
41 | {1, 0, 1}
42 | };
43 | int sr1 = 1;
44 | int sc1 = 1;
45 | int color1 = 2;
46 |
47 | int[][] result1 = floodFill(image1, sr1, sc1, color1);
48 | printImage(result1);
49 |
50 | int[][] image2 = {
51 | {0, 0, 0},
52 | {0, 0, 0}
53 | };
54 | int sr2 = 0;
55 | int sc2 = 0;
56 | int color2 = 0;
57 |
58 | int[][] result2 = floodFill(image2, sr2, sc2, color2);
59 | printImage(result2);
60 | }
61 |
62 | private static void printImage(int[][] image) {
63 | for (int[] row : image) {
64 | for (int num : row) {
65 | System.out.print(num + " ");
66 | }
67 | System.out.println();
68 | }
69 | System.out.println("---------");
70 | }
71 | }
72 |
73 | class Node {
74 | int x;
75 | int y;
76 |
77 | public Node(int x, int y) {
78 | this.x = x;
79 | this.y = y;
80 | }
81 | }
82 |
83 | /*
84 | - create a queue
85 | - offer root node (sr, sc)
86 | - check following
87 | - sr - 1 sc
88 | - sr, sc - 1
89 | - sr, sc + 1
90 | - sr + 1, sc
91 | - if sr = 0 -> dont do sr -1
92 | - if sc = 0 -> dont do sc -1
93 | - if sr = image.len - 1 -> dont do sr
94 | - if sc = image[sr].len -> dont do sc
95 | - if sr, sc != original color -> dont do sr, sc
96 | - else offet the node to the queue
97 | - stop if the queue is empty
98 | */
99 |
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/ImplementQueueUsingStacks.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75;
2 |
3 | import java.util.ArrayDeque;
4 | import java.util.Deque;
5 |
6 | // problem link: https://leetcode.com/problems/implement-queue-using-stacks/
7 | public class ImplementQueueUsingStacks {
8 | public static void main(String[] args) {
9 | MyQueue queue1 = new MyQueue();
10 | queue1.push(1);
11 | System.out.println(queue1); // [1]
12 |
13 | queue1.push(2);
14 | System.out.println(queue1); // [1, 2]
15 |
16 | System.out.println(queue1.peek()); // 1
17 | System.out.println(queue1); // [1, 2]
18 |
19 | System.out.println(queue1.pop()); // 1
20 | System.out.println(queue1);// [2]
21 |
22 | System.out.println(queue1.empty()); // false
23 |
24 | MyQueue queue2 = new MyQueue();
25 | System.out.println(queue2.peek()); // null
26 | }
27 | }
28 |
29 | class MyQueue {
30 | private final Deque stackForQueue;
31 | private final Deque stackForSwap;
32 |
33 | public MyQueue() {
34 | stackForQueue = new ArrayDeque<>();
35 | stackForSwap = new ArrayDeque<>();
36 | }
37 |
38 | public void push(int x) {
39 | while (!stackForQueue.isEmpty()) {
40 | stackForSwap.push(stackForQueue.pop());
41 | }
42 |
43 | stackForQueue.push(x);
44 |
45 | while (!stackForSwap.isEmpty()) {
46 | stackForQueue.push(stackForSwap.pop());
47 | }
48 | }
49 |
50 | public Integer pop() {
51 | return stackForQueue.pop();
52 | }
53 |
54 | public Integer peek() {
55 | return stackForQueue.peek();
56 | }
57 |
58 | public boolean empty() {
59 | return stackForQueue.isEmpty();
60 | }
61 |
62 | @Override
63 | public String toString() {
64 | return stackForQueue.toString();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/InvertBinaryTree.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75;
2 |
3 | import java.util.LinkedList;
4 |
5 | // problem link: https://leetcode.com/problems/invert-binary-tree/
6 | public class InvertBinaryTree {
7 |
8 | // time: O(n)
9 | // space: O(n)
10 | // traverse method: BFS
11 | public static TreeNode invertTree(TreeNode root) {
12 | if (root == null) return null;
13 |
14 | LinkedList treeNodes = new LinkedList<>();
15 | treeNodes.offer(root);
16 |
17 | while (!treeNodes.isEmpty()) {
18 | TreeNode current = treeNodes.poll();
19 |
20 | TreeNode temp = current.left;
21 | current.left = current.right;
22 | current.right = temp;
23 |
24 | if (current.left != null) treeNodes.offer(current.left);
25 | if (current.right != null) treeNodes.offer(current.right);
26 | }
27 |
28 | return root;
29 | }
30 |
31 | public static void main(String[] args) {
32 | TreeNode tree1 = new TreeNode(2, new TreeNode(1), new TreeNode(3));
33 |
34 | TreeNode tree2 = new TreeNode(4,
35 | new TreeNode(2, new TreeNode(1), new TreeNode(3)),
36 | new TreeNode(7, new TreeNode(6), new TreeNode(9)));
37 |
38 | TreeNode tree3 = null;
39 |
40 | printTreeBFS(invertTree(tree1)); // 2 3 1
41 | printTreeBFS(invertTree(tree2)); // 4 7 2 9 6 3 1
42 | printTreeBFS(invertTree(tree3)); // -
43 | }
44 |
45 | private static void printTreeBFS(TreeNode root) {
46 | if (root == null) return;
47 |
48 | LinkedList treeQueue = new LinkedList<>();
49 | treeQueue.offer(root);
50 |
51 | while (!treeQueue.isEmpty()) {
52 | TreeNode current = treeQueue.poll();
53 | System.out.print(current.val + " ");
54 |
55 | if (current.left != null) treeQueue.offer(current.left);
56 | if (current.right != null) treeQueue.offer(current.right);
57 | }
58 | System.out.println();
59 | }
60 | }
61 |
62 | class TreeNode {
63 | int val;
64 | TreeNode left;
65 | TreeNode right;
66 |
67 | TreeNode() {}
68 | TreeNode(int val) { this.val = val; }
69 | TreeNode(int val, TreeNode left, TreeNode right) {
70 | this.val = val;
71 | this.left = left;
72 | this.right = right;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/LinkedListCycle.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75;
2 |
3 | // problem link: https://leetcode.com/problems/linked-list-cycle/
4 | public class LinkedListCycle {
5 | // time: O(n)
6 | // space: O(1)
7 | // solved using Floyd's Tortoise and Hare Algorithm
8 | public static boolean hasCycle(ListNode head) {
9 | var back = head;
10 | var forward = head;
11 |
12 | while (forward != null && forward.next != null) {
13 | forward = forward.next.next;
14 | back = back.next;
15 | if (back == forward) return true;
16 | }
17 |
18 | return false;
19 | }
20 |
21 | public static void main(String[] args) {
22 | var list1Three = new ListNode(3);
23 | var list1Two = new ListNode(2);
24 | var list1Zero = new ListNode(0);
25 | var list1MinusFour = new ListNode(-4);
26 |
27 | list1Three.next = list1Two;
28 | list1Two.next = list1Zero;
29 | list1Zero.next = list1MinusFour;
30 | list1MinusFour.next = list1Two;
31 |
32 | System.out.println(hasCycle(list1Three)); // true
33 |
34 | var list2One = new ListNode(1);
35 | var list2Two = new ListNode(2);
36 | list2One.next = list2Two;
37 | list2Two.next = list2One;
38 |
39 | System.out.println(hasCycle(list2One)); // true
40 |
41 | var list3One = new ListNode(1);
42 | var list3MinusTwo = new ListNode(-2);
43 | list3One.next = list3MinusTwo;
44 | System.out.println(hasCycle(list3One)); // false
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/LowestCommonAncestorOfABinarySearchTree.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75;
2 |
3 | // problem link: https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/
4 | public class LowestCommonAncestorOfABinarySearchTree {
5 | // time: O(logn)
6 | // space: O(logn)
7 | public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
8 | if (p.val < root.val && q.val < root.val) {
9 | return lowestCommonAncestor(root.left, p, q);
10 | }
11 |
12 | if (p.val > root.val && q.val > root.val) {
13 | return lowestCommonAncestor(root.right, p, q);
14 | }
15 | return root;
16 | }
17 |
18 | public static void main(String[] args) {
19 | TreeNode six = new TreeNode(6);
20 | TreeNode two = new TreeNode(2);
21 | TreeNode eight = new TreeNode(8);
22 | TreeNode zero = new TreeNode(0);
23 | TreeNode four = new TreeNode(4);
24 | TreeNode seven = new TreeNode(7);
25 | TreeNode nine = new TreeNode(9);
26 | TreeNode three = new TreeNode(3);
27 | TreeNode five = new TreeNode(5);
28 | // construct tree1
29 | six.left = two;
30 | six.right = eight;
31 | two.left = zero;
32 | two.right = four;
33 | four.left = three;
34 | four.right = five;
35 | eight.left = seven;
36 | eight.right = nine;
37 |
38 | System.out.println(lowestCommonAncestor(six, two, eight).val); // 6
39 | System.out.println(lowestCommonAncestor(six, two, four).val); // 2
40 | }
41 | }
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/MergeTwoSortedLists.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75;
2 |
3 | // problem link: https://leetcode.com/problems/merge-two-sorted-lists/
4 | public class MergeTwoSortedLists {
5 | // time: O(n)
6 | // space: O(n)
7 | public static ListNode mergeTwoLists(ListNode list1, ListNode list2) {
8 | ListNode pointer1= list1;
9 | ListNode pointer2 = list2;
10 |
11 | if (pointer1 == null) return pointer2;
12 | if (pointer2 == null) return pointer1;
13 |
14 | ListNode result = new ListNode();
15 | ListNode rp = result;
16 |
17 | while (true) {
18 | if (pointer1.val == pointer2.val) {
19 | rp.val = pointer1.val;
20 | rp.next = new ListNode();
21 | rp = rp.next;
22 | rp.val = pointer2.val;
23 | pointer1 = pointer1.next;
24 | pointer2 = pointer2.next;
25 | } else if (pointer1.val < pointer2.val) {
26 | rp.val = pointer1.val;
27 | pointer1 = pointer1.next;
28 | } else {
29 | rp.val = pointer2.val;
30 | pointer2 = pointer2.next;
31 | }
32 |
33 | if (pointer1 == null) {
34 | if (pointer2 != null) rp.next = pointer2;
35 | break;
36 | }
37 | if (pointer2 == null) {
38 | rp.next = pointer1;
39 | break;
40 | }
41 |
42 | rp.next = new ListNode();
43 | rp = rp.next;
44 |
45 | }
46 | return result;
47 | }
48 |
49 | public static void main(String[] args) {
50 | ListNode list1 = new ListNode(1,
51 | new ListNode(2,
52 | new ListNode(4)));
53 |
54 | ListNode list2 = new ListNode(1,
55 | new ListNode(3,
56 | new ListNode(4)));
57 |
58 | ListNode list3 = new ListNode(5,
59 | new ListNode(7));
60 |
61 | ListNode list4 = null;
62 |
63 | ListNode result = mergeTwoLists(list1, list2);
64 | printNodeList(result); // should print 1 2 3 4
65 |
66 | result = mergeTwoLists(list1, list3);
67 | printNodeList(result); // should print 1 2 4 5 7
68 |
69 | result = mergeTwoLists(list3, list4);
70 | printNodeList(result); // should print 5 7
71 |
72 | }
73 |
74 | private static void printNodeList(ListNode list) {
75 | ListNode node = list;
76 |
77 | while (node != null) {
78 | System.out.print(node.val + " ");
79 | node = node.next;
80 | }
81 | System.out.println();
82 | }
83 | }
84 |
85 | class ListNode {
86 | int val;
87 | ListNode next;
88 | ListNode() {}
89 | ListNode(int val) { this.val = val; }
90 | ListNode(int val, ListNode next) { this.val = val; this.next = next; }
91 | }
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/RansomNote.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | // problem link: https://leetcode.com/problems/ransom-note/
7 | public class RansomNote {
8 | // first solution
9 | // time: O(n)
10 | // space: O(n)
11 | public boolean canConstruct1(String ransomNote, String magazine) {
12 | if (ransomNote.length() > magazine.length()) {
13 | return false;
14 | }
15 |
16 | Map letterCounts = new HashMap<>();
17 | for (char letter : magazine.toCharArray()) {
18 | letterCounts.compute(letter, (k, v) -> (v == null) ? 1 : v + 1);
19 | }
20 |
21 | for (char letter : ransomNote.toCharArray()) {
22 | if (!letterCounts.containsKey(letter) || letterCounts.get(letter) == 0) {
23 | return false;
24 | } else {
25 | letterCounts.computeIfPresent(letter, (k, v) -> v - 1);
26 | }
27 | }
28 | return true;
29 | }
30 |
31 | // second solution
32 | // time: O(n)
33 | // space: O(1)
34 | public boolean canConstruct2(String ransomNote, String magazine) {
35 | if (ransomNote.length() > magazine.length()) {
36 | return false;
37 | }
38 |
39 | int[] letterCounts = new int[26];
40 | for (char letter : magazine.toCharArray()) {
41 | letterCounts[letter - 'a'] += 1;
42 | }
43 |
44 | for (char letter : ransomNote.toCharArray()) {
45 | letterCounts[letter - 'a'] -= 1;
46 | if (letterCounts[letter - 'a'] == -1) {
47 | return false;
48 | }
49 | }
50 | return true;
51 | }
52 |
53 | public static void main(String[] args) {
54 | RansomNote ransomNote = new RansomNote();
55 | System.out.println(ransomNote.canConstruct1("a", "b")); // false
56 | System.out.println(ransomNote.canConstruct1("aa", "ab")); // false
57 | System.out.println(ransomNote.canConstruct1("aa", "aab")); // true
58 |
59 | System.out.println(ransomNote.canConstruct2("a", "b")); // false
60 | System.out.println(ransomNote.canConstruct2("aa", "ab")); // false
61 | System.out.println(ransomNote.canConstruct2("aa", "aab")); // true
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/TwoSum.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | // https://leetcode.com/problems/two-sum/
7 | public class TwoSum {
8 | // time: O(n)
9 | // space: O(n)
10 | public static int[] twoSum(int[] nums, int target) {
11 | Map found = new HashMap<>();
12 |
13 | for (int idx = 0; idx < nums.length; idx++) {
14 | int current = nums[idx];
15 | int lookingFor = target - current;
16 | if (found.containsKey(lookingFor)) {
17 | return new int[]{idx, found.get(lookingFor)};
18 | }
19 | found.put(current, idx);
20 | }
21 | return new int[0];
22 | }
23 |
24 | public static void main(String[] args) {
25 | int[] nums1 = {2, 7, 11, 15};
26 | int target1 = 9;
27 | for (int num : twoSum(nums1, target1)) System.out.print(num + " ");
28 | System.out.println();
29 |
30 | int[] nums2 = {3, 2, 4};
31 | int target2 = 6;
32 | for (int num : twoSum(nums2, target2)) System.out.print(num + " ");
33 | System.out.println();
34 |
35 | int[] nums3 = {3, 3, 3, 2};
36 | int target3 = 5;
37 | for (int num : twoSum(nums3, target3)) System.out.print(num + " ");
38 | System.out.println();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/ValidAnagram.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75;
2 |
3 | // problem link: https://leetcode.com/problems/valid-anagram/
4 | public class ValidAnagram {
5 | // time: O(n)
6 | // space: O(1)
7 | public static boolean isAnagram(String s, String t) {
8 | if (s.length() != t.length()) return false;
9 |
10 | char[] lettersS = new char[26];
11 | char[] lettersT = new char[26];
12 |
13 | for (int index = 0; index < s.length(); index++) {
14 | int letterPositionS = s.charAt(index) - 'a';
15 | lettersS[letterPositionS]++;
16 |
17 | int letterPositionT = t.charAt(index) - 'a';
18 | lettersT[letterPositionT]++;
19 | }
20 |
21 | for (int i = 0; i <= 25; i++) {
22 | if (lettersS[i] != lettersT[i]) return false;
23 | }
24 |
25 | return true;
26 | }
27 |
28 | public static void main(String[] args) {
29 | String s1 = "anagram";
30 | String t1 = "nagaram";
31 |
32 | System.out.println(isAnagram(s1, t1)); // true
33 |
34 | String s2 = "rat";
35 | String t2 = "car";
36 | System.out.println(isAnagram(s2, t2)); // false
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/ValidPalindrome.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75;
2 |
3 | // problem link: https://leetcode.com/problems/valid-palindrome/
4 | public class ValidPalindrome {
5 | // time: O(n)
6 | // space: O(1)
7 | public static boolean isPalindrome(String s) {
8 | int leftIndex = 0;
9 | int rightIndex = s.length() - 1;
10 |
11 | while (leftIndex < rightIndex) {
12 | if (!Character.isLetterOrDigit(s.charAt(leftIndex))) {
13 | leftIndex++;
14 | continue;
15 | }
16 | if (!Character.isLetterOrDigit(s.charAt(rightIndex))) {
17 | rightIndex--;
18 | continue;
19 | }
20 | if (Character.toLowerCase(s.charAt(leftIndex)) != Character.toLowerCase(s.charAt(rightIndex))) {
21 | return false;
22 | }
23 | leftIndex++;
24 | rightIndex--;
25 | }
26 | return true;
27 | }
28 |
29 | public static void main(String[] args) {
30 | String s1 = "A man, a plan, a canal: Panama";
31 | String s2 = "race a car";
32 | String s3 = " ";
33 |
34 | System.out.println(isPalindrome(s1)); // true
35 | System.out.println(isPalindrome(s2)); // false
36 | System.out.println(isPalindrome(s3)); // true
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/ValidParentheses.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75;
2 |
3 | import java.util.ArrayDeque;
4 | import java.util.Deque;
5 | import java.util.Map;
6 |
7 | // problem link: https://leetcode.com/problems/valid-parentheses/
8 | public class ValidParentheses {
9 | // time: O(n)
10 | // space: O(n)
11 | public static boolean isValid(String s) {
12 | Map pairs = Map.of(
13 | ')', '(',
14 | ']', '[',
15 | '}', '{'
16 | );
17 |
18 | Deque stack = new ArrayDeque<>();
19 |
20 | for (char ch : s.toCharArray()) {
21 | if (!pairs.containsKey(ch)) {
22 | stack.push(ch);
23 | } else if (!stack.isEmpty() && stack.peek() == pairs.get(ch)) {
24 | stack.pop();
25 | } else {
26 | return false;
27 | }
28 | }
29 | return stack.isEmpty();
30 | }
31 |
32 | public static void main(String[] args) {
33 | String s1 = "()";
34 | System.out.println(isValid(s1));
35 |
36 | String s2 = "()[]{}";
37 | System.out.println(isValid(s2));
38 |
39 | String s3 = "(])";
40 | System.out.println(isValid(s3));
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/dev/milikkan/grind75/balancedbinarytree/Solution.java:
--------------------------------------------------------------------------------
1 | package dev.milikkan.grind75.balancedbinarytree;
2 |
3 | // problem link: https://leetcode.com/problems/balanced-binary-tree/
4 | public class Solution {
5 | // time: O(n)
6 | // space: O(n)
7 | public static boolean isBalanced(TreeNode root) {
8 | return traverseDFS(root).isBalanced;
9 | }
10 |
11 | private static NodeInfo traverseDFS(TreeNode root) {
12 | if (root == null) {
13 | return new NodeInfo(true, 0);
14 | }
15 |
16 | NodeInfo left = traverseDFS(root.left);
17 | NodeInfo right = traverseDFS(root.right);
18 |
19 | boolean isBalanced = left.isBalanced &&
20 | right.isBalanced &&
21 | Math.abs(left.level - right.level) <= 1;
22 |
23 | return new NodeInfo(isBalanced, 1 + Math.max(left.level, right.level));
24 | }
25 |
26 | public static void main(String[] args) {
27 | var tree1 = new TreeNode(3,
28 | new TreeNode(9),
29 | new TreeNode(20,
30 | new TreeNode(15),
31 | new TreeNode(7))
32 | );
33 |
34 | var tree2 = new TreeNode(1,
35 | new TreeNode(2,
36 | new TreeNode(3,
37 | new TreeNode(4),
38 | new TreeNode(4)),
39 | new TreeNode(3)),
40 | new TreeNode(2)
41 | );
42 |
43 | TreeNode tree3 = null;
44 |
45 | System.out.println(isBalanced(tree1)); // true
46 | System.out.println(isBalanced(tree2)); // false
47 | System.out.println(isBalanced(tree3)); // true
48 | }
49 | }
50 |
51 | class TreeNode {
52 | int val;
53 | TreeNode left;
54 | TreeNode right;
55 |
56 | TreeNode() {
57 | }
58 |
59 | TreeNode(int val) {
60 | this.val = val;
61 | }
62 |
63 | TreeNode(int val, TreeNode left, TreeNode right) {
64 | this.val = val;
65 | this.left = left;
66 | this.right = right;
67 | }
68 | }
69 |
70 | class NodeInfo {
71 | boolean isBalanced;
72 | int level;
73 |
74 | public NodeInfo(boolean isBalanced, int level) {
75 | this.isBalanced = isBalanced;
76 | this.level = level;
77 | }
78 | }
--------------------------------------------------------------------------------