diff --git a/3sum/dohyeon2.java b/3sum/dohyeon2.java new file mode 100644 index 0000000000..c4cd128337 --- /dev/null +++ b/3sum/dohyeon2.java @@ -0,0 +1,55 @@ +import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; + +class Solution { + // TC: O(n^2) + // SC: O(n^2) + public List> threeSum(int[] nums) { + List> answer = new ArrayList>(); + + // Sort the array to use two-pointer technique. + Arrays.sort(nums); + + // Exclude the last two elements from the loop + // since the two pointers are involved in the iteration. + for (int i = 0; i < nums.length - 2; i++) { + if (i - 1 >= 0 && nums[i] == nums[i - 1]) { + // Skip if this number is the same as the previous one, + // so that we can avoid duplicate triplets. + continue; + } + + int left = i + 1; + int right = nums.length - 1; + + while (left < right) { + int sum = nums[i] + nums[left] + nums[right]; + if (sum == 0) { + ArrayList list = new ArrayList<>( + Arrays.asList(nums[i], nums[left], nums[right])); + answer.add(list); + + // According to the problem, we need to avoid duplicate triplets. + // Therefore, this loop is needed. + while (left < right && nums[left] == nums[left + 1]) { + left++; + } + while (left < right && nums[right] == nums[right - 1]) { + right--; + } + + left++; + right--; + } else if (sum < 0) { + left++; + } else { + right--; + } + } + + } + + return answer; + } +} diff --git a/climbing-stairs/dohyeon2.java b/climbing-stairs/dohyeon2.java new file mode 100644 index 0000000000..a915ba17e3 --- /dev/null +++ b/climbing-stairs/dohyeon2.java @@ -0,0 +1,32 @@ +class Solution { + // TC: O(n) + // SC: O(1) + public int climbStairs(int n) { + if (n < 3) { + // If n is less than 3 there are n ways. + return n; + } + + // There is one way to reach the first stair. + int nMinus2 = 1; + // There are two ways to reach the second stair. + int nMinus1 = 2; + + int nZero = nMinus1 + nMinus2; + + for (int step = 3; step <= n; step++) { + // To reach the third stair, it must come from the first stair or the second + // stair. + // The number of ways to reach the nth stair is the sum of those of the (n-1)th + // stair and those of the (n-2)th stair. + nZero = nMinus1 + nMinus2; + + nMinus2 = nMinus1; + nMinus1 = nZero; + } + + // A separate variable name is used to distinguish between nZero and nMinus1 so + // that the nth value is explicit + return nZero; + } +} diff --git a/product-of-array-except-self/dohyeon2.java b/product-of-array-except-self/dohyeon2.java new file mode 100644 index 0000000000..e851e6dd17 --- /dev/null +++ b/product-of-array-except-self/dohyeon2.java @@ -0,0 +1,49 @@ +import java.util.Arrays; + +class Solution { + // TC : O(n) + // SC : O(n) + public int[] productExceptSelf(int[] nums) { + /** + * I previously solved this problem using division, + * but the problem restricts that approach. + * This was pointed out in the following comment: + * https://github.com/DaleStudy/leetcode-study/pull/2396#discussion_r2934545648 + * + * Approach: + * Compute prefix products using left[i-1] * nums[i-1], + * which represents the product of elements before i. + * + * Compute suffix products using right[i+1] * nums[i+1] + * by traversing from right to left. + * + * The result at index i is: + * left[i] * right[i] + */ + + int[] answer = new int[nums.length]; + + int[] left = new int[nums.length]; + Arrays.fill(left, 1); + int[] right = new int[nums.length]; + Arrays.fill(right, 1); + + for (int i = 0; i < nums.length; i++) { + if (i - 1 < 0) + continue; + left[i] *= left[i - 1] * nums[i - 1]; + } + + for (int i = nums.length - 1; i >= 0; i--) { + if (i + 1 > nums.length - 1) + continue; + right[i] *= right[i + 1] * nums[i + 1]; + } + + for (int i = 0; i < nums.length; i++) { + answer[i] = left[i] * right[i]; + } + + return answer; + } +} diff --git a/valid-anagram/dohyeon2.java b/valid-anagram/dohyeon2.java new file mode 100644 index 0000000000..fb117b3237 --- /dev/null +++ b/valid-anagram/dohyeon2.java @@ -0,0 +1,26 @@ +import java.util.HashMap; + +class Solution { + public boolean isAnagram(String s, String t) { + if (s.length() != t.length()) { + return false; + } + + // TC = O(n) + // SC = O(n) + HashMap sMap = new HashMap<>(); + + for (char c : s.toCharArray()) { + sMap.merge(c, 1, Integer::sum); + } + + for (char c : t.toCharArray()) { + if (sMap.getOrDefault(c, 0) == 0) { + return false; + } + sMap.merge(c, -1, Integer::sum); + } + + return true; + } +} diff --git a/validate-binary-search-tree/dohyeon2.java b/validate-binary-search-tree/dohyeon2.java new file mode 100644 index 0000000000..0286b4c85e --- /dev/null +++ b/validate-binary-search-tree/dohyeon2.java @@ -0,0 +1,52 @@ +/** + * Definition for a binary tree node. + * public class TreeNode { + * int val; + * TreeNode left; + * TreeNode right; + * TreeNode() {} + * TreeNode(int val) { this.val = val; } + * TreeNode(int val, TreeNode left, TreeNode right) { + * this.val = val; + * this.left = left; + * this.right = right; + * } + * } + */ +class Solution { + // TC : O(n) Each node is visited once in the loop. + // SC : O(n) Memory allocated for call stack + // In the first attempt, I tried BFS to solve the problem. + // But I figured out that I needed to validate a BST recursively. + // So, I switched to DFS to solve the problem. + // At first, I compared the node's value with the children's values. + // And I checked that those values were in the range of min and max. + // Then, I simplified the approach by + // comparing the node's value with the min and max values (assisted by ChatGPT). + public boolean isValidBST(TreeNode root) { + return dfs(root); + } + + // Overloading the method to set default arguments + private boolean dfs(TreeNode node) { + return dfs(node, Long.MIN_VALUE, Long.MAX_VALUE); + } + + private boolean dfs(TreeNode node, long min, long max) { + // It's the end of the tree, return true, + // because the search is valid until this point. + if (node == null) { + return true; + } + + if (node.val <= min) { + return false; + } + if (node.val >= max) { + return false; + } + + // All the result of search must be true, if the tree is valid + return dfs(node.left, min, node.val) && dfs(node.right, node.val, max); + } +}