From 80768164b215c007293d3f5dafaaae56505e98e4 Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: Sun, 1 Mar 2026 21:35:41 +0900 Subject: [PATCH 1/7] Solution for Valid Anagram #218 --- valid-anagram/dohyeon2.java | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 valid-anagram/dohyeon2.java 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; + } +} From 83ab2d0c30899e6e27173e4327ed77e194af3793 Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: Sun, 1 Mar 2026 23:35:02 +0900 Subject: [PATCH 2/7] Solution for Climbing Stairs #230 Add time and space complexity comments to climbStairs method --- climbing-stairs/dohyeon2.java | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 climbing-stairs/dohyeon2.java 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; + } +} From 443405bfc4631611c7dc294558f565de5c4c6d1a Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: Mon, 2 Mar 2026 23:10:23 +0900 Subject: [PATCH 3/7] Solution for Product of Array Except Self #239 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 잊지말자 개행문자 --- product-of-array-except-self/dohyeon2.java | 49 ++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 product-of-array-except-self/dohyeon2.java diff --git a/product-of-array-except-self/dohyeon2.java b/product-of-array-except-self/dohyeon2.java new file mode 100644 index 0000000000..62cc2396a9 --- /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) { + /** + * Approach: + * 1. Calculate the product of all non-zero elements + * 2. Count how many zeros exist in the array. + * 3. Handle three cases: + * - If there are more than one zero, all results are 0. + * - If there is exactly one zero, + * only the index with 0 gets the total product; others are 0. + * - If there is no zero, each result is totalProduct / nums[i]. + */ + int zeroCount = 0; + + for (int n : nums) { + if (n == 0) { + zeroCount++; + } + if (zeroCount > 1) { + break; + } + } + + if (zeroCount > 1) { + return new int[nums.length]; + } + + int production = Arrays.stream(nums).filter((n) -> { + return n != 0; + }).reduce(1, (a, b) -> a * b); + + if (zeroCount == 1) { + return Arrays.stream(nums).map((n) -> { + if (n == 0) { + return production; + } + return 0; + }).toArray(); + } + + return Arrays.stream(nums).map((n) -> { + return production / n; + }).toArray(); + } +} From 212df1277fecf335fc93845f67190d55fe2bd305 Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: Mon, 9 Mar 2026 02:30:44 +0900 Subject: [PATCH 4/7] Solution for 3Sum #241 Refactor comments in 3Sum solution for clarity and consistency --- 3sum/dohyeon2.java | 57 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 3sum/dohyeon2.java diff --git a/3sum/dohyeon2.java b/3sum/dohyeon2.java new file mode 100644 index 0000000000..bcb58bfe49 --- /dev/null +++ b/3sum/dohyeon2.java @@ -0,0 +1,57 @@ +import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; + +class Solution { + // TC: O(n^2) + // SC: O(1) + 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--; + } + if (sum < 0) { + left++; + } + if (sum > 0) { + right--; + } + } + + } + + return answer; + } +} From 6e4c3dcec57734f2b31f17c20ab376616531336d Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: Mon, 9 Mar 2026 23:21:34 +0900 Subject: [PATCH 5/7] Solution for Validate Binary Search Tree #251 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit first approach second approach children solution update comments 개행문자 삽입 Update comments in validate-binary-search-tree solution for clarity Enhance comment clarity in validate-binary-search-tree solution --- validate-binary-search-tree/dohyeon2.java | 52 +++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 validate-binary-search-tree/dohyeon2.java 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); + } +} From e8e6de1cf728e8502505ae7153e55cdf942b9375 Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: Sat, 14 Mar 2026 14:24:01 +0900 Subject: [PATCH 6/7] Update space complexity comment and improve conditional logic clarity in 3Sum solution Refine space complexity comment in 3Sum solution for accuracy --- 3sum/dohyeon2.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/3sum/dohyeon2.java b/3sum/dohyeon2.java index bcb58bfe49..c4cd128337 100644 --- a/3sum/dohyeon2.java +++ b/3sum/dohyeon2.java @@ -4,7 +4,7 @@ class Solution { // TC: O(n^2) - // SC: O(1) + // SC: O(n^2) public List> threeSum(int[] nums) { List> answer = new ArrayList>(); @@ -41,11 +41,9 @@ public List> threeSum(int[] nums) { left++; right--; - } - if (sum < 0) { + } else if (sum < 0) { left++; - } - if (sum > 0) { + } else { right--; } } From 7f1344a4a0a445eae4bb36ece94ea70e7130cf67 Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: Sat, 14 Mar 2026 15:40:19 +0900 Subject: [PATCH 7/7] Refactor productExceptSelf method to eliminate division Add missing newline at the end of the file in dohyeon2.java --- product-of-array-except-self/dohyeon2.java | 62 +++++++++++----------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/product-of-array-except-self/dohyeon2.java b/product-of-array-except-self/dohyeon2.java index 62cc2396a9..e851e6dd17 100644 --- a/product-of-array-except-self/dohyeon2.java +++ b/product-of-array-except-self/dohyeon2.java @@ -5,45 +5,45 @@ class Solution { // 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: - * 1. Calculate the product of all non-zero elements - * 2. Count how many zeros exist in the array. - * 3. Handle three cases: - * - If there are more than one zero, all results are 0. - * - If there is exactly one zero, - * only the index with 0 gets the total product; others are 0. - * - If there is no zero, each result is totalProduct / nums[i]. + * 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 zeroCount = 0; - for (int n : nums) { - if (n == 0) { - zeroCount++; - } - if (zeroCount > 1) { - break; - } - } + 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); - if (zeroCount > 1) { - return new int[nums.length]; + for (int i = 0; i < nums.length; i++) { + if (i - 1 < 0) + continue; + left[i] *= left[i - 1] * nums[i - 1]; } - int production = Arrays.stream(nums).filter((n) -> { - return n != 0; - }).reduce(1, (a, b) -> a * b); + for (int i = nums.length - 1; i >= 0; i--) { + if (i + 1 > nums.length - 1) + continue; + right[i] *= right[i + 1] * nums[i + 1]; + } - if (zeroCount == 1) { - return Arrays.stream(nums).map((n) -> { - if (n == 0) { - return production; - } - return 0; - }).toArray(); + for (int i = 0; i < nums.length; i++) { + answer[i] = left[i] * right[i]; } - return Arrays.stream(nums).map((n) -> { - return production / n; - }).toArray(); + return answer; } }