From b6fb14eea529ba4061d554b342e8bed9ca289205 Mon Sep 17 00:00:00 2001 From: Suhyen Im Date: Sat, 2 Aug 2025 22:50:00 +0900 Subject: [PATCH 1/2] [suhyenim] WEEK02 solutions --- climbing-stairs/suhyenim.java | 82 +++++++++++++++++++ product-of-array-except-self/suhyenim.java | 93 ++++++++++++++++++++++ valid-anagram/suhyenim.java | 81 +++++++++++++++++++ 3 files changed, 256 insertions(+) create mode 100644 climbing-stairs/suhyenim.java create mode 100644 product-of-array-except-self/suhyenim.java create mode 100644 valid-anagram/suhyenim.java diff --git a/climbing-stairs/suhyenim.java b/climbing-stairs/suhyenim.java new file mode 100644 index 000000000..c3153a098 --- /dev/null +++ b/climbing-stairs/suhyenim.java @@ -0,0 +1,82 @@ +/* [5th/week02] 70. Climbing Stairs + +1. 문제 요약 +링크: https://leetcode.com/problems/climbing-stairs/description/ +한 번에 1칸이나 2칸을 올라갈 수 있을 때, n칸을 올라가는 방법의 수는? + +2. 문제 풀이 +풀이1: 1, 2칸을 올라가는 방법의 수는 이미 알기 때문에, "n칸을 올라가는 방법의 수 = n-2칸을 올라가는 방법의 수 + n-1칸을 올라가는 방법의 수"를 반복 +성공: Time: 0 ms (100%), Space: 40.4 MB (50.46%) +=> 시간 복잡도: O(n), 공간 복잡도: O(n) + +class Solution { + public int climbStairs(int n) { + Map dp = new HashMap<>(); + dp.put(1, 1); + dp.put(2, 2); + for (int i = 3; i <= n; i++){ + dp.put(i, dp.get(i - 2) + dp.get(i - 1)); + } + return dp.get(n); + } +} + +풀이2: 풀이1과 논리는 같지만, HashMap을 사용하지 않음으로써 공간 복잡도를 낮춤 +성공: Time: 0 ms (100%), Space: 40.1 MB (97.08%) +=> 시간 복잡도: O(n), 공간 복잡도: O(1) + +class Solution { + public int climbStairs(int n) { + if (n < 3){ + return n; + } + int n1 = 1, n2 = 2; + for (int i = 0; i < n - 2; i++){ + int n3 = n1 + n2; + n1 = n2; + n2 = n3; + } + return n2; + } +} + +풀이3: 풀이1은 반복문(bottom-up) DP이고, 풀이3은 재귀+메모이제이션(top-down) DP임 +성공: Time: 0 ms (100%), Space: 40.5 MB (50.46%) +=> 시간 복잡도: O(n), 공간 복잡도: O(n) + +class Solution { + private Map memo = new HashMap<>(); + + public int climbStairs(int n) { + if (memo.containsKey(n)) { + return memo.get(n); + } + + if (n < 3) { + return n; + } + + int result = climbStairs(n - 1) + climbStairs(n - 2); + memo.put(n, result); + return result; + } +} + +3. TIL +재귀에다가 메모이제이션을 더하면 +=> 큰 문제는 재귀적으로 쪼개서 풀되, 이미 계산한 작은 문제의 결과는 메모(map)에 저장해두었다가 꺼내 쓸 수 있기 때문에 +=> 중복 계산을 방지함으로써 시간 복잡도를 아낄 수 있다. + +*/ + +class Solution { + public int climbStairs(int n) { + Map dp = new HashMap<>(); + dp.put(1, 1); + dp.put(2, 2); + for (int i = 3; i <= n; i++){ + dp.put(i, dp.get(i - 2) + dp.get(i - 1)); + } + return dp.get(n); + } +} diff --git a/product-of-array-except-self/suhyenim.java b/product-of-array-except-self/suhyenim.java new file mode 100644 index 000000000..93db27ff3 --- /dev/null +++ b/product-of-array-except-self/suhyenim.java @@ -0,0 +1,93 @@ +/* [5th/week02] 238. Product of Array Except Self + +1. 문제 요약 +링크: https://leetcode.com/problems/product-of-array-except-self/description/ +각 인덱스 i에 대해, num[i]를 제외한 모든 값들을 곱해서 배열로 반환 +(주의: 나누기 안됨, 시간 복잡도 O(n) 내로 동작해야 함) + +2. 문제 풀이 +풀이1: 인덱스 i를 기점으로, 이전 값들의 누적곱 배열 & 이후 값들의 누적곱 배열을 만들고 -> 각 인덱스 i에 대해, 두 배열 값 곱하기 +성공: Time: 2 ms (87.36%), Space: 56.5 MB (10.9%) +=> 시간 복잡도: O(n), 공간 복잡도: O(n) + +class Solution { + public int[] productExceptSelf(int[] nums) { + int n = nums.length; + int[] before = new int[n]; + int[] after = new int[n]; + int[] products = new int[n]; + + before[0] = 1; + for (int i = 0; i < n - 1; i++) { + before[i + 1] = before[i] * nums[i]; + } + + after[n - 1] = 1; + for (int i = n - 1; i > 0; i--) { + after[i - 1] = after[i] * nums[i]; + } + + for (int i = 0; i < n; i++) { + products[i] = before[i] * after[i]; + } + + return products; + } +} + +풀이2: +성공: Time: 3 ms (19.55%), Space: 55.4 MB (61.74%) +=> 시간 복잡도: 시간 복잡도: O(n), 공간 복잡도: 결과 배열 제외하면 O(1) + +class Solution { + public int[] productExceptSelf(int[] nums) { + int n = nums.length; + int[] products = new int[n]; + Arrays.fill(products, 1); + + int leftProduct = 1; + for (int i = 0; i < n - 1; i++) { + leftProduct *= nums[i]; + products[i + 1] *= leftProduct; + } + + int rightProduct = 1; + for (int i = n - 1; i > 0; i--) { + rightProduct *= nums[i]; + products[i - 1] *= rightProduct; + } + + return products; + } +} + +3. TIL +동적 계획법(DP)이란? +큰 문제를 작은 부분 문제로 나누고, 그 부분 문제들의 해를 저장해 두었다가(메모이제이션/테이블), 필요할 때 재사용해서 전체 문제를 효율적으로 해결하는 기법이다. + +*/ + +class Solution { + public int[] productExceptSelf(int[] nums) { + int n = nums.length; + int[] before = new int[n]; + int[] after = new int[n]; + int[] products = new int[n]; + + before[0] = 1; + for (int i = 0; i < n - 1; i++) { + before[i + 1] = before[i] * nums[i]; + } + + after[n - 1] = 1; + for (int i = n - 1; i > 0; i--) { + after[i - 1] = after[i] * nums[i]; + } + + for (int i = 0; i < n; i++) { + products[i] = before[i] * after[i]; + } + + return products; + } +} diff --git a/valid-anagram/suhyenim.java b/valid-anagram/suhyenim.java new file mode 100644 index 000000000..0aa681ce4 --- /dev/null +++ b/valid-anagram/suhyenim.java @@ -0,0 +1,81 @@ +/* [5th/week02] 242. Valid Anagram + +1. 문제 요약 +링크: https://leetcode.com/problems/valid-anagram/description/ +문자열 t가 문자열 s의 anagram이면 true 반환 + +2. 문제 풀이 +제출1: 길이가 다른지 우선 체크하고 -> 각 문자열을 배열로 만들어서 오름차순 정렬 후, 반복문을 돌면서 문자가 다르면 false 반환 +성공: Time: 3 ms (91.78%), Space: 44.6 MB (43.28%) +=> 시간 복잡도: O(nlogn), 공간 복잡도: O(n) + +class Solution { + public boolean isAnagram(String s, String t) { + if (s.length() != t.length()){ + return false; + } + char[] ss = s.toCharArray(); + char[] tt = t.toCharArray(); + Arrays.sort(ss); + Arrays.sort(tt); + for (int i = 0; i < s.length(); i++){ + if (ss[i] != tt[i]){ + return false; + } + } + return true; + } +} + +풀이2: 길이가 다른지 우선 체크하고 -> s를 {문자:횟수} 구조의 HashMap으로 만든 후 -> t의 문자들과 비교해서 같으면 {키:밸류}쌍 삭제 -> 최종적으로 {키:밸류}쌍이 0개면 true 반환 +성공: Time: 15 ms (25.19%), Space: 45 MB (10.95%) +=> 시간 복잡도: O(n), 공간 복잡도: O(n) + +class Solution { + public boolean isAnagram(String s, String t) { + if (s.length() != t.length()) { + return false; + } + + Map count = new HashMap<>(); + for (char c : s.toCharArray()) { + count.put(c, count.getOrDefault(c, 0) + 1); + } + + for (char c : t.toCharArray()) { + if (!count.containsKey(c)) { + return false; + } + count.put(c, count.get(c) - 1); + if (count.get(c) == 0) { + count.remove(c); + } + } + + return count.isEmpty(); + } +} + +3. TIL +Map에는 다양한 메소드가 있다. ex) getOrDefault(), containsKey(), put(), get(), remove() 등 +getOrDefault() 내부 구현에는 containsKey()가 사용된다. + +*/ + +class Solution { + public boolean isAnagram(String s, String t) { + if (s.length() != t.length()){ + return false; + } + char[] ss = s.toCharArray(); + char[] tt = t.toCharArray(); + Arrays.sort(ss); + Arrays.sort(tt); + for (int i = 0; i < s.length(); i++){ + if (ss[i] != tt[i]){ + return false; + } + } + return true; + } +} From 6672f9917b7502b1b558512a470a765c94815b8c Mon Sep 17 00:00:00 2001 From: Suhyen Im Date: Sat, 2 Aug 2025 22:52:58 +0900 Subject: [PATCH 2/2] =?UTF-8?q?product-of-array-except-self=20=ED=92=80?= =?UTF-8?q?=EC=9D=B4=20=EC=84=A4=EB=AA=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- product-of-array-except-self/suhyenim.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product-of-array-except-self/suhyenim.java b/product-of-array-except-self/suhyenim.java index 93db27ff3..1ab6466d9 100644 --- a/product-of-array-except-self/suhyenim.java +++ b/product-of-array-except-self/suhyenim.java @@ -35,7 +35,7 @@ public int[] productExceptSelf(int[] nums) { } } -풀이2: +풀이2: 풀이1과 논리는 동일하지만, 누적곱을 배열을 사용해서 저장해두는 것이 아니라 변수 하나를 사용해서 저장하도록 변경 성공: Time: 3 ms (19.55%), Space: 55.4 MB (61.74%) => 시간 복잡도: 시간 복잡도: O(n), 공간 복잡도: 결과 배열 제외하면 O(1)