From e832a64a1641a7ee42f941a7a507a315f463b4c5 Mon Sep 17 00:00:00 2001 From: Yn3-3xh Date: Mon, 7 Apr 2025 19:34:51 +0900 Subject: [PATCH 1/5] valid anagram solution --- valid-anagram/Yn3-3xh.java | 80 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 valid-anagram/Yn3-3xh.java diff --git a/valid-anagram/Yn3-3xh.java b/valid-anagram/Yn3-3xh.java new file mode 100644 index 000000000..e269d9d38 --- /dev/null +++ b/valid-anagram/Yn3-3xh.java @@ -0,0 +1,80 @@ +/* +[문제풀이] +- char 배열로 맞춰보자 (x) +- s와 t의 길이가 같아야 한다. +- 각 철자의 개수가 s와 t 모두 일치하는지 확인한다. (테스트케이스 하나 실패) + +- s 철자의 개수를 세어 놓고, t 철자의 개수는 하나씩 빼서 0을 체크해보자. Map (O) +time: O(N), space: O(N) + class Solution { + public boolean isAnagram(String s, String t) { + if (s.length() != t.length()) { + return false; + } + + Map counting = new HashMap<>(); + for (char ch : s.toCharArray()) { + counting.put(ch, counting.getOrDefault(ch, 0) + 1); + } + for (char ch : t.toCharArray()) { + if (!counting.containsKey(ch)) { + return false; + } + counting.put(ch, counting.get(ch) - 1); + } + + return counting.values().stream() + .allMatch(count -> count == 0); + } + } + +- Arrays로 정렬 및 비교를 해보자. (O) +time: O(NlogN), space: O(N) + class Solution { + public boolean isAnagram(String s, String t) { + if (s.length() != t.length()) { + return false; + } + + char[] sToCharArray = s.toCharArray(); + char[] tToCharArray = t.toCharArray(); + Arrays.sort(sToCharArray); + Arrays.sort(tToCharArray); + + return Arrays.equals(sToCharArray, tToCharArray); + } + } + +- s 철자의 개수를 세어 놓고, t 철자의 개수는 하나씩 빼서 0을 체크해보자. Array (O) +time: O(N), space: O(1) + +[회고] +Arrays처럼 자바에서 제공해주는 util을 잘 활용하지 못한 것 같다.. (띵킹하자!) + +처음 성공한 솔루션 접근법은 좋았는데 왜 성능이 안나왔나.. +HashMap은 내부적으로 해시 테이블 구조를 사용하므로, 동일한 데이터를 저장하더라도 배열보다 메모리를 더 많이 사용한다. +또한, 키와 값을 객체 타입으로 저장하기 때문에 오토박싱/언박싱 비용이 발생하고, 해시 계산과 충돌 처리 등의 추가 연산이 필요하다. +따라서 배열에 비해 느린 것 같다. +*/ +class Solution { + public boolean isAnagram(String s, String t) { + if (s.length() != t.length()) { + return false; + } + + int[] counting = new int[26]; + for (char ch : s.toCharArray()) { + counting[ch - 'a']++; + } + for (char ch : t.toCharArray()) { + counting[ch - 'a']--; + } + + for (int count : counting) { + if (count != 0) { + return false; + } + } + return true; + } +} From 8ad991f97f8f90bf0f2b27dc151be06578122106 Mon Sep 17 00:00:00 2001 From: Yn3-3xh Date: Tue, 8 Apr 2025 19:30:22 +0900 Subject: [PATCH 2/5] climbing stairs solution --- climbing-stairs/Yn3-3xh.java | 47 ++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 climbing-stairs/Yn3-3xh.java diff --git a/climbing-stairs/Yn3-3xh.java b/climbing-stairs/Yn3-3xh.java new file mode 100644 index 000000000..fbaa4d615 --- /dev/null +++ b/climbing-stairs/Yn3-3xh.java @@ -0,0 +1,47 @@ +/* +[문제풀이] +- 1 또는 2로 n을 만들 수 있는 전체 가지수 구하기 +- dfs (X) 시간초과 + class Solution { + + public int climbStairs(int n) { + return dfs(n); + } + + private int dfs(int n) { + if (n == 0) { + return 1; + } + if (n < 0) { + return 0; + } + return dfs(n - 1) + dfs(n - 2); + } + } + +- DP (O) +time: O(N), space: O(1) + +[회고] +규칙을 찾으려고 했었는데 못찾았다.. +피보나치 수열.. 풀었던 문제인데.. 생각하자; +F(N) = F(n-1) + F(n-2) +*/ +class Solution { + + public int climbStairs(int n) { + if (n <= 3) { + return n; + } + + int prev1 = 3; + int prev2 = 2; + int current = 0; + for (int i = 4; i <= n; i++) { + current = prev1 + prev2; + prev2 = prev1; + prev1 = current; + } + return current; + } +} From 6be40f5cce0ddccbe6a7b12a922415cbae3a1350 Mon Sep 17 00:00:00 2001 From: Yn3-3xh Date: Wed, 9 Apr 2025 22:04:40 +0900 Subject: [PATCH 3/5] product of array except self solution --- product-of-array-except-self/Yn3-3xh.java | 71 +++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 product-of-array-except-self/Yn3-3xh.java diff --git a/product-of-array-except-self/Yn3-3xh.java b/product-of-array-except-self/Yn3-3xh.java new file mode 100644 index 000000000..0648eca45 --- /dev/null +++ b/product-of-array-except-self/Yn3-3xh.java @@ -0,0 +1,71 @@ +/* +[문제풀이] +- 본인 index를 제외한 모든 index의 수를 곱하자. +- O(N)으로 풀자. +- 나눗셈은 사용하지 말자. + +index 0 1 2 3 +num 1 2 3 4 +prefix 1 1 2 6 + +index 0 1 2 3 +num 1 2 3 4 +suffix 24 12 4 1 + +answer = prefix * suffix +24 12 8 6 + +- 풀이 1 +time: O(N), space: O(N) + class Solution { + public int[] productExceptSelf(int[] nums) { + int len = nums.length; + int[] answer = new int[len]; + int[] prefix = new int[len]; + int[] suffix = new int[len]; + + prefix[0] = 1; + suffix[len - 1] = 1; + for (int i = 1; i < len; i++) { + prefix[i] = prefix[i - 1] * nums[i - 1]; + } + for (int i = len - 2; i >= 0; i--) { + suffix[i] = suffix[i + 1] * nums[i + 1]; + } + + for (int i = 0; i < len; i++) { + answer[i] = prefix[i] * suffix[i]; + } + return answer; + } + } + +- 풀이 2 +time: O(N), space: O(1) + + +[회고] +본인 index가 아닌 "앞의 수들의 곱"과 "뒤의 수들의 곱" 을 어떻게 구할 수 있을까? +의 고민에서 방법을 찾지 못했다. + +풀이방법을 보고 변수와 반복문을 더 쓰기 싫어하는 부분에서 아이디어가 닫힌 것 같다.. +우선 많이 써보고 줄이는 방법으로 풀어보자. +*/ +class Solution { + public int[] productExceptSelf(int[] nums) { + int len = nums.length; + + int[] answer = new int[len]; + answer[0] = 1; + for (int i = 1; i < len; i++) { + answer[i] = answer[i - 1] * nums[i - 1]; + } + + int suffixMul = 1; + for (int i = len - 2; i >= 0; i--) { + suffixMul *= nums[i + 1]; + answer[i] *= suffixMul; + } + return answer; + } +} From 49c0cf3117119c2ad4c70723e9709bcb2d4174cc Mon Sep 17 00:00:00 2001 From: Yn3-3xh Date: Thu, 10 Apr 2025 00:01:28 +0900 Subject: [PATCH 4/5] 3sum solution --- 3sum/Yn3-3xh.java | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 3sum/Yn3-3xh.java diff --git a/3sum/Yn3-3xh.java b/3sum/Yn3-3xh.java new file mode 100644 index 000000000..72bd9f2a7 --- /dev/null +++ b/3sum/Yn3-3xh.java @@ -0,0 +1,39 @@ +/* +[문제풀이] +- nums 배열 안의 3가지 수를 더했을 때 0이어야 한다. +- 더해진 수들의 index는 모두 달라야 한다. +- DFS (X) + StackOverflowError +- 투 포인터 (O) +time: O(N^2), space: O(N^2) + +[회고] +해설을 보고 이해는 했는데 다시 풀 수 있을까? +아직 스킬이 부족한 것 같다.. + +*/ +class Solution { + public List> threeSum(int[] nums) { + Set> answers = new HashSet<>(); + Arrays.sort(nums); + + for (int start = 0; start < nums.length; start++) { + int mid = start + 1; + int end = nums.length - 1; + + while (mid < end) { + int sum = nums[start] + nums[mid] + nums[end]; + if (sum == 0) { + List answer = List.of(nums[start], nums[mid], nums[end]); + answers.add(answer); + end--; + } else if (sum < 0) { + mid++; + } else if (sum > 0) { + end--; + } + } + } + return new ArrayList<>(answers); + } +} From 132163fb8a9cf0b9f9e620f1b861d9e40c42798c Mon Sep 17 00:00:00 2001 From: Yn3-3xh Date: Fri, 11 Apr 2025 01:21:32 +0900 Subject: [PATCH 5/5] validate binary search tree solution --- validate-binary-search-tree/Yn3-3xh.java | 51 ++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 validate-binary-search-tree/Yn3-3xh.java diff --git a/validate-binary-search-tree/Yn3-3xh.java b/validate-binary-search-tree/Yn3-3xh.java new file mode 100644 index 000000000..716571411 --- /dev/null +++ b/validate-binary-search-tree/Yn3-3xh.java @@ -0,0 +1,51 @@ +/* +[문제풀이] +- node의 왼쪽은 작아야 한다. +- node의 오른쪽은 커야 한다. +- 2^31 - 1 까지면 int + - 범위는 long + +- dfs로 풀자 (O) +time: O(N), space: O(N) + +[회고] +!!! int 범위이지만 비교를 위해서는 더 큰 단위가 필요하므로 Long을 사용해야 한다 !!! + +leftMaxVal, rightMinVal 네이밍은 +왼쪽 노드는 root가 커야 해서 leftMaxVal, +오른쪽 노드는 root가 작아야 해서 rightMinVal로 +조금 더 직관적으로 지어봤다. (조건문도 마찬가지) +*/ + +/** + * 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 { + public boolean isValidBST(TreeNode root) { + return dfs(root, Long.MAX_VALUE, Long.MIN_VALUE); + } + + private boolean dfs(TreeNode node, long leftMaxVal, long rightMinVal) { + if (node == null) { + return true; + } + + if (!(node.val < leftMaxVal) || !(node.val > rightMinVal)) { + return false; + } + + return dfs(node.left, node.val, rightMinVal) && dfs(node.right, leftMaxVal, node.val); + } +}