From 7ff138e4234797e371d04f04969d3a0737fcc07a Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: 2026年3月15日 18:05:15 +0900 Subject: [PATCH 001/526] Solution for Valid Palindrome #220 --- valid-palindrome/dohyeon2.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 valid-palindrome/dohyeon2.java diff --git a/valid-palindrome/dohyeon2.java b/valid-palindrome/dohyeon2.java new file mode 100644 index 0000000000..4e95870a92 --- /dev/null +++ b/valid-palindrome/dohyeon2.java @@ -0,0 +1,18 @@ +class Solution { + // TC : O(n) + // SC : O(1) + public boolean isPalindrome(String s) { + // Condition 1 : after converting all uppercase letters into lowercase letters + // and removing all non-alphanumeric characters + String onlyAlphaNumeric = s.toLowerCase().replaceAll("[^a-z0-9]", ""); + int length = onlyAlphaNumeric.length(); + for (int i = 0; i < length / 2; i++) { + int right = length - 1 - i; + int left = i; + // Condition 2 : it reads the same forward and backward + if (onlyAlphaNumeric.charAt(left) != onlyAlphaNumeric.charAt(right)) + return false; + } + return true; + } +} From e92b93423c1ac1069b2c86bce13feb9b4ef342cc Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: 2026年3月15日 21:26:40 +0900 Subject: [PATCH 002/526] Solution for Number of 1 Bits #232 --- number-of-1-bits/dohyeon2.java | 75 ++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 number-of-1-bits/dohyeon2.java diff --git a/number-of-1-bits/dohyeon2.java b/number-of-1-bits/dohyeon2.java new file mode 100644 index 0000000000..6c30c9d3aa --- /dev/null +++ b/number-of-1-bits/dohyeon2.java @@ -0,0 +1,75 @@ +import java.util.HashMap; + +class Solution { + // n & (n-1) -> 마지막 set bit 제거 + // n & -n -> 마지막 set bit 추출 + // i>> 1 -> 절반 + // i & 1 -> 마지막 bit + // i & (i - 1) == 0 -> i는 2의 거듭제곱 + + // Follow up: If this function is called many times, how would you optimize it? + // I'll cache the results in a HashMap. + // (Or I can use lookup table or DP) + private HashMap cache = new HashMap(); + + public int hammingWeight(int n) { + // simple in Java + // return Integer.bitCount(n); + + if (cache.containsKey(n)) { + return cache.get(n); + } + + int buffer = n; + int answer = 0; + + // 1. self thought solution + // TC : O(log n) + // SC : O(1) + while (buffer> 0) { + answer += buffer % 2; + buffer = buffer / 2; + } + + // 2. fancy solution from leetcode using bit computing + // TC : O(log n) + // SC : O(1) + // while(buffer> 0){ + // if((buffer & 1) == 1){ + // answer++; + // } + // buffer = buffer>> 1; + // } + + // 3. another fancy solution from ChatGPT + // Brian Kernighan algorithm + // TC : O(number of set bits) + // SC : O(1) + // while (buffer != 0) { + // // 11 & 10 => 1 & 0 => 0 + // buffer = buffer & (buffer - 1); // AND with buffer and buffer -1 => remove + // last set bit. + // System.out.println(buffer); + // answer++; + // } + + // 4. using lookup table + // int[] table = new int[256]; + // for (int i = 0; i < 256; i++) { + // table[i] = (i & 1) + table[i>> 1]; + // } + // answer = table[buffer & 0xff] + + // table[(buffer>> 8) & 0xff] + + // table[(buffer>> 16) & 0xff] + + // table[(buffer>> 24) & 0xff]; + + // 5. DP + // int[] bits = new int[n + 1]; + // for (int i = 1; i <= n; i++) { + // bits[i] = bits[i>> 1] + (i & 1); + // } + + cache.put(n, answer); + return answer; + } +} From 262fd2376f3097ce29b3a2202d164faadbeabdb1 Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: 2026年3月16日 14:12:20 +0900 Subject: [PATCH 003/526] valid palindrome solution --- valid-palindrome/robinyoon-dev.js | 52 +++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 valid-palindrome/robinyoon-dev.js diff --git a/valid-palindrome/robinyoon-dev.js b/valid-palindrome/robinyoon-dev.js new file mode 100644 index 0000000000..1f62f50254 --- /dev/null +++ b/valid-palindrome/robinyoon-dev.js @@ -0,0 +1,52 @@ +/** + * @param {string} s + * @return {boolean} + */ +var isPalindrome = function (s) { + + //NOTE: 다음에는 투 포인터 방식으로 불어보겠습니다... + + //0. 엣지케이스 대비: 빈칸인 경우. + if (s.trim() === '') { + return true; + } + + //1. s를 array로 변환 + const sArray = Array.from(s); + + // 알파벳만 남기는 작업 + // (Alphanumeric characters include letters and numbers.) + const aAscii = 'a'.charCodeAt(0); + const zAscii = 'z'.charCodeAt(0); + const aUpperAscii = 'A'.charCodeAt(0); + const zUpperAscii = 'Z'.charCodeAt(0); + const zeroAscii = '0'.charCodeAt(0); + const nineAscii = '9'.charCodeAt(0); + + const filteredArray = []; + for (let char of sArray) { + let charAscii = char.charCodeAt(0); + + let isCharacter = (charAscii>= aAscii && charAscii <= zAscii) || (charAscii>= aUpperAscii && charAscii <= zUpperAscii) || (charAscii>= zeroAscii && charAscii <= nineAscii); + + if (isCharacter) { + filteredArray.push(char); + } + } + + // 대문자 -> 소문자로 변경하는 작업 + const lowerArray = []; + for (let char of filteredArray) { + lowerArray.push(char.toLowerCase()); + } + + // reverse 해도 똑같은지 확인하는 작업 + const reversedArray = [...lowerArray].reverse(); + + const originalString = lowerArray.join(); + const reversedString = reversedArray.join(); + + return originalString === reversedString; + +}; + From c9df170a9bc76eee24aabee8c36bf4b96155b050 Mon Sep 17 00:00:00 2001 From: DongHun Date: 2026年3月16日 17:01:16 +0900 Subject: [PATCH 004/526] Solve valid-palindrome in two-way --- valid-palindrome/OstenHun.cpp | 84 +++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 valid-palindrome/OstenHun.cpp diff --git a/valid-palindrome/OstenHun.cpp b/valid-palindrome/OstenHun.cpp new file mode 100644 index 0000000000..1267d0da8d --- /dev/null +++ b/valid-palindrome/OstenHun.cpp @@ -0,0 +1,84 @@ +/* + A phrase is a palindrome if, + after converting all uppercase letters into lowercase letters and + removing all non-alphanumeric characters, it reads the same forward and backward. + Alphanumeric characters include letters and numbers. + + Given a string s, return true if it is a palindrome, or false otherwise. + + Example 1: + + Input: s = "A man, a plan, a canal: Panama" + Output: true + Explanation: "amanaplanacanalpanama" is a palindrome. + + Constraints: + + 1 <= s.length <= 2 * 105 + s consists only of printable ASCII characters. +*/ + +#include +#include +#include +using namespace std; + +#pragma region ExtraSpaceIdea +// 새로운 배열을 만들어서 문자열을 정리한 후에 팰린드롬 판별 +// 시간 복잡도 : O(n) +// 공간 복잡도 : O(n) +// n은 문자열의 길이일 것이다. +namespace extra_space_idea { + +class Solution { +public: + bool isPalindrome(string s) { + vector str; + str.reserve(s.size()); + + size_t len = s.length(); + for (size_t i = 0; i < len; i++) { + if (isalnum(s[i])) { + str.push_back(tolower(s[i])); + } + } + + size_t vec_len = str.size(); + for (size_t i = 0; i < (vec_len + 1) / 2; i++) { + if (str[i] != str[vec_len - 1 - i]) return false; + } + + return true; + } +}; + +} // namespace extra_space_idea +#pragma endregion + +#pragma region FinalSolution +// 투 포인터를 이용해 추가 배열 없이 구현 +// 시간 복잡도 : O(n) +// 공간 복잡도 : O(1) +class Solution { +public: + bool isPalindrome(string s) { + int left = 0; + int right = s.length() - 1; + + while(left < right) { + if (!isalnum(s[left])) + left++; + else if (!isalnum(s[right])) + right--; + else { + if (tolower(s[left]) != tolower(s[right])) + return false; + left++; + right--; + } + } + + return true; + } +}; +#pragma endregion From d4a3f56d2dd8443e491f4b6c06e6aad2ce7bf362 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年3月16日 18:52:18 +0900 Subject: [PATCH 005/526] =?UTF-8?q?3=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=201=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Number of 1 Bits --- number-of-1-bits/hwi-middle.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 number-of-1-bits/hwi-middle.cpp diff --git a/number-of-1-bits/hwi-middle.cpp b/number-of-1-bits/hwi-middle.cpp new file mode 100644 index 0000000000..d3d81b1392 --- /dev/null +++ b/number-of-1-bits/hwi-middle.cpp @@ -0,0 +1,19 @@ +class Solution { +public: + int hammingWeight(int n) { + // 아주 간편한 풀이가 있지만... + // return __builtin_popcount(n); + + // 직접 해보기 + int cnt = 0; + for (unsigned int i = 1 << 31; i> 0; i /= 2) + { + if ((n & i) != 0) + { + cnt++; + } + } + + return cnt; + } +}; From 77751633dc8d67ec2505d2fd111a603fa0b55469 Mon Sep 17 00:00:00 2001 From: mrlee7 Date: 2026年3月16日 19:12:13 +0900 Subject: [PATCH 006/526] valid palindrome solution --- valid-palindrome/mrlee7.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 valid-palindrome/mrlee7.py diff --git a/valid-palindrome/mrlee7.py b/valid-palindrome/mrlee7.py new file mode 100644 index 0000000000..e4983e01d3 --- /dev/null +++ b/valid-palindrome/mrlee7.py @@ -0,0 +1,7 @@ +import re + + +class Solution: + def isPalindrome(self, s: str) -> bool: + result = re.sub(r'[^a-zA-Z0-9]', '', s).lower() + return result == result[::-1] From f70016b4cd8979dd886a4684914619202003f570 Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: 2026年3月16日 20:43:21 +0900 Subject: [PATCH 007/526] sadie100: valid palindrome solution --- valid-palindrome/sadie100.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 valid-palindrome/sadie100.ts diff --git a/valid-palindrome/sadie100.ts b/valid-palindrome/sadie100.ts new file mode 100644 index 0000000000..0258a1116d --- /dev/null +++ b/valid-palindrome/sadie100.ts @@ -0,0 +1,23 @@ +/* +s에서 알파벳과 숫자가 아닌 글자를 다 날리고, 스택에 문자를 절반까지 담은 후 절반 이후부터는 꺼내가며 앞뒤 레터가 일치하는지 확인한다 + +시간복잡도 : O(N) (N은 s의 길이) +공간복잡도 : O(N) (스택) +*/ + +function isPalindrome(s: string): boolean { + const newStr = s.replace(/[^a-zA-Z0-9]/g, '').toLowerCase() + const isStrEven = newStr.length % 2 === 0 + const lenHalf = Math.floor(newStr.length / 2) + const stack = [] + for (let i = 0; i < newStr.length; i++) { + if (i < lenHalf) { + stack.push(newStr[i]) + } else { + if (!isStrEven && i === lenHalf) continue + const isSame = newStr[i] === stack.pop() + if (!isSame) return false + } + } + return true +} From 615102360b129f38a6c197a31b8c52ae08c0fd2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年3月16日 21:14:10 +0900 Subject: [PATCH 008/526] Add solution for Valid Palindrome problem --- valid-palindrome/gcount85.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 valid-palindrome/gcount85.py diff --git a/valid-palindrome/gcount85.py b/valid-palindrome/gcount85.py new file mode 100644 index 0000000000..9fe8f4ccb6 --- /dev/null +++ b/valid-palindrome/gcount85.py @@ -0,0 +1,27 @@ +""" +# Approach +양 끝에 포인터를 두고 파이썬의 isalnum(), lower() 문자열 메소드로 검사합니다. + +# Complexity +- Time complexity: s의 길이를 N이라고 할 때, O(N) + +- Space complexity: O(1) +""" + + +class Solution: + def isPalindrome(self, s: str) -> bool: + l = 0 + r = len(s) - 1 + while l < r: + if not s[l].isalnum(): + l += 1 + continue + if not s[r].isalnum(): + r -= 1 + continue + if s[l].lower() != s[r].lower(): + return False + l += 1 + r -= 1 + return True From a69a338c415e9de2dfc3b5fd80a06cb0045b876f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年3月16日 21:32:27 +0900 Subject: [PATCH 009/526] Add solution for Number of 1 Bits problem --- number-of-1-bits/gcount85.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 number-of-1-bits/gcount85.py diff --git a/number-of-1-bits/gcount85.py b/number-of-1-bits/gcount85.py new file mode 100644 index 0000000000..e0f19cb9b4 --- /dev/null +++ b/number-of-1-bits/gcount85.py @@ -0,0 +1,18 @@ +""" +# Intuition +n을 n-1과 AND 비트 연산하면서 1을 제거해나가며 카운트한다. + +# Complexity +- Time complexity: n의 이진수 변환에서 1의 개수를 K라고 할 때, O(K) + +- Space complexity: O(1) +""" + + +class Solution: + def hammingWeight(self, n: int) -> int: + count = 0 + while n: + n &= n - 1 + count += 1 + return count From 0ea6ce851d08abd7f1c5175eb7fc5ba4a8224720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=EC=98=81?= Date: 2026年3月17日 10:19:31 +0900 Subject: [PATCH 010/526] =?UTF-8?q?isPalindrome=20=ED=92=80=EC=9D=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- valid-palindrome/junzero741.ts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 valid-palindrome/junzero741.ts diff --git a/valid-palindrome/junzero741.ts b/valid-palindrome/junzero741.ts new file mode 100644 index 0000000000..1f5bf7cbd9 --- /dev/null +++ b/valid-palindrome/junzero741.ts @@ -0,0 +1,29 @@ +// TC: O(n) +// SC: O(1) +function isPalindrome(s: string): boolean { + + let L = 0; + let R = s.length-1; + + while(R> 0 && L < s.length - 1 && L <= R) { + if(!isAlphanumeric(s[L])) { + L++; + continue; + } + if(!isAlphanumeric(s[R])) { + R--; + continue; + } + if(s[L].toLowerCase() !== s[R].toLowerCase()) { + return false; + } + L++; + R--; + } + + return true; +}; + +function isAlphanumeric(str: string): boolean { + return /^[a-zA-Z0-9]+$/.test(str); +} From 94bf9b6b73edbe39ce231a45daaac2f848d15659 Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: 2026年3月17日 10:35:47 +0900 Subject: [PATCH 011/526] number of 1 bits solution --- number-of-1-bits/robinyoon-dev.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 number-of-1-bits/robinyoon-dev.js diff --git a/number-of-1-bits/robinyoon-dev.js b/number-of-1-bits/robinyoon-dev.js new file mode 100644 index 0000000000..a47d965f44 --- /dev/null +++ b/number-of-1-bits/robinyoon-dev.js @@ -0,0 +1,19 @@ +/** + * @param {number} n + * @return {number} + */ +var hammingWeight = function (n) { + let count = 0; + let tempN = n; + while (tempN != 0) { + if (tempN & 1) { + // 비트 마스크(& 1): 앞의 비트들은 모두 0으로 무시하고, 맨 끝자리 비트만 추출하여 검사. + count++; + } + tempN = tempN>>> 1; + //>>: 부호 유지 우측 이동 + //>>>: 부호 상관없이 0으로 채우는 우측 이동 + } + + return count; +}; From 8d30b5f8592e03219d818ca45a08c9ce0829a520 Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年3月17日 15:52:14 +0900 Subject: [PATCH 012/526] add: validPalindrome solution --- valid-palindrome/Cyjin-jani.js | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 valid-palindrome/Cyjin-jani.js diff --git a/valid-palindrome/Cyjin-jani.js b/valid-palindrome/Cyjin-jani.js new file mode 100644 index 0000000000..c5052d3166 --- /dev/null +++ b/valid-palindrome/Cyjin-jani.js @@ -0,0 +1,41 @@ +// naive한 풀이 +// tc: O(n) +// sc: O(n) +const isPalindromeNaive = function (s) { + const str = s.toLowerCase().replace(/[^a-z0-9]/g, ''); // 이 부분에서 공간복잡도가 O(n) + let leftIdx = 0; + let rightIdx = str.length - 1; + + while (leftIdx <= rightIdx) { + if (str[leftIdx] !== str[rightIdx]) { + return false; + } else { + leftIdx++; + rightIdx--; + } + } + return true; +}; + +// 좀 더 최적화 된 풀이 +// tc: O(n) +// cs: O(1) +const isPalindrome = function (s) { + let leftIdx = 0; + let rightIdx = s.length - 1; + + while (leftIdx < rightIdx) { + while (leftIdx < rightIdx && !isAlphaNumeric(s[leftIdx])) leftIdx++; + while (leftIdx < rightIdx && !isAlphaNumeric(s[rightIdx])) rightIdx--; + + if (s[leftIdx].toLowerCase() !== s[rightIdx].toLowerCase()) return false; + + leftIdx++; + rightIdx--; + } + return true; +}; + +function isAlphaNumeric(char) { + return /[a-zA-Z0-9]/.test(char); +} From f886f0b1018ae409a0536abc00bce67fbaf49105 Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年3月17日 16:14:24 +0900 Subject: [PATCH 013/526] add: numberOf1Bits solution --- number-of-1-bits/Cyjin-jani.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 number-of-1-bits/Cyjin-jani.js diff --git a/number-of-1-bits/Cyjin-jani.js b/number-of-1-bits/Cyjin-jani.js new file mode 100644 index 0000000000..e8011574b4 --- /dev/null +++ b/number-of-1-bits/Cyjin-jani.js @@ -0,0 +1,29 @@ +// tc: O(logn) +// sc: O(logn) +const hammingWeight_simple = function (n) { + const binaryStr = n.toString(2); + let answer = 0; + + for (char of binaryStr) { + if (+char === 1) { + answer++; + } + } + + return answer; +}; + +// toString(2)를 쓰지 않고 처리 +// tc: O(logn) +// sc: O(1) +const hammingWeight = function (n) { + let answer = 0; + + while (n>= 0) { + const remains = n % 2; + if (remains === 1) answer++; + n = Math.floor(n / 2); + } + + return answer; +}; From 6e34e71008c48af1879f14e68af872f05fd6646c Mon Sep 17 00:00:00 2001 From: juhui Date: 2026年3月17日 17:26:21 +0900 Subject: [PATCH 014/526] WEEK 3 Solutions --- number-of-1-bits/juhui-jeong.java | 64 +++++++++++++++++++++++++++++++ valid-palindrome/juhui-jeong.java | 12 ++++++ 2 files changed, 76 insertions(+) create mode 100644 number-of-1-bits/juhui-jeong.java create mode 100644 valid-palindrome/juhui-jeong.java diff --git a/number-of-1-bits/juhui-jeong.java b/number-of-1-bits/juhui-jeong.java new file mode 100644 index 0000000000..357bf66cc9 --- /dev/null +++ b/number-of-1-bits/juhui-jeong.java @@ -0,0 +1,64 @@ +/* +// 첫번째 풀이, +// int -> string -> bit -> length +// 형변환을 하지 않고 하는 방법 필요 +class Solution { + public int hammingWeight(int n) { + String intConvertBit = String.format("%32s", Integer.toBinaryString(n)).replaceAll(" ", "0"); + + return intConvertBit.replaceAll("0", "").length(); + } +} + +// 32비트로 굳이 변환할 필요가 없는데..? +// 음수는 안들어오니, 비트 변환 후 바로 체크하여 반환 +class Solution { + public int hammingWeight(int n) { + return Integer.toBinaryString(n).replaceAll("0", "").length(); + } +} + +// 두번째 풀이, +// length말고 counting으로? +class Solution { + public int hammingWeight(int n) { + String s = Integer.toBinaryString(n); + + int count = 0; + for (char c: s.toCharArray()) { + if (c == '1') count++; + } + + return count; + } +} + +// 세번째 풀이 +// int형 그대로 사용(달레님 강의 참고하여 풀이) +// 10진수를 0이 될 때까지 계속 2로 나누고 나머지를 모두 연결한다. +class Solution { + public int hammingWeight(int n) { + int cnt = 0; + while (n> 0) { + cnt += n % 2; + n = n /2; + } + return cnt; + } +} + */ + +// 네번째 풀이 +// 비트 조작을 통한 풀이 +// 마지막 비트가 1인지 확인 +// 비트를 오른쪽으로 한 칸 이동시키고, 왼쪽 빈자리를 0으로 채움 +class Solution { + public int hammingWeight(int n) { + int cnt = 0; + while (n> 0) { + cnt += (n & 1); + n>>>= 1; + } + return cnt; + } +} diff --git a/valid-palindrome/juhui-jeong.java b/valid-palindrome/juhui-jeong.java new file mode 100644 index 0000000000..2263ef5006 --- /dev/null +++ b/valid-palindrome/juhui-jeong.java @@ -0,0 +1,12 @@ +class Solution { + public boolean isPalindrome(String s) { + s = s.replaceAll("[^a-zA-Z0-9]", "").trim().toLowerCase(); + if (s.equals("")) return true; + + String[] strArr = s.split(""); + for (int i = 0; i < strArr.length/2; i++) { + if (!strArr[i].equals(strArr[strArr.length-1-i])) return false; + } + return true; + } +} From 0439ac7eaa2ddbb62990f8e7836f2322afa8b91b Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: 2026年3月17日 20:25:24 +0900 Subject: [PATCH 015/526] sadie100: number of 1 bits solution --- number-of-1-bits/sadie100.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 number-of-1-bits/sadie100.ts diff --git a/number-of-1-bits/sadie100.ts b/number-of-1-bits/sadie100.ts new file mode 100644 index 0000000000..deb1a4af69 --- /dev/null +++ b/number-of-1-bits/sadie100.ts @@ -0,0 +1,14 @@ +/** +n을 이진수 변환하고 1의 개수를 센다 + +시간복잡도 O(N) (N은 숫자 n의 비트 개수) + */ + +function hammingWeight(n: number): number { + const binaryNum = n.toString(2) + let result = 0 + for (let char of binaryNum) { + if (char === '1') result += 1 + } + return result +} From c36dd0c024e0030aab4dc345fe46387572b6f4c7 Mon Sep 17 00:00:00 2001 From: mrlee7 Date: 2026年3月17日 21:20:38 +0900 Subject: [PATCH 016/526] number of 1 bits solution --- number-of-1-bits/mrlee7.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 number-of-1-bits/mrlee7.py diff --git a/number-of-1-bits/mrlee7.py b/number-of-1-bits/mrlee7.py new file mode 100644 index 0000000000..dae830146c --- /dev/null +++ b/number-of-1-bits/mrlee7.py @@ -0,0 +1,9 @@ +class Solution: + def hammingWeight(self, n: int) -> int: + result = 0 + + while n> 0: + result += n % 2 + n //= 2 + return result + From 203d69c39bea03ba1aa427bfeb6a3898773d8d91 Mon Sep 17 00:00:00 2001 From: mrlee7 Date: 2026年3月17日 21:21:14 +0900 Subject: [PATCH 017/526] formatting code --- number-of-1-bits/mrlee7.py | 1 - 1 file changed, 1 deletion(-) diff --git a/number-of-1-bits/mrlee7.py b/number-of-1-bits/mrlee7.py index dae830146c..6b1b7f37d8 100644 --- a/number-of-1-bits/mrlee7.py +++ b/number-of-1-bits/mrlee7.py @@ -6,4 +6,3 @@ def hammingWeight(self, n: int) -> int: result += n % 2 n //= 2 return result - From bbc7cbacab5498b25f00fca77e6a2846d5421f33 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年3月17日 23:02:23 +0900 Subject: [PATCH 018/526] init --- valid-palindrome/hyeri0903.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 valid-palindrome/hyeri0903.py diff --git a/valid-palindrome/hyeri0903.py b/valid-palindrome/hyeri0903.py new file mode 100644 index 0000000000..e69de29bb2 From cd02770a7efd3bfe65744da1bf24bbcb1e4edd70 Mon Sep 17 00:00:00 2001 From: DongHun Date: 2026年3月18日 00:00:00 +0900 Subject: [PATCH 019/526] Solve number-of-1-bits --- number-of-1-bits/OstenHun.cpp | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 number-of-1-bits/OstenHun.cpp diff --git a/number-of-1-bits/OstenHun.cpp b/number-of-1-bits/OstenHun.cpp new file mode 100644 index 0000000000..6381f18928 --- /dev/null +++ b/number-of-1-bits/OstenHun.cpp @@ -0,0 +1,42 @@ +/* + 191. Number of 1 Bits + + Given a positive integer n, write a function + that returns the number of set bits in its binary representation + (also known as the Hamming weight). + + Example 1: + Input: n = 11 + Output: 3 + + Explanation: + The input binary string 1011 has a total of three set bits. + + Constraints: + 1 <= n <= 2^31 - 1 +*/ + +// 비트 연산을 이용하여 풀기 +#include +using namespace std; + +class Solution { +public: + int hammingweight(int n) { + unsigned int answer = 0; + while(n>0) { + if (n & 1) + answer++; + n = n>> 1; + } + return answer; + } +}; + +int main() { + int n; + cin>> n; + Solution s; + + cout << s.hammingweight(n); +} From c055eff98e02f225eef3b46b03f8a99a25079597 Mon Sep 17 00:00:00 2001 From: DongHun Date: 2026年3月18日 01:46:06 +0900 Subject: [PATCH 020/526] Refine number-of-1-bits solution --- number-of-1-bits/OstenHun.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/number-of-1-bits/OstenHun.cpp b/number-of-1-bits/OstenHun.cpp index 6381f18928..7e280e0e7a 100644 --- a/number-of-1-bits/OstenHun.cpp +++ b/number-of-1-bits/OstenHun.cpp @@ -20,6 +20,9 @@ #include using namespace std; +// 시간 복잡도 : O(logn) -> n>> 1 연산을 하기 때문에 절반씩 줄어듬 +// 문제의 조건은 32bit 내의 범위이기 때문에 32번의 반복으로 항상 끝나기에 O(1)이라고 할 수 있다. +// 공간 복잡도 : O(1) class Solution { public: int hammingweight(int n) { @@ -29,14 +32,20 @@ class Solution { answer++; n = n>> 1; } + + // 처음 풀었던 풀이. + // unsigned int answer = 0; + // for (int i = 0; i < 32; i++) { + // if ((n>> i) & 1) answer++; + // } + + // 생각 못 한 풀이 + // -> n & (n-1) 을 하면 가장 오른쪽 1비트를 지운다. + // while (n> 0) { + // n &= (n - 1); + // answer++; + // } + return answer; } }; - -int main() { - int n; - cin>> n; - Solution s; - - cout << s.hammingweight(n); -} From 95555e7221474c182986f4d4386c1626aa53786d Mon Sep 17 00:00:00 2001 From: robin Date: 2026年3月18日 03:59:37 +0900 Subject: [PATCH 021/526] valid-palindrome --- valid-palindrome/nowrobin.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 valid-palindrome/nowrobin.js diff --git a/valid-palindrome/nowrobin.js b/valid-palindrome/nowrobin.js new file mode 100644 index 0000000000..86049f76c7 --- /dev/null +++ b/valid-palindrome/nowrobin.js @@ -0,0 +1,23 @@ +/** + * @param {string} s + * @return {boolean} + */ +var isPalindrome = function(s) { + // 1. 소문자로 변환 + 알파벳/숫자만 남기기 + // (공백, 특수문자 제거) + s = s.toLowerCase().replace(/[^a-z0-9]/g, ""); + + const length = s.length; + + // 2. 문자열의 절반만 순회하면서 양쪽 비교 + for (let i = 0; i < length / 2; i++) { + // 왼쪽(i) vs 오른쪽(length - 1 - i) + if (s[i] !== s[length - 1 - i]) { + // 하나라도 다르면 팰린드롬 아님 + return false; + } + } + + // 3. 끝까지 문제 없으면 팰린드롬 + return true; +}; \ No newline at end of file From 7b3401fdd44f6afc1f122b4dd4f63684d44460a8 Mon Sep 17 00:00:00 2001 From: robin Date: 2026年3月18日 04:07:40 +0900 Subject: [PATCH 022/526] number of 1 bits solution --- number-of-1-bits/nowrobin.js | 21 +++++++++++++++++++++ valid-palindrome/nowrobin.js | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 number-of-1-bits/nowrobin.js diff --git a/number-of-1-bits/nowrobin.js b/number-of-1-bits/nowrobin.js new file mode 100644 index 0000000000..cf33dc9b82 --- /dev/null +++ b/number-of-1-bits/nowrobin.js @@ -0,0 +1,21 @@ +/** + * @param {number} n - 32비트 정수 + * @return {number} - 이진수에서 1의 개수 + */ +var hammingWeight = function(n) { + let setBitCount = 0; // 1의 개수를 저장할 변수 + + // n이 0이 될 때까지 반복 (모든 1비트를 제거할 때까지) + while (n !== 0) { + // 가장 오른쪽에 있는 1비트를 제거 + // 예: 101100 -> 101000 + n &= (n - 1); + + // 1비트 하나 제거했으므로 카운트 증가 + setBitCount++; + } + + // 총 1의 개수 반환 + return setBitCount; +}; + diff --git a/valid-palindrome/nowrobin.js b/valid-palindrome/nowrobin.js index 86049f76c7..cc4fdecaeb 100644 --- a/valid-palindrome/nowrobin.js +++ b/valid-palindrome/nowrobin.js @@ -20,4 +20,4 @@ var isPalindrome = function(s) { // 3. 끝까지 문제 없으면 팰린드롬 return true; -}; \ No newline at end of file +}; From 955cce81aa6b2b333c5241203a9b2ee951f9d28c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=EC=98=81?= Date: 2026年3月18日 09:15:36 +0900 Subject: [PATCH 023/526] =?UTF-8?q?number-of-1-bits=20=ED=92=80=EC=9D=B4?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- number-of-1-bits/junzero741.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 number-of-1-bits/junzero741.ts diff --git a/number-of-1-bits/junzero741.ts b/number-of-1-bits/junzero741.ts new file mode 100644 index 0000000000..2c8aa49cdc --- /dev/null +++ b/number-of-1-bits/junzero741.ts @@ -0,0 +1,13 @@ +// TC: O(log n) +// SC: O(1) +function hammingWeight(n: number): number { + const binary = n.toString(2); + let bits = 0; + for(let i = 0; i < binary.length; i++) { + if(binary[i] === '1') { + bits++; + } + } + + return bits; +}; From 95cc89bf3918b07166f955da0e5fce57cb7b5093 Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: 2026年3月18日 10:47:46 +0900 Subject: [PATCH 024/526] combination sum solution --- combination-sum/robinyoon-dev.js | 36 ++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 combination-sum/robinyoon-dev.js diff --git a/combination-sum/robinyoon-dev.js b/combination-sum/robinyoon-dev.js new file mode 100644 index 0000000000..72c70ed2ed --- /dev/null +++ b/combination-sum/robinyoon-dev.js @@ -0,0 +1,36 @@ +/** + * @param {number[]} candidates + * @param {number} target + * @return {number[][]} + */ +var combinationSum = function (candidates, target) { + + const result = []; + + function dfs(remainTarget, currentArray, currentIndex) { + + if (remainTarget < 0) { + return; + } + + if (remainTarget == 0) { + result.push([...currentArray]); + return; + } + + // 백트래킹 탐색 + for (let i = currentIndex; i < candidates.length; i++) { + currentArray.push(candidates[i]); + + dfs(remainTarget - candidates[i], currentArray, i); + + currentArray.pop(); + } + + } + + dfs(target, [], 0); + + return result; + +}; From f011d0f7b362c96e2b390449a4bda106520c473e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年3月18日 13:44:11 +0900 Subject: [PATCH 025/526] Add solution for Decode Ways problem --- decode-ways/gcount85.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 decode-ways/gcount85.py diff --git a/decode-ways/gcount85.py b/decode-ways/gcount85.py new file mode 100644 index 0000000000..fb1ebe33b3 --- /dev/null +++ b/decode-ways/gcount85.py @@ -0,0 +1,29 @@ +""" +# Intuition +dp[n]은 s의 n번째 글자까지 디코딩할수 있는 경우의 수 +dp[n] = dp[n-1](if can be decoded) + dp[n-2](if can be decoded) + +# Approach +i-1 ~ i까지의 숫자, i-2 ~ i까지의 숫자가 각각 디코딩 될 수 있는지 확인한다. +디코딩 가능하면 그 위치의 dp 배열의 값을 각각 더하고, 디코딩 불가능하면 더하지 않는다. + +# Complexity +- Time complexity: N을 s의 길이라고 할 때, 반복문으로 O(N) + +- Space complexity: dp 배열 만드는 데에 O(N) +""" + + +class Solution: + def numDecodings(self, s: str) -> int: + n = len(s) + dp = [0] * (n + 1) + dp[1] = 1 if s[0] != "0" else 0 + if dp[1] == 0 or n == 1: + return dp[1] + dp[2] = 1 if int(s[1])> 0 else 0 + dp[2] += 1 if int(s[:2])> 9 and int(s[:2]) < 27 else 0 + for i in range(3, n + 1): + dp[i] = dp[i - 1] if s[i - 1 : i] != "0" else 0 + dp[i] += dp[i - 2] if s[i - 2 : i]> "09" and s[i - 2 : i] < "27" else 0 + return dp[n] From e004f3814b13e11a0b4628999fcf68a95b9a95ee Mon Sep 17 00:00:00 2001 From: Ted Date: 2026年3月18日 00:50:06 -0400 Subject: [PATCH 026/526] add week 3 solutions --- combination-sum/tedkimdev.rs | 29 +++++++++++++++++++++++++++++ decode-ways/tedkimdev.rs | 34 ++++++++++++++++++++++++++++++++++ maximum-subarray/tedkimdev.rs | 16 ++++++++++++++++ number-of-1-bits/tedkimdev.rs | 13 +++++++++++++ valid-palindrome/tedkimdev.rs | 23 +++++++++++++++++++++++ 5 files changed, 115 insertions(+) create mode 100644 combination-sum/tedkimdev.rs create mode 100644 decode-ways/tedkimdev.rs create mode 100644 maximum-subarray/tedkimdev.rs create mode 100644 number-of-1-bits/tedkimdev.rs create mode 100644 valid-palindrome/tedkimdev.rs diff --git a/combination-sum/tedkimdev.rs b/combination-sum/tedkimdev.rs new file mode 100644 index 0000000000..68cd60bc27 --- /dev/null +++ b/combination-sum/tedkimdev.rs @@ -0,0 +1,29 @@ +// SC: O(2^t/m) +// TC: O(t/m) +impl Solution { + pub fn combination_sum(nums: Vec, target: i32) -> Vec> { + let mut res: Vec> = vec![]; + + fn dfs(nums: &[i32], target: i32, i: usize, cur: &mut Vec, mut sum: i32, res: &mut Vec>) { + if sum == target { + res.push(cur.clone()); + return; + } + if i>= nums.len() || sum> target { + return; + } + + sum += nums[i]; + cur.push(nums[i]); + dfs(nums, target, i, cur, sum, res); + + sum -= nums[i]; + cur.pop(); + dfs(nums, target, i+1, cur, sum, res); + } + + dfs(&nums, target, 0, &mut vec![], 0, &mut res); + + res + } +} diff --git a/decode-ways/tedkimdev.rs b/decode-ways/tedkimdev.rs new file mode 100644 index 0000000000..b141047d0d --- /dev/null +++ b/decode-ways/tedkimdev.rs @@ -0,0 +1,34 @@ +// SC: O(t/m) -> maximum recursion depth +// TC: O(2^(t/m)) +// t = target value +// m = smallest number in nums +// t/m = maximum number of elements in a combination +impl Solution { + pub fn num_decodings(s: String) -> i32 { + if s.starts_with('0') { + return 0; + } + + // dfs + fn dfs(s: &str) -> i32 { + if s.is_empty() { + return 1; + } + + let mut output = 0; + if s[..1].parse::().unwrap() != 0 { + output += dfs(&s[1..]); + } + if s.len()>= 2 && !s[..2].starts_with('0') { + if s[..2].parse::().unwrap()> 26 { + return output; + } else { + output += dfs(&s[2..]); + } + } + output + } + dfs(&s) + } + +} diff --git a/maximum-subarray/tedkimdev.rs b/maximum-subarray/tedkimdev.rs new file mode 100644 index 0000000000..de9c4b81ab --- /dev/null +++ b/maximum-subarray/tedkimdev.rs @@ -0,0 +1,16 @@ +// SC: O(1) +// TC: O(n) +impl Solution { + pub fn max_sub_array(nums: Vec) -> i32 { + let mut max_sub = nums[0]; + let mut cur_sum = 0; + for &num in &nums { + if cur_sum < 0 { + cur_sum = 0; + } + cur_sum += num; + max_sub = max_sub.max(cur_sum); + } + max_sub + } +} diff --git a/number-of-1-bits/tedkimdev.rs b/number-of-1-bits/tedkimdev.rs new file mode 100644 index 0000000000..8c771cac02 --- /dev/null +++ b/number-of-1-bits/tedkimdev.rs @@ -0,0 +1,13 @@ +// TC: O(1) +// SC: O(1) +impl Solution { + pub fn hamming_weight(n: u32) -> i32 { + let mut count: i32 = 0; + for i in 0..32 { + if n & (1u32 << i) != 0 { + count += 1; + } + } + count + } +} diff --git a/valid-palindrome/tedkimdev.rs b/valid-palindrome/tedkimdev.rs new file mode 100644 index 0000000000..6235e8f1a9 --- /dev/null +++ b/valid-palindrome/tedkimdev.rs @@ -0,0 +1,23 @@ +// TC: O(n) +// SC: O(1) +impl Solution { + pub fn is_palindrome(s: String) -> bool { + let s = s.as_bytes(); + let (mut l, mut r) = (0i32, s.len() as i32 - 1); + + while l < r { + while l < r && !s[l as usize].is_ascii_alphanumeric() { + l += 1; + } + while r> l && !s[r as usize].is_ascii_alphanumeric() { + r -= 1; + } + if s[l as usize].to_ascii_lowercase() != s[r as usize].to_ascii_lowercase() { + return false; + } + l += 1; + r -= 1; + } + true + } +} \ No newline at end of file From c911f4ea14dd63eb5eb7e28e72b67c9172be0618 Mon Sep 17 00:00:00 2001 From: Ted Date: 2026年3月18日 00:52:56 -0400 Subject: [PATCH 027/526] fix lint error --- valid-palindrome/tedkimdev.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/valid-palindrome/tedkimdev.rs b/valid-palindrome/tedkimdev.rs index 6235e8f1a9..c132dad4fc 100644 --- a/valid-palindrome/tedkimdev.rs +++ b/valid-palindrome/tedkimdev.rs @@ -20,4 +20,4 @@ impl Solution { } true } -} \ No newline at end of file +} From 80d99913b15399a587ad4e90ec34018e5a07725c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年3月18日 14:00:09 +0900 Subject: [PATCH 028/526] Add solution for Maximum Subarray problem --- maximum-subarray/gcount85.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 maximum-subarray/gcount85.py diff --git a/maximum-subarray/gcount85.py b/maximum-subarray/gcount85.py new file mode 100644 index 0000000000..19cc410040 --- /dev/null +++ b/maximum-subarray/gcount85.py @@ -0,0 +1,19 @@ +""" +# Intuition +max(전 위치까지의 sum + 지금 위치 값, 지금 위치의 값) + +# Complexity +- Time complexity: nums의 길이를 N이라고 할 때 O(N) + +- Space complexity: O(1) +""" + + +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + a = nums[0] + best = a + for i in range(1, len(nums)): + a = max(a + nums[i], nums[i]) + best = max(a, best) + return best From ec750c0cd7c721cc32d8b0829321620ec71b710b Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年3月18日 14:31:23 +0900 Subject: [PATCH 029/526] [7th batch] week 3 - valid palindrome --- valid-palindrome/liza0525.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/valid-palindrome/liza0525.py b/valid-palindrome/liza0525.py index b6e0ac8ffa..38f24b3389 100644 --- a/valid-palindrome/liza0525.py +++ b/valid-palindrome/liza0525.py @@ -24,3 +24,33 @@ def isPalindrome(self, s: str) -> bool: return False return True + + +# 7기 풀이 +# 시간 복잡도: O(n) +# - 문자열 s의 전체 문자를 순회할 때 길이 n만큼의 시간 소요 +# 공간 복잡도: O(1) +# - start, end 등의 변수만 사용 + +class Solution: + def isPalindrome(self, s: str) -> bool: + # two pointer로 각 문자열을 비교하며 palindrome인지 체크한다. + # 해당 문제의 조건 중 하나가 alphanumeric한 문자만 체크하는 것 + start, end = 0, len(s) - 1 + + # 양 끝의 포인터 인덱스가 같아지기 전까지 루프를 돌린다. + while start < end: + if not s[start].isalnum(): + # s[start] 문자가 alphanumeric하지 않은 경우엔 start 포인터를 오른쪽으로 한 칸 이동 + start += 1 + continue + if not s[end].isalnum(): + # s[end] 문자가 alphanumeric하지 않은 경우엔 end 포인터를 왼쪽으로 한 칸 이동 + end -= 1 + continue + if s[start].lower() != s[end].lower(): + # 두 문자의 lowercase가 동일하지 않은 경우에는 palindrome이 아니므로 False로 early return 해준다. + return False + start, end = start + 1, end - 1 + # while 루프가 다 돌았다면 조건에 걸리지 않고 palindrome임을 충족하므로 True를 return + return True From 77a30889e6a399f7dd9fcfb3c6667e54387528e9 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年3月18日 15:15:00 +0900 Subject: [PATCH 030/526] [7th batch] week 3 - number of 1 bits --- number-of-1-bits/liza0525.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/number-of-1-bits/liza0525.py b/number-of-1-bits/liza0525.py index da1678834b..48f8a7162a 100644 --- a/number-of-1-bits/liza0525.py +++ b/number-of-1-bits/liza0525.py @@ -20,3 +20,27 @@ def hammingWeight(self, n: int) -> int: n = n // 2 return bits_sum + + +# 7기 풀이 +# 시간 복잡도: O(log n) +# - 2로 계속 나누고, 이는 2진수 자릿수 만큼 반복 +# 공간 복잡도: O(1) +# - 고정된 변수(quotient, remainder)만 사용 +class Solution: + def hammingWeight(self, n: int) -> int: + # 10진수를 2진수로 변환하는 과정은 2로 계속 나누면서 그 나머지 값들을 순차적으로 나열하는 것이다. + # 이 때 문자열로 만들지 않고 바로 result에 더해가면 답이 될 수 있음 + result = 0 + + while n> 0: + # 몫과 나머지 계산 + quotient, remainder = n // 2, n % 2 + + # 나머지는 result에 더함 + result += remainder + + # 몫은 다음 피제수로 사용 + n = quotient + + return result From fe1cfaa34134f4bff6aee3b614984aa78dc2082f Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年3月18日 15:43:52 +0900 Subject: [PATCH 031/526] =?UTF-8?q?3=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=202=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Decode Ways - Maximum Subarray --- decode-ways/hwi-middle.cpp | 34 +++++++++++++++++++++++++++++++ valid-palindrome/hwi-middle.cpp | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 decode-ways/hwi-middle.cpp create mode 100644 valid-palindrome/hwi-middle.cpp diff --git a/decode-ways/hwi-middle.cpp b/decode-ways/hwi-middle.cpp new file mode 100644 index 0000000000..2152eb51b2 --- /dev/null +++ b/decode-ways/hwi-middle.cpp @@ -0,0 +1,34 @@ +class Solution { +public: + int numDecodings(string s) { + int d[101]; + int len = s.size(); + + if (s[0] == '0') // 0으로 시작할 수 없음 + { + return 0; + } + + d[0] = 1; // 빈 문자열 -> 1가지 방법 + d[1] = 1; // 첫 문자 -> 1가지 방법 (0이 아닌건 확인했음) + + for (int i = 2; i <= len; ++i) + { + d[i] = 0; + + // 0이 아니어서 단독으로 해석 가능한 경우 + if (s[i - 1] != '0') + { + d[i] += d[i - 1]; + } + + // 앞글자와 조합해서 유효한 두 자리가 될 수 있는 경우 + if (s[i - 2] == '1' || (s[i - 2] == '2' && s[i - 1] <= '6')) + { + d[i] += d[i - 2]; + } + } + + return d[len]; + } +}; diff --git a/valid-palindrome/hwi-middle.cpp b/valid-palindrome/hwi-middle.cpp new file mode 100644 index 0000000000..3a39c79447 --- /dev/null +++ b/valid-palindrome/hwi-middle.cpp @@ -0,0 +1,36 @@ +class Solution { +public: + bool isPalindrome(string s) { + int len = s.size(); + int l = 0; + int r = len - 1; + + while (l <= r) + { + while (l <= r &&!isalnum(s[l])) + { + l++; + } + + while (l <= r && !isalnum(s[r])) + { + r--; + } + + if (l> r) + { + break; + } + + if (tolower(s[l]) != tolower(s[r])) + { + return false; + } + + l++; + r--; + } + + return true; + } +}; From 42be3de31ea64c254b100f00693234beeddb1b3f Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年3月18日 15:47:26 +0900 Subject: [PATCH 032/526] =?UTF-8?q?3=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=201=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Maximum Subarray --- maximum-subarray/hwi-middle.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 maximum-subarray/hwi-middle.cpp diff --git a/maximum-subarray/hwi-middle.cpp b/maximum-subarray/hwi-middle.cpp new file mode 100644 index 0000000000..7349d26576 --- /dev/null +++ b/maximum-subarray/hwi-middle.cpp @@ -0,0 +1,20 @@ +class Solution { +public: + int maxSubArray(vector& nums) { + int cur = 0; + int ans = -1e5; + for (int n : nums) + { + // 이전까지 합이 음수라면 무조건 다시 시작하는게 이득 + if (cur < 0) + { + cur = 0; + } + + cur += n; + ans = max(cur, ans); + } + + return ans; + } +}; From e65d4d4f471f0789bb8717b900e65db5e4112c1d Mon Sep 17 00:00:00 2001 From: YOOHYOJEONG Date: 2026年3月18日 15:56:59 +0900 Subject: [PATCH 033/526] week03_1_2_3_solution --- combination-sum/YOOHYOJEONG.py | 31 +++++++++++++++++++++++++++++++ number-of-1-bits/YOOHYOJEONG.py | 6 ++++++ valid-palindrome/YOOHYOJEONG.py | 22 ++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 combination-sum/YOOHYOJEONG.py create mode 100644 number-of-1-bits/YOOHYOJEONG.py create mode 100644 valid-palindrome/YOOHYOJEONG.py diff --git a/combination-sum/YOOHYOJEONG.py b/combination-sum/YOOHYOJEONG.py new file mode 100644 index 0000000000..02dc739e61 --- /dev/null +++ b/combination-sum/YOOHYOJEONG.py @@ -0,0 +1,31 @@ +# https://leetcode.com/problems/combination-sum/ + +# for문으로 해결이 되지 않아 gpt 도움을 받아 해결하였습니다. +# 같은 숫자를 재사용하면서, 순서를 고정해서 중복 없는 조합을 DFS로 탐색하는 구조 +# 시간 복잡도 : O(2^n) (백트래킹 탐색) +# 공간 복잡도 : O(target) (재귀 깊이) + +class Solution(object): + def combinationSum(self, candidates, target): + + result = [] + + def dfs(start, path, total): + # 종료 조건 1 : target을 맞춘 경우 + if total == target: + result.append(path[:]) + return + + # 종료 조건 2 : target 초과한 경우 + if total> target: + return + + # 후보 탐색 -> 같은 방향으로만 탐색 + for i in range(start, len(candidates)): + # 같은 숫자 재사용 가능 -> i를 그대로 넘기기 + dfs(i, path+[candidates[i]], total+candidates[i]) # 새로운 리스트 만들어서 전달 + + + dfs(0, [], 0) + + return result diff --git a/number-of-1-bits/YOOHYOJEONG.py b/number-of-1-bits/YOOHYOJEONG.py new file mode 100644 index 0000000000..3c9e5b92b4 --- /dev/null +++ b/number-of-1-bits/YOOHYOJEONG.py @@ -0,0 +1,6 @@ +# https://leetcode.com/problems/number-of-1-bits + +class Solution(object): + def hammingWeight(self, n): + binary = bin(n)[2:] + return len(str(binary).replace('0', '')) diff --git a/valid-palindrome/YOOHYOJEONG.py b/valid-palindrome/YOOHYOJEONG.py new file mode 100644 index 0000000000..89b44ab329 --- /dev/null +++ b/valid-palindrome/YOOHYOJEONG.py @@ -0,0 +1,22 @@ +# https://leetcode.com/problems/valid-palindrome + +# re.sub -> O(n) +# lower() -> O(n) +# reverse -> O(n) +# 최종 시간 복잡도 : O(n) + O(n) + O(n) + O(n) = O(n) + +# s_pali -> 최대 O(n) +# s_pali_reverse -> O(n) +# 최종 공간 복잡도 : O(n) + +import re + +class Solution(object): + def isPalindrome(self, s): + s_pali = re.sub(r'[^a-zA-Z0-9]', '', s).lower() + s_pali_reverse = s_pali[::-1] + + if s_pali == s_pali_reverse: + return True + else: + return False From d8ba0d176463e5f12238e19765cc5997c0aaef4f Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年3月18日 15:57:18 +0900 Subject: [PATCH 034/526] [7th batch] week 3 - combination sum --- combination-sum/liza0525.py | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/combination-sum/liza0525.py b/combination-sum/liza0525.py index 8f5140f4f0..ccd5eec13e 100644 --- a/combination-sum/liza0525.py +++ b/combination-sum/liza0525.py @@ -38,3 +38,42 @@ def dfs(target_list, start_i): dfs([], 0) return results + + +# 7기 풀이 +# T: target 수, C: candidates의 최소값일 때, +# 시간 복잡도: O(n ^ (T/C)) +# - 최악의 경우는 가장 작은 candidate로 target을 만드는 횟수만큼 candidates를 탐색할 때이다. (dominant) +# - sorting은 O(n log n)이며, 무시 가능 +# 공간 복잡도: O(T/C) +# - dfs의 call stack의 깊이는 T/C가 최대 깊이 +# - result의 조합 또한 T/C가 최대 길이 +class Solution: + # DFS로 문제를 풀이하며 조건에 맞춰 가지치기가 필요한 문제 + # 문제 풀이 편의를 위해 candidates를 sorting한 후 풀이를 한다. + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + candidates.sort() + results = [] + + def dfs(target, result): + if target == 0: + # 더이상 target을 만드는데 숫자가 필요하지 않으므로 + # 정답 array에 deepcopy하여 저장 + results.append(result[:]) + return + + for candidate in candidates: + if candidate> target: + # 후보 수가 target보다 크면 그 이후의 수는 더이상 탐색하지 않아도 된다 + return + if result and candidate < result[-1]: + # 후보 수가 result의 마지막 수보다 크면 skip한다(result 내 숫자들도 작은 수부터 저장되게 함) + continue + result.append(candidate) + # target에서 candidate를 뺀 만큼 다음 stack 계산을 한다. + dfs(target - candidate, result) + result.pop() + + dfs(target, []) + + return results From 69e7b0e21864412c0ce1ab8f227625e46a51a360 Mon Sep 17 00:00:00 2001 From: JIHOON LEE Date: 2026年3月18日 16:01:18 +0900 Subject: [PATCH 035/526] 3Week - valid-palindrome --- valid-palindrome/jiji-hoon96.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/valid-palindrome/jiji-hoon96.ts b/valid-palindrome/jiji-hoon96.ts index e69de29bb2..4836a7fa60 100644 --- a/valid-palindrome/jiji-hoon96.ts +++ b/valid-palindrome/jiji-hoon96.ts @@ -0,0 +1,20 @@ +function isPalindrome(s: string): boolean { + const word = s.replace(/[^a-zA-Z0-9]/g, "").toLowerCase(); + if (word.length === 0) { + return true; + } + + for (let i = word.length - 1; i>= 0; i--) { + if (word[i] !== word[word.length - 1 - i]) { + return false; + } + } + + return true; +} + +isPalindrome("A man, a plan, a canal: Panama"); // true +isPalindrome("race a car"); // false +isPalindrome(" "); // true +isPalindrome("0P"); // false +isPalindrome("a"); // true From 8c3337cf306e99dab6ca59d8760334418ad01816 Mon Sep 17 00:00:00 2001 From: JIHOON LEE Date: 2026年3月18日 16:02:27 +0900 Subject: [PATCH 036/526] 3Week - number-of-1-bits --- number-of-1-bits/jiji-hoon96.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/number-of-1-bits/jiji-hoon96.ts b/number-of-1-bits/jiji-hoon96.ts index e69de29bb2..32a82b4cb8 100644 --- a/number-of-1-bits/jiji-hoon96.ts +++ b/number-of-1-bits/jiji-hoon96.ts @@ -0,0 +1,10 @@ +function hammingWeight(n: number): number { + let count = 0; + + while (n !== 0) { + n &= n - 1; + count++; + } + + return count; +} From 41463f633f9d4006b51c95310827c8d09df9fe68 Mon Sep 17 00:00:00 2001 From: JIHOON LEE Date: 2026年3月18日 16:39:21 +0900 Subject: [PATCH 037/526] 3Week - maximum-subarray --- combination-sum/jiji-hoon96.ts | 5 +++++ decode-ways/jiji-hoon96.ts | 5 +++++ maximum-subarray/jiji-hoon96.ts | 15 +++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/combination-sum/jiji-hoon96.ts b/combination-sum/jiji-hoon96.ts index e69de29bb2..676a0e5880 100644 --- a/combination-sum/jiji-hoon96.ts +++ b/combination-sum/jiji-hoon96.ts @@ -0,0 +1,5 @@ +function combinationSum(candidates: number[], target: number): number[][] {} + +combinationSum([2, 3, 6, 7], 7); // [[2,2,3], [7]] +combinationSum([2, 3, 5], 8); // [[2,2,2,2],[2,3,3],[3,5]] +combinationSum([2], 1); // [] diff --git a/decode-ways/jiji-hoon96.ts b/decode-ways/jiji-hoon96.ts index e69de29bb2..c982544147 100644 --- a/decode-ways/jiji-hoon96.ts +++ b/decode-ways/jiji-hoon96.ts @@ -0,0 +1,5 @@ +function numDecodings(s: string): number {} + +numDecodings("12"); // 2 +numDecodings("226"); // 3 +numDecodings("06"); // 0 diff --git a/maximum-subarray/jiji-hoon96.ts b/maximum-subarray/jiji-hoon96.ts index e69de29bb2..f2a9b50197 100644 --- a/maximum-subarray/jiji-hoon96.ts +++ b/maximum-subarray/jiji-hoon96.ts @@ -0,0 +1,15 @@ +function maxSubArray(nums: number[]): number { + let currentSum = nums[0]; + let maxSum = nums[0]; + + for (let i = 1; i < nums.length; i++) { + currentSum = Math.max(currentSum + nums[i], nums[i]); + maxSum = Math.max(currentSum, maxSum); + } + + return maxSum; +} + +maxSubArray([-2, 1, -3, 4, -1, 2, 1, -5, 4]); // 6 +maxSubArray([1]); // 1 +maxSubArray([5, 4, -1, 7, 8]); // 23 From ab9e71b4d7273315ce4fef87e3d8b5f3cc87b785 Mon Sep 17 00:00:00 2001 From: mrlee7 Date: 2026年3月18日 17:16:16 +0900 Subject: [PATCH 038/526] combination sum solution --- combination-sum/mrlee7.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 combination-sum/mrlee7.py diff --git a/combination-sum/mrlee7.py b/combination-sum/mrlee7.py new file mode 100644 index 0000000000..21ccedb871 --- /dev/null +++ b/combination-sum/mrlee7.py @@ -0,0 +1,17 @@ +class Solution: + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + result, nums = list(), list() + + def dfs(start_position, total_sum): + if total_sum> target: + return + if total_sum == target: + result.append(nums[:]) + for idx in range(start_position, len(candidates)): + num = candidates[idx] + nums.append(num) + dfs(idx, total_sum + num) + nums.pop() + + dfs(0,0) + return result \ No newline at end of file From a13f6c232f3c118bad8593a7aebe9b35ed7f95fa Mon Sep 17 00:00:00 2001 From: mrlee7 Date: 2026年3月18日 17:16:35 +0900 Subject: [PATCH 039/526] combination sum solution --- combination-sum/mrlee7.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/combination-sum/mrlee7.py b/combination-sum/mrlee7.py index 21ccedb871..6f1c3da829 100644 --- a/combination-sum/mrlee7.py +++ b/combination-sum/mrlee7.py @@ -1,3 +1,6 @@ +from typing import List + + class Solution: def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: result, nums = list(), list() @@ -13,5 +16,5 @@ def dfs(start_position, total_sum): dfs(idx, total_sum + num) nums.pop() - dfs(0,0) - return result \ No newline at end of file + dfs(0, 0) + return result From 3251a99d8f3aa42b66b6032205cd11ffb8f14a49 Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年3月18日 01:26:51 -0700 Subject: [PATCH 040/526] valid palindrome solution --- valid-palindrome/jylee2033.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 valid-palindrome/jylee2033.py diff --git a/valid-palindrome/jylee2033.py b/valid-palindrome/jylee2033.py new file mode 100644 index 0000000000..a1fb7d206e --- /dev/null +++ b/valid-palindrome/jylee2033.py @@ -0,0 +1,14 @@ +class Solution: + def isPalindrome(self, s: str) -> bool: + # 1. Remove non-alphanumeric characters and convert to lowercase + # 2. Compare with reversed string + + cleaned_s = "" + for ch in s: + if ch.isalnum(): + cleaned_s += ch.lower() + + return cleaned_s == cleaned_s[::-1] + +# Time Complexity : O(n) +# Space Complexity : O(n) From af27ccbea93050fbcce75f65f7c17f9e3069520d Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: 2026年3月18日 18:47:29 +0900 Subject: [PATCH 041/526] sadie100: combination sum solution --- combination-sum/sadie100.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 combination-sum/sadie100.ts diff --git a/combination-sum/sadie100.ts b/combination-sum/sadie100.ts new file mode 100644 index 0000000000..97f4afc9ef --- /dev/null +++ b/combination-sum/sadie100.ts @@ -0,0 +1,28 @@ +/* +dfs로 각 candidates를 돌면서 target과 같아지는 순간에 result를 반환한다. + +같은 조합이 중복됨을 피하기 위해 candidates를 정렬하고, 각 숫자보다 크거나 같은 candidate만 탐색한다. + +시간복잡도 : O(N^(T/min(c))) - N은 candidates의 수, T는 타겟, c는 candidates. +타겟을 candidates의 최소값으로 나눈 값이 최대 깊이이므로 최악의 경우 해당 횟수만큼 반복해서 배열을 탐색함 +*/ + +function combinationSum(candidates: number[], target: number): number[][] { + candidates.sort((a, b) => a - b) + const result = [] + const search = (idx, nums, sum) => { + if (sum === target) { + result.push(nums) + return + } + for (let i = idx; i < candidates.length; i++) { + const num = candidates[i] + if (sum + num> target) return + search(i, [...nums, num], sum + num) + } + } + + search(0, [], 0) + + return result +} From bb1b12e2c7b196f41551fca6bd7fc9d34bd7c1f7 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年3月18日 20:40:40 +0900 Subject: [PATCH 042/526] =?UTF-8?q?3=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=201=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Combination Sum --- combination-sum/hwi-middle.cpp | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 combination-sum/hwi-middle.cpp diff --git a/combination-sum/hwi-middle.cpp b/combination-sum/hwi-middle.cpp new file mode 100644 index 0000000000..576bc49ce2 --- /dev/null +++ b/combination-sum/hwi-middle.cpp @@ -0,0 +1,41 @@ +class Solution { +public: + vector> combinationSum(vector& candidates, int target) { + vector> res; + vector v; + + solve(candidates, target, v, 0, res, 0); + return res; + } + + /** + * @param candidates 사용할 수 있는 수의 후보 + * @param target candidates의 원소들을 사용해 만들어야하는 합계 + * @param cur 지금까지 시도한 조합 + * @param sum 사전에 계산된 cur 원소들의 합계 + * @param res 최종 결과 + * @param idx 현재까지 진행된 인덱스 (중복 방지를 위해 존재) + */ + void solve(const vector& candidates, const int target, vector& cur, int sum, vector>& res, int idx) + { + if (sum> target) + { + return; + } + + if (sum == target) + { + res.push_back(cur); + return; + } + + int len = candidates.size(); + for (int i = idx; i < len; ++i) + { + int c = candidates[i]; + cur.push_back(c); + solve(candidates, target, cur, sum + c, res, i); + cur.pop_back(); + } + } +}; From 0911277690f1b1ab3fb655dc9d12e7ae14cd25b0 Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年3月18日 10:01:26 -0700 Subject: [PATCH 043/526] number of 1 bits solution --- number-of-1-bits/jylee2033.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 number-of-1-bits/jylee2033.py diff --git a/number-of-1-bits/jylee2033.py b/number-of-1-bits/jylee2033.py new file mode 100644 index 0000000000..beaaf25255 --- /dev/null +++ b/number-of-1-bits/jylee2033.py @@ -0,0 +1,27 @@ +class Solution: + def hammingWeight(self, n: int) -> int: + # 1. Find highest power of 2 range that covers n + # 2. Greedily subtract from largest power of 2 to smallest + + # powers : 1 + 2 + 4 + 8 + 16 + ... + # total : 1 + 3 + 7 + 15 + 31 + ... + # index : 0 1 2 3 4 + + i = 0 + total = 1 + + while n> total: + i += 1 + total += 2 ** i + + count = 0 + + for j in range(i, -1, -1): + if n>= 2 ** j: + n -= 2 ** j + count += 1 + + return count + +# Time Complexity : O(log n) +# Space Complexity : O(1) From 44889eab0465d8af78f73a4a072ca215d28b86ef Mon Sep 17 00:00:00 2001 From: river Date: 2026年3月19日 04:03:19 +0900 Subject: [PATCH 044/526] number of 1 bits solution --- number-of-1-bits/riveroverflows.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 number-of-1-bits/riveroverflows.py diff --git a/number-of-1-bits/riveroverflows.py b/number-of-1-bits/riveroverflows.py new file mode 100644 index 0000000000..638a6b1de8 --- /dev/null +++ b/number-of-1-bits/riveroverflows.py @@ -0,0 +1,20 @@ +from typing import * + + +class Solution: + """ + TC: O(log n) + SC: O(1) + + 풀이: + Brian Kernighan의 비트 트릭을 활용. + n & (n-1)은 n의 가장 오른쪽 1비트를 하나 제거한다. + n이 0이 될 때까지 반복한 횟수가 곧 1비트의 개수. + """ + def hammingWeight(self, n: int) -> int: + answer = 0 + while n> 0: + n = n & (n - 1) + answer += 1 + + return answer From 49b697013579004364a9edef2e3a2fb02f2f6880 Mon Sep 17 00:00:00 2001 From: river Date: 2026年3月19日 04:51:09 +0900 Subject: [PATCH 045/526] valid palindrome solution --- valid-palindrome/riveroverflows.py | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 valid-palindrome/riveroverflows.py diff --git a/valid-palindrome/riveroverflows.py b/valid-palindrome/riveroverflows.py new file mode 100644 index 0000000000..4cf434e9c2 --- /dev/null +++ b/valid-palindrome/riveroverflows.py @@ -0,0 +1,36 @@ +class Solution: + """ + 풀이 1: 투포인터 + TC: O(n) + SC: O(1) + + 양쪽 끝에서 포인터를 좁혀가며 알파벳/숫자만 비교. + """ + def isPalindrome(self, s: str) -> bool: + l, r = 0, len(s) - 1 + while l < r: + if not s[l].isalnum(): + l += 1 + continue + if not s[r].isalnum(): + r -= 1 + continue + + if s[l].lower() != s[r].lower(): + return False + + l += 1 + r -= 1 + + return True + + """ + 풀이 2: 리스트 변환 + 역순 비교 + TC: O(n) + SC: O(n) + + 알파벳/숫자만 추출한 리스트를 역순과 비교. + """ + def isPalindrome2(self, s: str) -> bool: + s = [c for c in s.lower() if c.isalnum()] + return s == s[::-1] From c13a9ebead251435f736736b0cc1531ddb06e92b Mon Sep 17 00:00:00 2001 From: Se Hee Kim <82367039+sadie100@users.noreply.github.com> Date: 2026年3月19日 05:23:52 +0900 Subject: [PATCH 046/526] sadie100: decode ways solution --- decode-ways/sadie100.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 decode-ways/sadie100.ts diff --git a/decode-ways/sadie100.ts b/decode-ways/sadie100.ts new file mode 100644 index 0000000000..2e387fa8b1 --- /dev/null +++ b/decode-ways/sadie100.ts @@ -0,0 +1,30 @@ +/* +dp 배열을 만들고 s를 순회하며 각 단계에서 이전 자리의 숫자를 채택하거나 버리는 경우를 더해 나간다 +만약 현재 순번의 숫자가 0일 경우 : 이전 자리의 숫자를 채택, i-1 순번의 숫자가 0이거나 3 이상이면 즉시 0을 리턴. 아닐 경우 dp의 i-2번째값을 넣는다. +이전 순번의 숫자와 현재 숫자를 더한 값이 26보다 크거나 이전 순번의 숫자가 0일 경우 : 개별 자리의 숫자를 채택, 직전 dp값을 넣는다 +위에 모두 해당하지 않을 경우 : 개별 자리의 숫자를 채택하거나 버리는 경우를 다 고려하여 직전 dp값과 2스텝 전 dp값을 더한다 +맨 끝 순번에 도달했을 때의 값을 구한다 + +시간복잡도 : O(N) (N은 s의 길이) +*/ + +function numDecodings(s: string): number { + if(s.startsWith("0")) return 0; + const dp = []; + + dp.push(1); + if(s.length<2) return dp[0] + for(let i=1;i=3) return 0; + dp.push(dp?.[i-2] ?? 1) + }else if(Number(`${s[i-1]}${numStr}`)> 26 || s[i-1] === "0"){ + dp.push(dp[i-1]) + }else{ + dp.push(dp[i-1] + (dp?.[i-2] ?? 1)) + } + } + + return dp[s.length-1]; +}; \ No newline at end of file From e86ed204fbeecd8e9bad2da947af4b5c032ccd3c Mon Sep 17 00:00:00 2001 From: Se Hee Kim <82367039+sadie100@users.noreply.github.com> Date: 2026年3月19日 05:26:00 +0900 Subject: [PATCH 047/526] sadie100 : add line --- decode-ways/sadie100.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/decode-ways/sadie100.ts b/decode-ways/sadie100.ts index 2e387fa8b1..0db8d19236 100644 --- a/decode-ways/sadie100.ts +++ b/decode-ways/sadie100.ts @@ -27,4 +27,4 @@ function numDecodings(s: string): number { } return dp[s.length-1]; -}; \ No newline at end of file +}; From 49c729dd521e2b669c97c59c73920c2c7ca9527b Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年3月19日 15:19:15 +0900 Subject: [PATCH 048/526] [7th batch] week 3 - decode ways --- decode-ways/liza0525.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 decode-ways/liza0525.py diff --git a/decode-ways/liza0525.py b/decode-ways/liza0525.py new file mode 100644 index 0000000000..fc0eb091d7 --- /dev/null +++ b/decode-ways/liza0525.py @@ -0,0 +1,34 @@ +# 7기 풀이 +# 시간복잡도: O(n) +# - memoization을 하기 때문에 각 인덱스 별로 가능한 수를 계산할 때 한 번 씩만 계산 +# 공간복잡도: O(n) +# - 문자열의 길이만큼 memo 값이 늘어남 +class Solution: + # DP를 이용해 문제를 풀면 된다. + # 각 인덱스로 별로 문자열을 잘랐을 때의 가능한 디코딩 방법 수를 memo한다 + def numDecodings(self, s: str) -> int: + len_s = len(s) + memo = {} + + def dfs(index): + if index == len_s: # 끝까지 탐색했다면 가능한 디코딩 방법이므로 1을 return + return 1 + + if s[index] == '0': # 현재 index의 문자가 '0'이면 해당 방법은 디코딩이 불가한 것으로 판단 0을 return + return 0 + + if index in memo: # 이미 저장되어 있다면 memo 값을 return + return memo[index] + + result = dfs(index + 1) # index로부터 한 자리 수만 계산할 때, 다음 계산은 index + 1이 된다 + + if ( + index + 1 < len_s + and int(s[index:index + 2]) <= 26 + ): # index~index+1의 문자열이 26보다 작은 두 자리 수일 때만 index + 2번째 계산을 한다 + result += dfs(index + 2) + + memo[index] = result # memoization을 한다 + return result + + return dfs(0) From d433b66411d5ca3d7f62bed40b28c9e3bb348972 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年3月19日 16:05:11 +0900 Subject: [PATCH 049/526] [7th batch] week 3 - maximum subarray --- maximum-subarray/liza0525.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 maximum-subarray/liza0525.py diff --git a/maximum-subarray/liza0525.py b/maximum-subarray/liza0525.py new file mode 100644 index 0000000000..007f6c1c5d --- /dev/null +++ b/maximum-subarray/liza0525.py @@ -0,0 +1,19 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - nums의 모든 요소를 탐색하기 때문에 nums의 길이에 관련되어 있음 +# 공간 복잡도: O(1) +# - 변수 이외에 객체를 쓰지 않았기 때문에 공간 복잡도는 O(1)이다(input 길이와 상관 없음) +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + curr_sum = nums[0] + max_sum = nums[0] + + for i in range(1, len(nums)): + # 1. (현재까지의 합과 i의 요소를 더한 값)과 i의 요소를 서로 비교하여 지금까지의 합을 업데이트한다. + # - 자기 자신만으로도 이전 합들보다 크다면 이전 합들은 의미가 없어짐을 얘기 + curr_sum = max(nums[i], curr_sum + nums[i]) + + # 현재까지의 합과 이전 max 합을 비교하여 업데이트 + max_sum = max(max_sum, curr_sum) + + return max_sum From cf6e2dccc4148540634b92644f2c1952082e0fab Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年3月19日 17:20:08 +0900 Subject: [PATCH 050/526] add: combinationSum solution --- combination-sum/Cyjin-jani.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 combination-sum/Cyjin-jani.js diff --git a/combination-sum/Cyjin-jani.js b/combination-sum/Cyjin-jani.js new file mode 100644 index 0000000000..285ba314b3 --- /dev/null +++ b/combination-sum/Cyjin-jani.js @@ -0,0 +1,24 @@ +// ! 나중에 다시 풀어야 할 문제 +//! 30분 내에 풀지 못해서 AI의 도움을 받아 구현했습니다.. +// recursion의 사용, 종료 조건 등 어느정도 근접한 아이디어를 구현했지만, +// idx를 넘기지 않고 number를 직접 넘기려고 했던 부분이나, results pop을 놓쳤던 부분 등이 있습니다. +const combinationSum = function (candidates, target) { + const answer = []; + + function recursion(idx, target, results = []) { + if (target === 0) { + answer.push([...results]); + return; + } + if (target < 0) return; + + for (let i = idx; i < candidates.length; i++) { + results.push(candidates[i]); + recursion(i, target - candidates[i], results); + results.pop(); + } + } + recursion(0, target, []); + + return answer; +}; From 7574a46baded5ab529299c6232650df896a104bd Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年3月19日 21:23:21 +0900 Subject: [PATCH 051/526] solved combination-sums. --- combination-sum/sangbeenmoon.py | 26 ++++++++++++++++++++++++++ valid-palindrome/sangbeenmoon.py | 21 +++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 combination-sum/sangbeenmoon.py create mode 100644 valid-palindrome/sangbeenmoon.py diff --git a/combination-sum/sangbeenmoon.py b/combination-sum/sangbeenmoon.py new file mode 100644 index 0000000000..998009875f --- /dev/null +++ b/combination-sum/sangbeenmoon.py @@ -0,0 +1,26 @@ +# TC : O(2^target) 재귀 트리의 분기 수 +# SC : O(target/min(candidates)) 재귀 스택 깊이 + +class Solution: + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + self.answer = [] + for i in range(len(candidates)): + self.go(i, candidates, [candidates[i]], candidates[i], target) + + return self.answer + + def go(self, i:int, candidates: List[int], nums: List[int], sum_: int, target: int): + if sum_ == target: + self.answer.append(nums.copy()) + + for j in range(i, len(candidates)): + if candidates[j] + sum_ <= target: + nums.append(candidates[j]) + self.go(j, candidates, nums, sum_ + candidates[j], target) + nums.pop() + + + + + + diff --git a/valid-palindrome/sangbeenmoon.py b/valid-palindrome/sangbeenmoon.py new file mode 100644 index 0000000000..90967855cb --- /dev/null +++ b/valid-palindrome/sangbeenmoon.py @@ -0,0 +1,21 @@ +# TC : O(n) +# SC : O(n) + +class Solution: + def isPalindrome(self, s: str) -> bool: + refined_s = [] + + for ch in s: + if 'a' <= ch and ch <= 'z' or ('0' <= ch and ch <= '9'): + refined_s.append(ch) + continue + + if 'A' <= ch and ch <= 'Z': + refined_s.append(ch.lower()) + + for i in range(len(refined_s)): + j = len(refined_s) - i - 1 + if refined_s[i] != refined_s[j]: + return False + + return True From 083991d9814902b2f9b511e704f05a84281b1681 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年3月19日 21:38:28 +0900 Subject: [PATCH 052/526] solved number-of-1-bits. --- number-of-1-bits/sangbeenmoon.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 number-of-1-bits/sangbeenmoon.py diff --git a/number-of-1-bits/sangbeenmoon.py b/number-of-1-bits/sangbeenmoon.py new file mode 100644 index 0000000000..17f0c03eea --- /dev/null +++ b/number-of-1-bits/sangbeenmoon.py @@ -0,0 +1,9 @@ +class Solution: + def hammingWeight(self, n: int) -> int: + cnt = 0 + while n> 0: + if n % 2 == 1: + cnt = cnt + 1 + n = n // 2 + print(n) + return cnt \ No newline at end of file From 120f01ee1e456498d322ee01cfc360531b466014 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年3月19日 21:38:45 +0900 Subject: [PATCH 053/526] solved number-of-1-bits. --- number-of-1-bits/sangbeenmoon.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/number-of-1-bits/sangbeenmoon.py b/number-of-1-bits/sangbeenmoon.py index 17f0c03eea..056cc5c06b 100644 --- a/number-of-1-bits/sangbeenmoon.py +++ b/number-of-1-bits/sangbeenmoon.py @@ -6,4 +6,5 @@ def hammingWeight(self, n: int) -> int: cnt = cnt + 1 n = n // 2 print(n) - return cnt \ No newline at end of file + return cnt + \ No newline at end of file From 9b7fd8584af7adc780600c04e2079ec37ff5cd04 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年3月19日 21:39:20 +0900 Subject: [PATCH 054/526] solved number-of-1-bits. --- number-of-1-bits/sangbeenmoon.py | 1 - 1 file changed, 1 deletion(-) diff --git a/number-of-1-bits/sangbeenmoon.py b/number-of-1-bits/sangbeenmoon.py index 056cc5c06b..144e437598 100644 --- a/number-of-1-bits/sangbeenmoon.py +++ b/number-of-1-bits/sangbeenmoon.py @@ -7,4 +7,3 @@ def hammingWeight(self, n: int) -> int: n = n // 2 print(n) return cnt - \ No newline at end of file From 226ca6348027c062d79549915a9786b87ee9b4c1 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年3月19日 23:16:53 +0900 Subject: [PATCH 055/526] valid-palindrome solution --- valid-palindrome/hyeri0903.java | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 valid-palindrome/hyeri0903.java diff --git a/valid-palindrome/hyeri0903.java b/valid-palindrome/hyeri0903.java new file mode 100644 index 0000000000..b245a1202c --- /dev/null +++ b/valid-palindrome/hyeri0903.java @@ -0,0 +1,40 @@ +class Solution { + public boolean isPalindrome(String s) { + /** + 1. 문제: 팰린드롬인지 판단하는 문제. + 2. 조건: 알파벳 소문자로 변환, 문자 또는 숫자가 아닌건 모두 제거 (공백, 쉼표 등)) + - left, right index 이중 포인터로 풀이 + time complexity : O(n) + space complexity : O(1) + */ + boolean answer = true; + //문자열 추가하면 space complexity : O(n) + //s = s.toLowerCase(); + //s = s.replaceAll("[^0-9a-z]", ""); + int left = 0 ; + int right = s.length() - 1; + + while(left < right) { + char l = s.charAt(left); + char r = s.charAt(right); + + //왼쪽이 알파벳 or 숫자가 아니면 skip + if (!Character.isLetterOrDigit(l)) { + left += 1; + continue; + } + //오른쪽이 알파벳 or 숫자가 아니면 skip + if (!Character.isLetterOrDigit(r)) { + right -= 1; + continue; + } + if (Character.toLowerCase(l) != Character.toLowerCase(r) ) { + return false; + } + left += 1; + right -= 1; + } + + return answer; + } +} From c37eac92e06de8001c478832e23c316f632d38bc Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年3月19日 23:17:15 +0900 Subject: [PATCH 056/526] delete unuse file --- valid-palindrome/hyeri0903.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 valid-palindrome/hyeri0903.py diff --git a/valid-palindrome/hyeri0903.py b/valid-palindrome/hyeri0903.py deleted file mode 100644 index e69de29bb2..0000000000 From fcf0f052fdea93e4848a82c08031727cb06b92d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年3月19日 23:24:20 +0900 Subject: [PATCH 057/526] Add solution for Combination Sum problem --- combination-sum/gcount85.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 combination-sum/gcount85.py diff --git a/combination-sum/gcount85.py b/combination-sum/gcount85.py new file mode 100644 index 0000000000..82b977ffc7 --- /dev/null +++ b/combination-sum/gcount85.py @@ -0,0 +1,37 @@ +""" +# Intuition +backtracking + +# Complexity +- Time complexity: N을 깊이만큼 곱한다. 따라서 아래와 같을 때, O(N^(T/M)) + N = candidates 개수 + T = target + M = candidates 중 최소값 + +- Space complexity: O(T/M) +""" + + +class Solution: + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + candidates.sort() + answer = [] + output = [] + + def dfs(cur_i, cur_sum): + if cur_sum == target: + answer.append(output[:]) + return + + for i in range(cur_i, len(candidates)): + num = candidates[i] + + if cur_sum + num> target: + break + + output.append(num) + dfs(i, cur_sum + num) + output.pop() + + dfs(0, 0) + return answer From d2eb3097685878cf380c1a5d80859b2aa42cb4e9 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年3月19日 23:48:11 +0900 Subject: [PATCH 058/526] maximium subarray solution --- maximum-subarray/hyeri0903.java | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 maximum-subarray/hyeri0903.java diff --git a/maximum-subarray/hyeri0903.java b/maximum-subarray/hyeri0903.java new file mode 100644 index 0000000000..319839f54e --- /dev/null +++ b/maximum-subarray/hyeri0903.java @@ -0,0 +1,23 @@ +class Solution { + public int maxSubArray(int[] nums) { + /** + 1. 문제: 가장 큰 합을 가지는 subarray 의 sum 을 반환 + 2. 조건: 원소값은 음수 ~ 양수, 배열 최대 길이 = 10^5, 최소 길이 = 1 + - time complexity: O(N) + - space complexity: O(1) + */ + + if (nums.length == 1) { + return nums[0]; + } + + int maxSum = nums[0]; //전체 최대 + int curSum = nums[0]; //현재 합 + + for(int i = 1; i Date: 2026年3月20日 00:13:56 +0900 Subject: [PATCH 059/526] =?UTF-8?q?feat:=20=EB=B0=98=EB=B3=B5=EB=AC=B8=20?= =?UTF-8?q?=EC=88=9C=ED=9A=8C=ED=95=98=EB=A9=B4=EC=84=9C=20=ED=92=80?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- missing-number/gyeo-ri.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 missing-number/gyeo-ri.py diff --git a/missing-number/gyeo-ri.py b/missing-number/gyeo-ri.py new file mode 100644 index 0000000000..f1b79c68f2 --- /dev/null +++ b/missing-number/gyeo-ri.py @@ -0,0 +1,31 @@ +""" +[결과 요약] +# 재시도횟수: 1회 + 1. 반복문으로 구하기: 로직은 쉬우나 n이 최대 10^4이므로 input 길이에 따라 속도가 느려질 수 있음 +""" + + +class Solution: + def missingNumber(self, nums: list[int]) -> int: + len_nums = len(nums) + for i in range(len_nums + 1): + if i not in nums: + return i + + raise Exception("No Answer") + + +if __name__ == "__main__": + test_cases = [ + ([3, 0, 1], 2), + ([0, 1], 2), + ([9, 6, 4, 2, 3, 5, 7, 0, 1], 8), + ] + + solution = Solution() + for idx, case_ in enumerate(test_cases): + nums, answer = case_ + result = solution.missingNumber(nums) + assert ( + answer == result + ), f"Test Case {idx} Failed: Expected {answer}, Got {result}" From 8fc1dd4a286ef882e9291f305c210efba67b4fe8 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年3月20日 00:19:08 +0900 Subject: [PATCH 060/526] =?UTF-8?q?feat:=20=EB=93=B1=EC=B0=A8=EC=88=98?= =?UTF-8?q?=EC=97=B4=EC=9D=98=20=EC=9B=90=EB=A6=AC=20=ED=99=9C=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- missing-number/gyeo-ri.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/missing-number/gyeo-ri.py b/missing-number/gyeo-ri.py index f1b79c68f2..a5d044782e 100644 --- a/missing-number/gyeo-ri.py +++ b/missing-number/gyeo-ri.py @@ -1,18 +1,16 @@ """ [결과 요약] -# 재시도횟수: 1회 +# 재시도횟수: 2회 1. 반복문으로 구하기: 로직은 쉬우나 n이 최대 10^4이므로 input 길이에 따라 속도가 느려질 수 있음 + 2. 등차수열의 원리를 활용하여 n!을 구한 다음 nums의 합을 빼주기 """ class Solution: def missingNumber(self, nums: list[int]) -> int: len_nums = len(nums) - for i in range(len_nums + 1): - if i not in nums: - return i - - raise Exception("No Answer") + total_sum = int(len_nums * (len_nums + 1) / 2) + return total_sum - sum(nums) if __name__ == "__main__": From f541aa1fc48a203c5881e7c4e6fce9a794dfd7a1 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年3月20日 00:25:08 +0900 Subject: [PATCH 061/526] =?UTF-8?q?feat:=20=EA=B0=80=EB=8F=85=EC=84=B1/?= =?UTF-8?q?=EB=A9=94=EB=AA=A8=EB=A6=AC=20=EC=82=AC=EC=9A=A9=EB=9F=89?= =?UTF-8?q?=EC=9D=80=20=EB=96=A8=EC=96=B4=EC=A7=80=EC=A7=80=EB=A7=8C=20?= =?UTF-8?q?=EC=86=8D=EB=8F=84=EA=B0=80=20=EB=B9=A0=EB=A5=B8=20=EC=98=B5?= =?UTF-8?q?=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- missing-number/gyeo-ri.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/missing-number/gyeo-ri.py b/missing-number/gyeo-ri.py index a5d044782e..a158a06733 100644 --- a/missing-number/gyeo-ri.py +++ b/missing-number/gyeo-ri.py @@ -8,10 +8,17 @@ class Solution: def missingNumber(self, nums: list[int]) -> int: + # (Runtime: 3ms / Beats 61.16%, Memory 20.23MB / Beats: 98.53% ) len_nums = len(nums) total_sum = int(len_nums * (len_nums + 1) / 2) return total_sum - sum(nums) + """ + 이때, 아래와 같이 변수 선언 없이 계산하면(In Memory) 메모리는 조금 더 쓰지만 속도는 빨라진다. + (Runtime: 0ms / Beats 100.00%, Memory 20.34MB / Beats: 90.41% ) + return int(len(nums) * (len(nums) + 1) / 2) - sum(nums) + """ + if __name__ == "__main__": test_cases = [ From 77fa2c825ec0fa2f58694cfe097629b23f5980ab Mon Sep 17 00:00:00 2001 From: dohee Date: 2026年3月19日 14:59:46 -0400 Subject: [PATCH 062/526] comment out --- valid-palindrome/doh6077.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/valid-palindrome/doh6077.py b/valid-palindrome/doh6077.py index cb2b3e5600..452594c6ec 100644 --- a/valid-palindrome/doh6077.py +++ b/valid-palindrome/doh6077.py @@ -1,16 +1,16 @@ -import re -# two pointers -class Solution: - def isPalindrome(self, s: str) -> bool: - # remove all alphanumeric characters and convert all uppercase letters into lowercase letters - cleaned_s = re.sub(r'[^a-zA-Z0-9]', '', s).lower() - n = len(cleaned_s) - left, right = 0, n -1 - while left < right: - if cleaned_s[left] == cleaned_s[right]: - left += 1 - right -= 1 - else: - return False +# import re +# # two pointers +# class Solution: +# def isPalindrome(self, s: str) -> bool: +# # remove all alphanumeric characters and convert all uppercase letters into lowercase letters +# cleaned_s = re.sub(r'[^a-zA-Z0-9]', '', s).lower() +# n = len(cleaned_s) +# left, right = 0, n -1 +# while left < right: +# if cleaned_s[left] == cleaned_s[right]: +# left += 1 +# right -= 1 +# else: +# return False - return True +# return True From 235ff39fe7376c1b23b99b1d2c987420587121bd Mon Sep 17 00:00:00 2001 From: dohee Date: 2026年3月19日 15:02:18 -0400 Subject: [PATCH 063/526] Valid Palindrome Solution --- valid-palindrome/doh6077.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/valid-palindrome/doh6077.py b/valid-palindrome/doh6077.py index 452594c6ec..e033bdf4a8 100644 --- a/valid-palindrome/doh6077.py +++ b/valid-palindrome/doh6077.py @@ -14,3 +14,16 @@ # return False # return True +# 7기 +# use two pointers +# Time Complexity: O(n) +class Solution: + def isPalindrome(self, s: str) -> bool: + cleaned_s = re.sub(r'[^a-zA-Z0-9]', '', s).lower() + l, r = 0, len(cleaned_s) - 1 + while l < r : + if cleaned_s[l] != cleaned_s[r]: + return False + l += 1 + r -= 1 + return True From 06863a7a99866a46c69b1157803c520cecc69309 Mon Sep 17 00:00:00 2001 From: river Date: 2026年3月20日 05:19:45 +0900 Subject: [PATCH 064/526] combination sum solution --- combination-sum/riveroverflows.py | 33 +++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 combination-sum/riveroverflows.py diff --git a/combination-sum/riveroverflows.py b/combination-sum/riveroverflows.py new file mode 100644 index 0000000000..f168757b14 --- /dev/null +++ b/combination-sum/riveroverflows.py @@ -0,0 +1,33 @@ +class Solution: + """ + TC: O(N^(T/M)) + - N = len(candidates), T = target, M = min(candidates) + SC: O((T/M) * N^(T/M)) + + 풀이: + 백트래킹으로 모든 조합을 탐색하되, 중복 조합 방지를 위해 + start 인덱스를 활용하여 이전 후보는 건너뛰고, 같은 후보는 재사용 허용. + path_sum> target이면 가지치기(pruning)하여 불필요한 탐색을 줄임. + """ + def combinationSum(self, candidates: list[int], target: int) -> list[list[int]]: + answer = [] + + def backtrack(start, path, path_sum): + if path_sum> target: + return + + if path_sum == target: + answer.append(path[:]) + return + + for i in range(start, len(candidates)): + candidate = candidates[i] + path.append(candidate) + path_sum += candidate + backtrack(i, path, path_sum) + path_sum -= candidate + path.pop() + + backtrack(0, [], 0) + + return answer From f53185032408044e9f612309460a1a4f381e85cf Mon Sep 17 00:00:00 2001 From: grapefruit Date: 2026年3月20日 12:41:18 +0900 Subject: [PATCH 065/526] =?UTF-8?q?valid=20palindrome=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- valid-palindrome/grapefruit13.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 valid-palindrome/grapefruit13.ts diff --git a/valid-palindrome/grapefruit13.ts b/valid-palindrome/grapefruit13.ts new file mode 100644 index 0000000000..3bd0e17bf0 --- /dev/null +++ b/valid-palindrome/grapefruit13.ts @@ -0,0 +1,13 @@ +function isPalindrome(s: string): boolean { + const cleaned = s.toLowerCase().replace(/[^a-z0-9]/g, ''); + + let left = 0; + let right = cleaned.length - 1; + + while (left < right) { + if (cleaned[left] !== cleaned[right]) return false; + left++; + right--; + } + return true; +} From 9303e783eec16a665ca5cdb5b32e2af032d9b6e1 Mon Sep 17 00:00:00 2001 From: grapefruit Date: 2026年3月20日 12:50:20 +0900 Subject: [PATCH 066/526] solve combintaion sum --- combination-sum/grapefruit13.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 combination-sum/grapefruit13.ts diff --git a/combination-sum/grapefruit13.ts b/combination-sum/grapefruit13.ts new file mode 100644 index 0000000000..1eae3260d6 --- /dev/null +++ b/combination-sum/grapefruit13.ts @@ -0,0 +1,20 @@ +function combinationSum(candidates: number[], target: number): number[][] { + const answer: number[][] = []; + + function dfs(index: number, path: number[], sum: number) { + if (sum === target) { + answer.push([...path]); + return; + } + if (sum> target) return; + + for (let i = index; i < candidates.length; i++) { + path.push(candidates[i]); + dfs(i, path, sum + candidates[i]); + path.pop(); + } + } + + dfs(0, [], 0); + return answer; +} From 87b023c3f8c9c235a1926149fea14ff75b384c59 Mon Sep 17 00:00:00 2001 From: grapefruit Date: 2026年3月20日 13:03:34 +0900 Subject: [PATCH 067/526] solve decode ways --- decode-ways/grapefruit13.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 decode-ways/grapefruit13.ts diff --git a/decode-ways/grapefruit13.ts b/decode-ways/grapefruit13.ts new file mode 100644 index 0000000000..0b66c27bde --- /dev/null +++ b/decode-ways/grapefruit13.ts @@ -0,0 +1,23 @@ +function numDecodings(s: string): number { + if (s[0]==="0") return 0; + + const dp = new Array(s.length).fill(0); + dp[0] = 1; + + for (let i=1; i Date: 2026年3月20日 14:06:38 +0900 Subject: [PATCH 068/526] sadie100: maximum subarray solution --- maximum-subarray/sadie100.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 maximum-subarray/sadie100.ts diff --git a/maximum-subarray/sadie100.ts b/maximum-subarray/sadie100.ts new file mode 100644 index 0000000000..127d182ec1 --- /dev/null +++ b/maximum-subarray/sadie100.ts @@ -0,0 +1,19 @@ +/* +nums를 순회하며 최대 sum을 찾는다. 다음 규칙을 따른다 +- 매 순간 숫자를 더해 가며 현재까지의 합과 최대합 비교, 갱신 +- 만약 해당 인덱스 num을 더했을 때 0보다 작아지면 현재까지의 값을 0으로 초기화(총합 버림) + +*/ + +function maxSubArray(nums: number[]): number { + let result = -Infinity; + let curSum = 0; + + for (let num of nums) { + curSum += num; + result = Math.max(result, curSum); + if (curSum < 0) curSum = 0; + } + + return result; +} From a5875bcfb3b3e78b824b6469d510ba00ecb0626a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年3月20日 15:44:01 +0900 Subject: [PATCH 069/526] Add solution for Maximum Depth of Binary Tree problem --- maximum-depth-of-binary-tree/gcount85.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 maximum-depth-of-binary-tree/gcount85.py diff --git a/maximum-depth-of-binary-tree/gcount85.py b/maximum-depth-of-binary-tree/gcount85.py new file mode 100644 index 0000000000..b705564184 --- /dev/null +++ b/maximum-depth-of-binary-tree/gcount85.py @@ -0,0 +1,19 @@ +""" +# Intuition +1) BFS + 큐 +2) DFS + 재귀 +1번으로 풀었다가 2번이 코드가 더 간결해서 바꿨습니다. + +# Complexity +- Time complexity: 모든 노드를 다 봐야 하므로 O(N) + +- Space complexity: 재귀 깊이만큼 O(H) +""" + +class Solution: + def maxDepth(self, root: Optional[TreeNode]) -> int: + if not root: + return 0 + return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right)) + + \ No newline at end of file From d3c9c58fa451a3eb39f27bdf2516805ce7e052e0 Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: 2026年3月20日 19:58:10 +0900 Subject: [PATCH 070/526] Solution for Maximum Subarray #275 --- maximum-subarray/dohyeon2.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 maximum-subarray/dohyeon2.java diff --git a/maximum-subarray/dohyeon2.java b/maximum-subarray/dohyeon2.java new file mode 100644 index 0000000000..9ffe3d4b0b --- /dev/null +++ b/maximum-subarray/dohyeon2.java @@ -0,0 +1,17 @@ +class Solution { + // TC : O(n) + // SC : O(1) + public int maxSubArray(int[] nums) { + int max = nums[0]; + int sum = 0; + + for (int i = 0; i < nums.length; i++) { + // 부분합보다 현재 숫자가 더 크면 갱신한다. + // 현재 숫자 단독이 더 큰 경우 이전 합이 의미가 없기 때문에 그리디하게 처리 가능 + sum = Math.max(nums[i], nums[i] + sum); + max = Math.max(sum, max); + } + + return max; + } +} From 189911dcd67a528676cb91e082e3d2381f63f4a9 Mon Sep 17 00:00:00 2001 From: YOOHYOJEONG Date: 2026年3月20日 22:01:30 +0900 Subject: [PATCH 071/526] week03_4_5_solution --- decode-ways/YOOHYOJEONG.py | 25 +++++++++++++++++++++++++ maximum-subarray/YOOHYOJEONG.py | 15 +++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 decode-ways/YOOHYOJEONG.py create mode 100644 maximum-subarray/YOOHYOJEONG.py diff --git a/decode-ways/YOOHYOJEONG.py b/decode-ways/YOOHYOJEONG.py new file mode 100644 index 0000000000..cfcb32afbc --- /dev/null +++ b/decode-ways/YOOHYOJEONG.py @@ -0,0 +1,25 @@ +# https://leetcode.com/problems/decode-ways + +class Solution(object): + def numDecodings(self, s): + if not s or s[0] == '0': + return 0 + + n = len(s) + + # dp[i] = i번째까지 문자열을 해석하는 방법의 개수 + dp = [0] * (n + 1) + dp[0] = 1 + dp[1] = 1 + + for i in range(2, n + 1): + # 1자리 체크 + if s[i-1] != '0': + dp[i] += dp[i-1] + + # 2자리 체크 + two_digit = int(s[i-2:i]) + if 10 <= two_digit <= 26: + dp[i] += dp[i-2] + + return dp[n] diff --git a/maximum-subarray/YOOHYOJEONG.py b/maximum-subarray/YOOHYOJEONG.py new file mode 100644 index 0000000000..c5d170e8be --- /dev/null +++ b/maximum-subarray/YOOHYOJEONG.py @@ -0,0 +1,15 @@ +# https://leetcode.com/problems/maximum-subarray/ + +# 이전까지 누적한 값이 음수면 버리고 현재 값부터 다시 시작 +# 한 번만 순회 -> O(n) + +class Solution(object): + def maxSubArray(self, nums): + current_sum = nums[0] + max_sum = nums[0] + + for i in range(1, len(nums)): + current_sum = max(nums[i], current_sum + nums[i]) + max_sum = max(max_sum, current_sum) + + return max_sum From 6305af0ab63f237e1bba06559c6c85294120ef06 Mon Sep 17 00:00:00 2001 From: YOUNGJIN NA <120540450+ppxyn1@users.noreply.github.com> Date: 2026年3月20日 22:17:28 +0900 Subject: [PATCH 072/526] [:solved] Weeks3 --- number-of-1-bits/ppxyn1.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/number-of-1-bits/ppxyn1.py b/number-of-1-bits/ppxyn1.py index 3762a12b3e..15a65772f3 100644 --- a/number-of-1-bits/ppxyn1.py +++ b/number-of-1-bits/ppxyn1.py @@ -1,5 +1,7 @@ # idea: - +# Ans 1 +# Time Complexity: O(N) ? from collections import Counter class Solution: def hammingWeight(self, n: int) -> int: @@ -8,3 +10,13 @@ def hammingWeight(self, n: int) -> int: +# Ans 2 +# Time Complexity: O(N) +class Solution: + def hammingWeight(self, n: int) -> int: + cnt = 0 + while n: + cnt += n & 1 # check current bit + n>>= 1 # move to next bit + return cnt + From ddddb8637e4633d1f20e69ba5d5eb8c8d277637d Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年3月20日 23:24:12 +0900 Subject: [PATCH 073/526] add: decodeWays solution --- decode-ways/Cyjin-jani.js | 57 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 decode-ways/Cyjin-jani.js diff --git a/decode-ways/Cyjin-jani.js b/decode-ways/Cyjin-jani.js new file mode 100644 index 0000000000..2a0bedc6f3 --- /dev/null +++ b/decode-ways/Cyjin-jani.js @@ -0,0 +1,57 @@ +//! 다시 풀어야 하는 문제 + +// Time limit 초과 +const numDecodings_timeLimit = function (s) { + let answer = 0; + + function recursion(idx, remains) { + if (idx === remains.length) { + answer++; + return; + } + + const one = remains.slice(idx, idx + 1); + if (+one>= 1 && +one <= 9) { + recursion(idx + 1, remains); + } + + if (idx + 1 < remains.length) { + const two = remains.slice(idx, idx + 2); + if (+two>= 10 && +two <= 26) { + recursion(idx + 2, remains); + } + } + } + + recursion(0, s); + + return answer; +}; + +// 메모이제이션 적용 +const numDecodings = function (s) { + function recursion(idx, remains, memo = {}) { + if (idx === remains.length) return 1; + + if (idx in memo) return memo[idx]; + + let answer = 0; + + const one = remains.slice(idx, idx + 1); + if (+one>= 1 && +one <= 9) { + answer += recursion(idx + 1, remains, memo); + } + + if (idx + 1 < remains.length) { + const two = remains.slice(idx, idx + 2); + if (+two>= 10 && +two <= 26) { + answer += recursion(idx + 2, remains, memo); + } + } + + memo[idx] = answer; + return answer; + } + + return recursion(0, s, {}); +}; From 91c1722b7e25f0865c93da657f4644e02bfb048f Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年3月20日 23:50:04 +0900 Subject: [PATCH 074/526] add: maximumSubArray solution --- maximum-subarray/Cyjin-jani.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 maximum-subarray/Cyjin-jani.js diff --git a/maximum-subarray/Cyjin-jani.js b/maximum-subarray/Cyjin-jani.js new file mode 100644 index 0000000000..815dadd402 --- /dev/null +++ b/maximum-subarray/Cyjin-jani.js @@ -0,0 +1,13 @@ +//! 다시 풀어보기 (divide and conquer) +const maxSubArray = function (nums) { + let currentSum = 0; + let maxSum = -Infinity; + + for (let right = 0; right < nums.length; right++) { + currentSum += nums[right]; + maxSum = Math.max(maxSum, currentSum); + if (currentSum < 0) currentSum = 0; + } + + return maxSum; +}; From 72df4a91160415a94aebdbb5090dded767e5fb76 Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年3月20日 23:58:52 +0900 Subject: [PATCH 075/526] week3: valid-palindrome --- valid-palindrome/reeseo3o.js | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 valid-palindrome/reeseo3o.js diff --git a/valid-palindrome/reeseo3o.js b/valid-palindrome/reeseo3o.js new file mode 100644 index 0000000000..97bdad7342 --- /dev/null +++ b/valid-palindrome/reeseo3o.js @@ -0,0 +1,5 @@ +const isPalindrome = (s) => { + const cleaned = s.toLowerCase().replace(/[^a-z0-9]/g, ''); + const reversed = cleaned.split('').reverse().join(''); + return cleaned === reversed; +}; From 9608bb41fb38b24bcaaa05f508963c8a78db7d7d Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: 2026年3月21日 01:11:04 +0900 Subject: [PATCH 076/526] Solution for Combination Sum #254 --- combination-sum/dohyeon2.java | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 combination-sum/dohyeon2.java diff --git a/combination-sum/dohyeon2.java b/combination-sum/dohyeon2.java new file mode 100644 index 0000000000..161184fa4d --- /dev/null +++ b/combination-sum/dohyeon2.java @@ -0,0 +1,30 @@ +import java.util.ArrayList; +import java.util.List; + +class Solution { + // TC : O(n!) => TC : O(2^T) + // SC : O(n^2) => SC : O(T) + ArrayList> result = new ArrayList(); + + public List> combinationSum(int[] candidates, int target) { + backtrack(0, target, candidates, new ArrayList()); + return result; + } + + private void backtrack(int start, int diff, int[] candidates, ArrayList path) { + if (diff == 0) { + result.add(new ArrayList(path)); // 깊은 복사 + return; + } + + if (diff < 0) { + return; + } + + for (int i = start; i < candidates.length; i++) { + path.add(candidates[i]); + backtrack(i, diff - candidates[i], candidates, path); + path.remove(path.size() - 1); + } + } +} From e9acb59f98c7fd913ef5081e8d3df9385076a23c Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: 2026年3月21日 01:42:10 +0900 Subject: [PATCH 077/526] Solution for Decode Ways #268 --- decode-ways/dohyeon2.java | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 decode-ways/dohyeon2.java diff --git a/decode-ways/dohyeon2.java b/decode-ways/dohyeon2.java new file mode 100644 index 0000000000..ce095b0596 --- /dev/null +++ b/decode-ways/dohyeon2.java @@ -0,0 +1,35 @@ +class Solution { + // TC : O(n) + // SC : O(1) + public int numDecodings(String s) { + // If it starts with 0, the value can't be decoded. + if (s.charAt(0) == '0') { + return 0; + } + + int n = s.length(); + + int prev2 = 1; + int prev1 = 1; + + // dp[i] = dp[i-1] + dp[i-2] + for (int i = 1; i < n; i++) { + int current = 0; + + if (s.charAt(i) != '0') { + current += prev1; + } + + int twoDigit = Integer.valueOf(s.substring(i - 1, i + 1)); + + if (twoDigit>= 10 && twoDigit <= 26) { + current += prev2; + } + + prev2 = prev1; + prev1 = current; + } + + return prev1; + } +} From dcbf5298f7d9ce3b844dd4d5ca5f93112a477a96 Mon Sep 17 00:00:00 2001 From: dohee Date: 2026年3月20日 16:34:28 -0400 Subject: [PATCH 078/526] Number of 1 Bits Solution --- number-of-1-bits/doh6077.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/number-of-1-bits/doh6077.py b/number-of-1-bits/doh6077.py index b04b5900c5..f654b17d12 100644 --- a/number-of-1-bits/doh6077.py +++ b/number-of-1-bits/doh6077.py @@ -1,7 +1,15 @@ +# class Solution: +# def hammingWeight(self, n: int) -> int: +# ans = 0 +# while n != 0: +# ans += 1 +# n = n & ( n-1) +# return ans + class Solution: def hammingWeight(self, n: int) -> int: ans = 0 while n != 0: ans += 1 - n = n & ( n-1) - return ans + n = n & (n-1) + return ans From 00093a46fe475112442f39b401e4cdf91cd035a4 Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年3月20日 14:21:08 -0700 Subject: [PATCH 079/526] combination sum solution --- combination-sum/jylee2033.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 combination-sum/jylee2033.py diff --git a/combination-sum/jylee2033.py b/combination-sum/jylee2033.py new file mode 100644 index 0000000000..283b9ed0f6 --- /dev/null +++ b/combination-sum/jylee2033.py @@ -0,0 +1,22 @@ +class Solution: + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + output = [] + + def backtrack(remain, comb, start): + if remain == 0: + output.append(list(comb)) + return + + elif remain < 0: + return + + for i in range(start, len(candidates)): + comb.append(candidates[i]) + backtrack(remain - candidates[i], comb, i) + comb.pop() + + backtrack(target, [], 0) + return output + +# Time Complexity : O(N^T/M) N - number of candidates, T - target, M - minimum value in candidates +# Space Complexity : O(T/M) - maximum depth of the recursion tree From c8d52f3edafa0433a6fd9eaac67cd6bbf5047b6b Mon Sep 17 00:00:00 2001 From: juhui Date: 2026年3月21日 11:36:02 +0900 Subject: [PATCH 080/526] WEEK 3 Solutions --- combination-sum/juhui-jeong.java | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 combination-sum/juhui-jeong.java diff --git a/combination-sum/juhui-jeong.java b/combination-sum/juhui-jeong.java new file mode 100644 index 0000000000..76815b62f4 --- /dev/null +++ b/combination-sum/juhui-jeong.java @@ -0,0 +1,24 @@ +class Solution { + public List> combinationSum(int[] candidates, int target) { + // dfs & 백트래킹 + List> resultList = new ArrayList(); + dfs(candidates, target, 0, new ArrayList(), resultList); + return resultList; + } + private void dfs(int[] candidates, int target, int start, List path, List> resultList) { + if (target == 0) { + resultList.add(new ArrayList(path)); + return; + } + + if (target < 0) { + return; + } + + for(int i = start; i < candidates.length; i++) { + path.add(candidates[i]); + dfs(candidates, target - candidates[i], i, path, resultList); + path.remove(path.size() -1); + } + } +} From acc6d7e5f4f848dfad9a9aadcd5deff3f5a49d4a Mon Sep 17 00:00:00 2001 From: Yerim Moon Date: 2026年3月20日 22:08:26 -0700 Subject: [PATCH 081/526] number of 1 bits solution --- number-of-1-bits/yerim01.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 number-of-1-bits/yerim01.py diff --git a/number-of-1-bits/yerim01.py b/number-of-1-bits/yerim01.py new file mode 100644 index 0000000000..f5b8bdfabe --- /dev/null +++ b/number-of-1-bits/yerim01.py @@ -0,0 +1,19 @@ +# Goal: Given a positive int n, return the number of set bits in binary. +# Approach: +# Divide by 2 and check the remainder to determine the last bit. +# If the remainder is 1, update the variable 'count'. +# Repeat until n becomes 0. +# Time Complexity: O(logn) +# - We process each bit of n. +# Space Complexity: O(1) +# - We use only one variable 'count'. +class Solution: + def hammingWeight(self, n: int) -> int: + count = 0 + + while n != 0: + if n % 2 == 1: + count += 1 + n = n // 2 + + return count From 909b6d744d4bdb658373f2a9a0d6b3f3b211c6db Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年3月20日 22:12:54 -0700 Subject: [PATCH 082/526] number of 1 bits solution refactor --- number-of-1-bits/jylee2033.py | 39 +++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/number-of-1-bits/jylee2033.py b/number-of-1-bits/jylee2033.py index beaaf25255..555f414483 100644 --- a/number-of-1-bits/jylee2033.py +++ b/number-of-1-bits/jylee2033.py @@ -1,26 +1,39 @@ class Solution: def hammingWeight(self, n: int) -> int: - # 1. Find highest power of 2 range that covers n - # 2. Greedily subtract from largest power of 2 to smallest + # # 1. Find highest power of 2 range that covers n + # # 2. Greedily subtract from largest power of 2 to smallest - # powers : 1 + 2 + 4 + 8 + 16 + ... - # total : 1 + 3 + 7 + 15 + 31 + ... - # index : 0 1 2 3 4 + # # powers : 1 + 2 + 4 + 8 + 16 + ... + # # total : 1 + 3 + 7 + 15 + 31 + ... + # # index : 0 1 2 3 4 - i = 0 - total = 1 + # i = 0 + # total = 1 - while n> total: - i += 1 - total += 2 ** i + # while n> total: + # i += 1 + # total += 2 ** i + + # count = 0 + + # for j in range(i, -1, -1): + # if n>= 2 ** j: + # n -= 2 ** j + # count += 1 + + # return count + +# Time Complexity : O(log n) +# Space Complexity : O(1) count = 0 - for j in range(i, -1, -1): - if n>= 2 ** j: - n -= 2 ** j + while n> 0: + if n % 2 == 1: count += 1 + n //= 2 + return count # Time Complexity : O(log n) From 36176b9e0e18ff7044aa6eea9c8854684b2d3870 Mon Sep 17 00:00:00 2001 From: Yerim Moon Date: 2026年3月20日 22:21:40 -0700 Subject: [PATCH 083/526] valid palindrome solution --- valid-palindrome/yerim01.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 valid-palindrome/yerim01.py diff --git a/valid-palindrome/yerim01.py b/valid-palindrome/yerim01.py new file mode 100644 index 0000000000..c67e06e7c9 --- /dev/null +++ b/valid-palindrome/yerim01.py @@ -0,0 +1,31 @@ +# Goal: Return true if it's a palindrome. If it's not, return false +# - palindrome: a string that reads the same forward and backward +# Time Complexity: O(n) +# - Building string is O(n) + Two pointer check is O(n). +# Space Complexity: O(n) +# - We use a new string of size s. +class Solution: + def isPalindrome(self, s: str) -> bool: + chars = [] + + # Trim 's' to contain only alphanumerical characters + for ch in s: + if ch.isalnum(): + chars.append(ch.lower()) # make it case-insensitive + + new_s = "".join(chars) + + # Use two pointers + # ptr1 -> starting index ptr2 -> ending index + ptr1 = 0 + ptr2 = len(new_s) - 1 + + while ptr1 < ptr2: # O(n) time + # Return false if ptr1 and ptr2 point to different char + if new_s[ptr1] != new_s[ptr2]: + return False + ptr1 += 1 + ptr2 -= 1 + + # Otherwise, return true + return True From a4089d5d6bd2ee4f0475a3943c8a42fb95e1f5bb Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年3月20日 22:35:05 -0700 Subject: [PATCH 084/526] valid palindrome solution refactor --- valid-palindrome/jylee2033.py | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/valid-palindrome/jylee2033.py b/valid-palindrome/jylee2033.py index a1fb7d206e..c6665250b7 100644 --- a/valid-palindrome/jylee2033.py +++ b/valid-palindrome/jylee2033.py @@ -3,12 +3,31 @@ def isPalindrome(self, s: str) -> bool: # 1. Remove non-alphanumeric characters and convert to lowercase # 2. Compare with reversed string - cleaned_s = "" - for ch in s: - if ch.isalnum(): - cleaned_s += ch.lower() + # cleaned_s = "" + # for ch in s: + # if ch.isalnum(): + # cleaned_s += ch.lower() - return cleaned_s == cleaned_s[::-1] + # return cleaned_s == cleaned_s[::-1] # Time Complexity : O(n) # Space Complexity : O(n) + + left = 0 + right = len(s) - 1 + + while left < right: + if not s[left].isalnum(): + left += 1 + elif not s[right].isalnum(): + right -= 1 + elif s[left].lower() != s[right].lower(): + return False + else: + left += 1 + right -= 1 + + return True + +# Time Complexity : O(n) +# Space Complexity : O(1) From db463133fb163fe36e22636caae16c2e3ecf7f8e Mon Sep 17 00:00:00 2001 From: Dia Date: 2026年3月21日 17:06:09 +0900 Subject: [PATCH 085/526] feat: add palindrom problem --- valid-palindrome/kangdaia.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 valid-palindrome/kangdaia.py diff --git a/valid-palindrome/kangdaia.py b/valid-palindrome/kangdaia.py new file mode 100644 index 0000000000..41df6fe59b --- /dev/null +++ b/valid-palindrome/kangdaia.py @@ -0,0 +1,35 @@ +class Solution: + def isPalindrome(self, s: str) -> bool: + """ + string이 팰린드롬 문자열인지 판단하는 함수 + 팰린드롬: 대소문자x 영문자&숫자 만으로 앞뒤가 동일한 문자열 + + 방법: + 1. 리스트를 필터/소문자화해서, 앞에서 반절과 뒤의 반절 (reverse)한 것을 비교하기 + -> 순회를 두번하게 됨 + 2. 앞과 뒤에서 포인터 방식으로 찾기 + -> 영문자혹은 숫자가 아니면 건너뛰기 + -> isalnum으로 유효한 문자인지 판단 + -> 시간 복잡도 O(n) 공간 복잡도 O(1) + Args: + s (str): 검사할 문자열 + + Returns: + bool: 팰린드롬이면 True, 아니면 False + """ + i, j = 0, len(s)-1 + answer = True + while i < len(s) and j>= 0 and i < j: + if s[i].isalnum() == False: + i += 1 + elif s[j].isalnum() == False: + j -= 1 + else: + if s[i].lower() == s[j].lower(): + answer = answer and True + else: + answer = answer and False + break + i += 1 + j -= 1 + return answer From bdc238b9b085894bc564175aaf0cf133b27a7a26 Mon Sep 17 00:00:00 2001 From: Dia Date: 2026年3月21日 17:14:43 +0900 Subject: [PATCH 086/526] feat: add nums of 1 bits solution --- number-of-1-bits/kangdaia.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 number-of-1-bits/kangdaia.py diff --git a/number-of-1-bits/kangdaia.py b/number-of-1-bits/kangdaia.py new file mode 100644 index 0000000000..01740af55d --- /dev/null +++ b/number-of-1-bits/kangdaia.py @@ -0,0 +1,28 @@ +class Solution: + def hammingWeight(self, n: int) -> int: + """ + 주어진 숫자의 이진 표현에서, 1의 개수를 계산하는 함수 + 예) 11 -> 1011 => 3 + + 방법: + 1. 숫자를 이진법으로 바꿔서 1을 찾아 계산하기 + - 이진법으로 바꾸는 과정에서 전체 순회를 하고, 1을 찾을때 또 순회해야햠. + -> 한번에 해결할 수 없을까? + 2. 숫자를 직접 비트연산하며 계산하기 + - 숫자를 bitshift하면서 마지막 비트가 1인지 아닌지 찾기 + - 1이면 count + 1 + -> 시간 복잡도 O(k) (k는 비트길이), 공간복잡도 O(1) + + Args: + n(int): 양수 + + Returns: + int: 이진 표현에서 1의 개수 + """ + curr = n + count = 0 + while curr> 0: + if curr & 1 == 1: + count += 1 + curr = curr>> 1 + return count From bff76a066f52e2b47bd7631482d28ce9af91838c Mon Sep 17 00:00:00 2001 From: Dia Date: 2026年3月21日 17:23:02 +0900 Subject: [PATCH 087/526] feat: add combination sum solution --- combination-sum/kangdaia.py | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 combination-sum/kangdaia.py diff --git a/combination-sum/kangdaia.py b/combination-sum/kangdaia.py new file mode 100644 index 0000000000..2901120130 --- /dev/null +++ b/combination-sum/kangdaia.py @@ -0,0 +1,40 @@ +class Solution: + def combinationSum(self, candidates: list[int], target: int) -> list[list[int]]: + """ + 주어진 숫자 목록에서 목표하는 합을 만들 수 있는 조합을 찾는 함수 + 숫자는 동일 숫자를 여러번 사용해도 됨 + + 방법: + DFS 방식을 사용함. + - 현재 인덱스를 기준으로, + (선택지) + 현재 위치의 숫자값을 현재 조합에 포함할지 + - 현재 합을 만들기 위해 남은 값 - 현재 값이 0 이상이면 포함 가능 + - 현재 값을 여러번 쓸 수 있기에 인덱스를 늘리지 x + 현재 위치의 숫자값을 현재 조합에 포함하지 않을지 + - 이 인덱스가 목록길이를 넘어가면 안됨 + - 합의 나머지 값이 0이면 목표에 도달한것 -> 조합 목록에 포함 + + Args: + candidates (list[int]): 사용가능한 숫자 목록. unique + target (int): 목표하는 합 + + Returns: + list[list[int]]: 목표하는 합을 만들 수 있는 가능한 숫자 조합. unique + """ + combinations = list() + def getCombination(idx, remain, path): + """ + 현재 함수에서 재귀를 위한 helper 함수 + """ + if remain == 0: + combinations.append(path) + return + if idx < len(candidates): + curr = candidates[idx] + if remain - curr>= 0: + getCombination(idx, remain - curr, path + [curr]) + getCombination(idx + 1, remain, path) + return + getCombination(0, target, []) + return combinations From ca3c33e48b8beea5cd62d3b898c97deb7f0d2622 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年3月21日 19:02:20 +0900 Subject: [PATCH 088/526] combination-sum solution --- combination-sum/hyeri0903.java | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 combination-sum/hyeri0903.java diff --git a/combination-sum/hyeri0903.java b/combination-sum/hyeri0903.java new file mode 100644 index 0000000000..f8037ec430 --- /dev/null +++ b/combination-sum/hyeri0903.java @@ -0,0 +1,26 @@ +class Solution { + public List> combinationSum(int[] candidates, int target) { + List> answer = new ArrayList(); + Arrays.sort(candidates); //불필요한 탐색을 줄이기 위해 sorting + dfs(0, candidates, target, new ArrayList(), answer); + return answer; + + } + + public void dfs(int start, int[] candidates, int target, List curList, List> answer) { + if (target == 0) { + answer.add(new ArrayList(curList)); + return; + } + for(int i = start; i < candidates.length; i++) { + if (candidates[i]> target) { + break; + } + + curList.add(candidates[i]); + dfs(i, candidates, target - candidates[i], curList, answer); + curList.remove(curList.size()-1); //다음 경우의 수를 위해 backtracking + + } + } +} From d8ddf63fc7e105c8089e83ac8f3b244e7f76c980 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年3月21日 19:32:56 +0900 Subject: [PATCH 089/526] decode-ways solution --- decode-ways/hyeri0903.java | 45 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 decode-ways/hyeri0903.java diff --git a/decode-ways/hyeri0903.java b/decode-ways/hyeri0903.java new file mode 100644 index 0000000000..96b15121e9 --- /dev/null +++ b/decode-ways/hyeri0903.java @@ -0,0 +1,45 @@ +class Solution { + public int numDecodings(String s) { + /** + 1.문제: decode 할 수 있는 모든 경우의 수 return + 2.조건: + - 여러 개의 경우의 수 있을 수 있다. + - decode 불가능한 경우가 있을 수 있다. + - 모두 불가능한 경우 return 0 + 3.풀이 + - dp (해석할 수 있는 방법 수를 누적해서 더함) + e.g 226 + 0자리 : dp[0] = 0 + 1자리(2) : 2 -> dp]1] = 1 + 2자리(22): 2(B), 22(v) -> dp[2] = 2 + 3자리(226): (2, 2, 6), (22, 6), (2, 26) -> dp[3] = 3 + + time complexity: O(N) + space complexity: O(N) + + */ + if (s.charAt(0) == '0') { + return 0; + } + int n = s.length(); + int[] dp = new int[n+1]; + dp[0] = 1; //아무것도 없는 상태 + dp[1] = 1; + + for(int i = 2; i<=n; i++) { + //1자리수 + if (s.charAt(i-1) != '0') { + dp[i] += dp[i-1]; + } + //2자리수 + if(i> 1) { + int number = Integer.parseInt(s.substring(i-2, i)); + //2자리 수는 10 ~ 26사이만 가능 + if (number>= 10 && number <= 26) { + dp[i] += dp[i-2]; + } + } + } + return dp[n]; + } +} From c08fb7c9743d62f8c0f2337fce85e7d27613e29a Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年3月21日 19:49:04 +0900 Subject: [PATCH 090/526] number-of-1-bits solution --- number-of-1-bits/hyeri0903.java | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 number-of-1-bits/hyeri0903.java diff --git a/number-of-1-bits/hyeri0903.java b/number-of-1-bits/hyeri0903.java new file mode 100644 index 0000000000..65a291ba12 --- /dev/null +++ b/number-of-1-bits/hyeri0903.java @@ -0,0 +1,23 @@ +class Solution { + public int hammingWeight(int n) { + /** + 1.문제: 이진수 변환 후 1의 개수 반환 + 2. 2로 나누면서 나머지가 1일 경우 count+=1 + */ + int count = 0; + // while(n> 0) { + // if (n % 2 != 0) { + // count += 1; + // } + // n = n / 2; + // } + + while(n> 0) { + if ((n & 1) == 1) { + count += 1; + } + n>>= 1; + } + return count; + } +} From 3e593f43f9744fbb4388d82cd78de2b0cb047408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=A4=EC=99=95=ED=83=9D=5FT6102=28Wang-Taek=20Oh=29?= Date: 2026年3月21日 19:57:05 +0900 Subject: [PATCH 091/526] Combination sum solution --- combination-sum/ohkingtaek.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 combination-sum/ohkingtaek.py diff --git a/combination-sum/ohkingtaek.py b/combination-sum/ohkingtaek.py new file mode 100644 index 0000000000..ddbd8b802a --- /dev/null +++ b/combination-sum/ohkingtaek.py @@ -0,0 +1,25 @@ +class Solution: + def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: + """ + - 시간복잡도: O(n^2) + - 공간복잡도: O(n) + DFS 사용 + 1. 모든 조합을 찾기 + 2. 조합을 찾을 때, 중복된 조합을 방지하기 + """ + result = [] + + def dfs(start, path, total): + if total == target: + result.append(path[:]) + return + if total> target: + return + + for i in range(start, len(candidates)): + path.append(candidates[i]) + dfs(i, path, total + candidates[i]) + path.pop() + + dfs(0, [], 0) + return result From 637ca7d128f9447e9375b66ea4bbed8237b39766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=A4=EC=99=95=ED=83=9D=5FT6102=28Wang-Taek=20Oh=29?= Date: 2026年3月21日 19:57:23 +0900 Subject: [PATCH 092/526] Number of 1 bits solution --- number-of-1-bits/ohkingtaek.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 number-of-1-bits/ohkingtaek.py diff --git a/number-of-1-bits/ohkingtaek.py b/number-of-1-bits/ohkingtaek.py new file mode 100644 index 0000000000..01c71378ad --- /dev/null +++ b/number-of-1-bits/ohkingtaek.py @@ -0,0 +1,10 @@ +from collections import Counter + +class Solution: + def hammingWeight(self, n: int) -> int: + """ + - 시간복잡도: O(n) + - 공간복잡도: O(n) + 문자열을 이진수로 변환하고, 1의 개수를 세기 + """ + return Counter(bin(n)[2:])["1"] \ No newline at end of file From f295e2f8f84c8829a733edd817975d19343c3fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=A4=EC=99=95=ED=83=9D=5FT6102=28Wang-Taek=20Oh=29?= Date: 2026年3月21日 19:57:33 +0900 Subject: [PATCH 093/526] Valid palindrome solutiuon --- valid-palindrome/ohkingtaek.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 valid-palindrome/ohkingtaek.py diff --git a/valid-palindrome/ohkingtaek.py b/valid-palindrome/ohkingtaek.py new file mode 100644 index 0000000000..5d056438b8 --- /dev/null +++ b/valid-palindrome/ohkingtaek.py @@ -0,0 +1,17 @@ +class Solution: + def isPalindrome(self, s: str) -> bool: + """ + - 시간복잡도: O(n) + - 공간복잡도: O(n) + 1. 문자열을 소문자로 변환하고, 알파벳과 숫자만 남기기 + 2. 남은 문자열을 절반으로 나누고, 앞과 뒤를 비교하여 회문인지 확인 + 3. 회문이면 True, 아니면 False 반환 + """ + a = "" + for i in s.lower(): + if i.isalnum(): + a += i + for i, j in zip(a[:len(a) // 2], a[len(a):(len(a) // 2 - 1):-1]): + if i != j: + return False + return True From 74c8ccc79cf3749cb07e0cf07688c42dea7b5ecb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=A4=EC=99=95=ED=83=9D=28Wang-Taek=20Oh=29?= Date: 2026年3月21日 20:05:24 +0900 Subject: [PATCH 094/526] Add newline at end of ohkingtaek.py Fix missing newline at end of file. --- number-of-1-bits/ohkingtaek.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/number-of-1-bits/ohkingtaek.py b/number-of-1-bits/ohkingtaek.py index 01c71378ad..c3b568cd36 100644 --- a/number-of-1-bits/ohkingtaek.py +++ b/number-of-1-bits/ohkingtaek.py @@ -7,4 +7,4 @@ def hammingWeight(self, n: int) -> int: - 공간복잡도: O(n) 문자열을 이진수로 변환하고, 1의 개수를 세기 """ - return Counter(bin(n)[2:])["1"] \ No newline at end of file + return Counter(bin(n)[2:])["1"] From 82e6ecb4a9ad1d859b2a75fd7a5f19a4e5c19ccd Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年3月21日 20:25:55 +0900 Subject: [PATCH 095/526] week3: number-of-1-bits --- number-of-1-bits/reeseo3o.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 number-of-1-bits/reeseo3o.js diff --git a/number-of-1-bits/reeseo3o.js b/number-of-1-bits/reeseo3o.js new file mode 100644 index 0000000000..9206d9a8e0 --- /dev/null +++ b/number-of-1-bits/reeseo3o.js @@ -0,0 +1 @@ +const hammingWeight = (n) => n.toString(2).split("").filter(b => b === "1").length; From 191748f8d92cdf5b9c8baf1d0413fe4c0c40739e Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年3月21日 20:26:11 +0900 Subject: [PATCH 096/526] week3: combination-sum --- combination-sum/reeseo3o.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 combination-sum/reeseo3o.js diff --git a/combination-sum/reeseo3o.js b/combination-sum/reeseo3o.js new file mode 100644 index 0000000000..8d8d4ea57d --- /dev/null +++ b/combination-sum/reeseo3o.js @@ -0,0 +1,20 @@ +const combinationSum = (candidates, target) => { + const result = []; + + const backtrack = (startIndex, current, remaining) => { + if (remaining === 0) { + result.push([...current]); + return; + } + if (remaining < 0) return; + + for (let i = startIndex; i < candidates.length; i++) { + current.push(candidates[i]); + backtrack(i, current, remaining - candidates[i]); + current.pop(); + } + }; + + backtrack(0, [], target); + return result; +}; From 6c7ec079ee566712de6d9e1cc7a6dc4a8c19fa7f Mon Sep 17 00:00:00 2001 From: robin Date: 2026年3月21日 21:42:58 +0900 Subject: [PATCH 097/526] decode ways solution --- decode-ways/nowrobin.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 decode-ways/nowrobin.js diff --git a/decode-ways/nowrobin.js b/decode-ways/nowrobin.js new file mode 100644 index 0000000000..634a8d1f8d --- /dev/null +++ b/decode-ways/nowrobin.js @@ -0,0 +1,30 @@ +/** + * @param {string} s + * @return {number} + */ +var numDecodings = function(s) { + if (!s || s[0] === '0') { + return 0; + } + + const n = s.length; + const dp = new Array(n + 1).fill(0); + dp[0] = 1; + dp[1] = 1; + + for (let i = 2; i <= n; ++i) { + const oneDigit = parseInt(s[i - 1]); + const twoDigits = parseInt(s.substring(i - 2, i)); + + if (oneDigit !== 0) { + dp[i] += dp[i - 1]; + } + + if (10 <= twoDigits && twoDigits <= 26) { + dp[i] += dp[i - 2]; + } + } + + return dp[n]; +}; + From 417109ed71df553fc767b5034cb11658a4523a66 Mon Sep 17 00:00:00 2001 From: robin Date: 2026年3月21日 21:47:37 +0900 Subject: [PATCH 098/526] combination-sum --- combination-sum/nowrobin.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 combination-sum/nowrobin.js diff --git a/combination-sum/nowrobin.js b/combination-sum/nowrobin.js new file mode 100644 index 0000000000..8082fa7f21 --- /dev/null +++ b/combination-sum/nowrobin.js @@ -0,0 +1,22 @@ +/** + * @param {number[]} candidates + * @param {number} target + * @return {number[][]} + */ +function combinationSum(candidates, target) { + var buffer = []; + var result = []; + search(0, target); + return result; + + function search(startIdx, target) { + if (target === 0) return result.push(buffer.slice()); + if (target < 0) return; + if (startIdx === candidates.length) return; + buffer.push(candidates[startIdx]); + search(startIdx, target - candidates[startIdx]); + buffer.pop(); + search(startIdx + 1, target); + } +}; + From ba931916b03cae1998e5c018c5b6687e8e9949f7 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年3月21日 22:06:53 +0900 Subject: [PATCH 099/526] solved decode-ways. --- combination-sum/sangbeenmoon.py | 6 ------ decode-ways/sangbeenmoon.py | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 decode-ways/sangbeenmoon.py diff --git a/combination-sum/sangbeenmoon.py b/combination-sum/sangbeenmoon.py index 998009875f..4d15a4fb7b 100644 --- a/combination-sum/sangbeenmoon.py +++ b/combination-sum/sangbeenmoon.py @@ -18,9 +18,3 @@ def go(self, i:int, candidates: List[int], nums: List[int], sum_: int, target: i nums.append(candidates[j]) self.go(j, candidates, nums, sum_ + candidates[j], target) nums.pop() - - - - - - diff --git a/decode-ways/sangbeenmoon.py b/decode-ways/sangbeenmoon.py new file mode 100644 index 0000000000..0e54ad53b2 --- /dev/null +++ b/decode-ways/sangbeenmoon.py @@ -0,0 +1,36 @@ +# idea +# 마지막 두자리 수가 독립 가능 -> dp[i] = dp[i-1] + dp[i-2] +# 마지막 한자리 수가 독립 가능 -> dp[i] = dp[i-1] +# 위 두 케이스 모두 불가능 -> 0 반환 +# TC : O(n) +# SC : O(n) + +class Solution: + def numDecodings(self, s: str) -> int: + dp = [1] * len(s) + + if s[0] == '0': + return 0 + + if '1' <= s[0] and s[0] <= '9': + dp[0] = 1 + + for i in range(1, len(s)): + target = s[i-1:i+1] + + if int(s[i]) != 0 and 10 <= int(target) and int(target) <= 26: + dp[i] = dp[i-1] + dp[i-2] + continue + + if int(s[i]) == 0 and 10 <= int(target) and int(target) <= 26: + dp[i] = dp[i-2] + continue + + target = s[i] + if 1 <= int(target) and int(target) <= 9: + dp[i] = dp[i-1] + continue + + return 0 + + return dp[len(s) - 1] From fc25046ed56a51dd927f6dbc1dd437e51f0db423 Mon Sep 17 00:00:00 2001 From: robin Date: 2026年3月21日 22:09:30 +0900 Subject: [PATCH 100/526] max subarray --- maximum-subarray/nowrobin.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 maximum-subarray/nowrobin.js diff --git a/maximum-subarray/nowrobin.js b/maximum-subarray/nowrobin.js new file mode 100644 index 0000000000..99d55523e0 --- /dev/null +++ b/maximum-subarray/nowrobin.js @@ -0,0 +1,25 @@ +/** + * @param {number[]} nums + * @return {number} + */ +var maxSubArray = function(nums) { + if (!nums || nums.length === 0) { + return 0; + } + + // max_so_far: overall maximum sum + let max_so_far = nums[0]; + + // max_ending_here: max sum of subarray ending at current position + let max_ending_here = nums[0]; + + for (let i = 1; i < nums.length; i++) { + // Core decision: start new or extend previous + max_ending_here = Math.max(nums[i], max_ending_here + nums[i]); + + // Update overall maximum + max_so_far = Math.max(max_so_far, max_ending_here); + } + + return max_so_far; +}; From 872cceca4806b0c12ba7f85434170207bd3e8f6b Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年3月21日 22:55:29 +0900 Subject: [PATCH 101/526] could not solve maximun-subarray. --- maximum-subarray/sangbeenmoon.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 maximum-subarray/sangbeenmoon.py diff --git a/maximum-subarray/sangbeenmoon.py b/maximum-subarray/sangbeenmoon.py new file mode 100644 index 0000000000..1aad195eeb --- /dev/null +++ b/maximum-subarray/sangbeenmoon.py @@ -0,0 +1,12 @@ +# 30분 내로 풀지 못함. +# prefix sum 을 사용해서 풀어보려고 했으나 시간 초과. +# dp 문제임을 파악할 수 있는 직관 필요... + +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + dp = [0] * len(nums) + dp[0] = nums[0] + for i in range(1, len(nums)): + dp[i] = max(nums[i], nums[i] + dp[i-1]) + + return max(dp) From 5ff1826f6b6aa06f8827fb6be8c0d5702443c9ba Mon Sep 17 00:00:00 2001 From: yihyun-kim1 Date: 2026年3月22日 12:26:07 +0900 Subject: [PATCH 102/526] add solution: maximum-subarray --- maximum-subarray/yihyun-kim1.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 maximum-subarray/yihyun-kim1.js diff --git a/maximum-subarray/yihyun-kim1.js b/maximum-subarray/yihyun-kim1.js new file mode 100644 index 0000000000..3446f39e96 --- /dev/null +++ b/maximum-subarray/yihyun-kim1.js @@ -0,0 +1,15 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const maxSubArray = (nums) => { + let currentSum = nums[0]; + let maxSum = nums[0]; + + for (let i = 1; i < nums.length; i++) { + currentSum = Math.max(nums[i], currentSum + nums[i]); + maxSum = Math.max(maxSum, currentSum); + } + + return maxSum; +}; From 6613b456813ecc1214040cba1227b55a9daf4af6 Mon Sep 17 00:00:00 2001 From: yihyun-kim1 Date: 2026年3月22日 12:26:18 +0900 Subject: [PATCH 103/526] add solution: number-of-1-bits --- number-of-1-bits/yihyun-kim1.js | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 number-of-1-bits/yihyun-kim1.js diff --git a/number-of-1-bits/yihyun-kim1.js b/number-of-1-bits/yihyun-kim1.js new file mode 100644 index 0000000000..b29e320ddb --- /dev/null +++ b/number-of-1-bits/yihyun-kim1.js @@ -0,0 +1,8 @@ +/** + * @param {number} n + * @return {number} + */ +const hammingWeight = (n) => { + const binary = n.toString(2); + return binary.split("").filter((bit) => bit === "1").length; +}; From ce0ae129ad225950e9875228f314fe9c9340ef63 Mon Sep 17 00:00:00 2001 From: yihyun-kim1 Date: 2026年3月22日 12:26:32 +0900 Subject: [PATCH 104/526] add solution: valid-palindrome --- valid-palindrome/yihyun-kim1.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 valid-palindrome/yihyun-kim1.js diff --git a/valid-palindrome/yihyun-kim1.js b/valid-palindrome/yihyun-kim1.js new file mode 100644 index 0000000000..01fc4bf409 --- /dev/null +++ b/valid-palindrome/yihyun-kim1.js @@ -0,0 +1,10 @@ +/** + * @param {string} s + * @return {boolean} + */ +const isPalindrome = (s) => { + const cleaned = s.toLowerCase().replace(/[^a-z0-9]/g, ""); + const flipped = cleaned.split("").reverse().join(""); + + return cleaned === flipped; +}; From eabf95225bf47f98bb2cb34537e968028c8436b7 Mon Sep 17 00:00:00 2001 From: soobing Date: 2026年3月22日 13:47:01 +0900 Subject: [PATCH 105/526] =?UTF-8?q?feat:=203=EC=A3=BC=EC=B0=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- combination-sum/soobing3.ts | 19 +++++++++++++++++++ decode-ways/soobing3.ts | 14 ++++++++++++++ maximum-subarray/soobing3.ts | 11 +++++++++++ number-of-islands/soobing3.ts | 9 +++++++++ valid-palindrome/soobing3.ts | 12 ++++++++++++ 5 files changed, 65 insertions(+) create mode 100644 combination-sum/soobing3.ts create mode 100644 decode-ways/soobing3.ts create mode 100644 maximum-subarray/soobing3.ts create mode 100644 number-of-islands/soobing3.ts create mode 100644 valid-palindrome/soobing3.ts diff --git a/combination-sum/soobing3.ts b/combination-sum/soobing3.ts new file mode 100644 index 0000000000..276ff87b9b --- /dev/null +++ b/combination-sum/soobing3.ts @@ -0,0 +1,19 @@ +function combinationSum(candidates: number[], target: number): number[][] { + const result: number[][] = []; + + function backtracking(start: number, current: number[], remaining: number) { + if(remaining < 0) return; + if(remaining === 0) { + result.push([...current]); + return; + } + + for(let i = start; i < candidates.length; i++) { + current.push(candidates[i]); + backtracking(i, current, remaining - candidates[i]); + current.pop(); + } + } + backtracking(0, [], target) + return result; +}; diff --git a/decode-ways/soobing3.ts b/decode-ways/soobing3.ts new file mode 100644 index 0000000000..97655932c0 --- /dev/null +++ b/decode-ways/soobing3.ts @@ -0,0 +1,14 @@ +function numDecodings(s: string): number { + const n = s.length; + const dp: number[] = new Array(n + 1).fill(0); + dp[0] = 1; + dp[1] = s[0] === '0' ? 0 : 1; + + for(let i=2; i<= n; i++) { + const one = Number(s[i-1]); + const two = Number(s[i-2] + s[i-1]); + if(one !== 0) dp[i] += dp[i-1]; + if(two>= 10 && two <= 26) dp[i] += dp[i-2]; + } + return dp[n]; +}; diff --git a/maximum-subarray/soobing3.ts b/maximum-subarray/soobing3.ts new file mode 100644 index 0000000000..9cd0073ed8 --- /dev/null +++ b/maximum-subarray/soobing3.ts @@ -0,0 +1,11 @@ +function maxSubArray(nums: number[]): number { + let max = nums[0]; + const dp = new Array(nums.length).fill(0); + dp[0] = Math.max(0, nums[0]); + + for(let i = 1; i < nums.length; i++) { + dp[i] = Math.max(dp[i-1] + nums[i], nums[i]); + max = Math.max(dp[i], max); + } + return max; +}; diff --git a/number-of-islands/soobing3.ts b/number-of-islands/soobing3.ts new file mode 100644 index 0000000000..5d2a326d9b --- /dev/null +++ b/number-of-islands/soobing3.ts @@ -0,0 +1,9 @@ +function hammingWeight(n: number): number { + let count = 0; + for(let i = 31; i>= 0; i--) { + if((n>> i) & 1) { + count++; + } + } + return count; +}; diff --git a/valid-palindrome/soobing3.ts b/valid-palindrome/soobing3.ts new file mode 100644 index 0000000000..f811fcc19d --- /dev/null +++ b/valid-palindrome/soobing3.ts @@ -0,0 +1,12 @@ +function isPalindrome(s: string): boolean { + const original = s.replace(/[^a-zA-Z0-9]/g, '').toLowerCase(); + let left = 0; + let right = original.length - 1; + + while(left < right) { + if(original[left] !== original[right]) return false; + left++; + right--; + } + return true; +}; From 755bda4f47336a5c08379a433d85cf4b2678c22d Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年3月23日 10:11:43 +0900 Subject: [PATCH 106/526] solved merge-two-sorted-lists. --- merge-two-sorted-lists/sangbeenmoon.py | 35 ++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 merge-two-sorted-lists/sangbeenmoon.py diff --git a/merge-two-sorted-lists/sangbeenmoon.py b/merge-two-sorted-lists/sangbeenmoon.py new file mode 100644 index 0000000000..58ea3ef505 --- /dev/null +++ b/merge-two-sorted-lists/sangbeenmoon.py @@ -0,0 +1,35 @@ +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: + + cur1 = list1 + cur2 = list2 + + answer = ListNode() + head = answer + + + while cur1 != None: + if cur2 != None: + if cur1.val>= cur2.val: + answer.next = ListNode(cur2.val) + cur2 = cur2.next + answer = answer.next + else: + answer.next = ListNode(cur1.val) + cur1 = cur1.next + answer = answer.next + else: + answer.next = ListNode(cur1.val) + cur1 = cur1.next + answer = answer.next + + while cur2 != None: + answer.next = ListNode(cur2.val) + cur2 = cur2.next + answer = answer.next + return head.next From 9ea2b26185dc0457ecbd60751a445cb6d20531ef Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年3月23日 14:45:56 +0900 Subject: [PATCH 107/526] add: mergeTwoSortedLists solution --- merge-two-sorted-lists/Cyjin-jani.js | 33 ++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 merge-two-sorted-lists/Cyjin-jani.js diff --git a/merge-two-sorted-lists/Cyjin-jani.js b/merge-two-sorted-lists/Cyjin-jani.js new file mode 100644 index 0000000000..cc0cd01234 --- /dev/null +++ b/merge-two-sorted-lists/Cyjin-jani.js @@ -0,0 +1,33 @@ +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} list1 + * @param {ListNode} list2 + * @return {ListNode} + */ +//! 추후 복습 필요한 문제 +const mergeTwoLists = function (list1, list2) { + // 이 부분을 제한 시간 내에 떠올리지 못해 ai로부터 힌트를 받아 로직을 작성 + let temp = new ListNode(0); + let cur = temp; + + while (list1 !== null && list2 !== null) { + if (list1.val <= list2.val) { + cur.next = list1; + list1 = list1.next; + } else { + cur.next = list2; + list2 = list2.next; + } + cur = cur.next; + } + + cur.next = list1 !== null ? list1 : list2; + + return temp.next; +}; From 0d5c6ea05d1355754de9583d4507a275a5771d52 Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: 2026年3月23日 20:06:43 +0900 Subject: [PATCH 108/526] add solution for valid-palindrome --- valid-palindrome/Hyeri1ee.java | 48 ++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 valid-palindrome/Hyeri1ee.java diff --git a/valid-palindrome/Hyeri1ee.java b/valid-palindrome/Hyeri1ee.java new file mode 100644 index 0000000000..69e332b001 --- /dev/null +++ b/valid-palindrome/Hyeri1ee.java @@ -0,0 +1,48 @@ +import java.util.*; + +//palindrome +class Solution { + public boolean isPalindrome(String s) { + + ArrayList list = new ArrayList(); + //list에 넣기 + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + + if (!Character.isLetterOrDigit(c)) + continue; + + list.add(c); + } + + System.out.println(list.size()); + + boolean ok = true; + int start = 0; + int end = list.size() - 1; + + if (list.size() == 0 || list.size() == 1) + return true; + + //디버깅 + for (int i = 0; i < list.size(); i++) { + System.out.println(list.get(i)); + } + + while (start < end) { + if (Character.toLowerCase(list.get(start)) != + Character.toLowerCase(list.get(end))) { + return false; +} + + start++;end--; + } //end of while + + return ok; + } + + private static boolean isInRange(char c) { + return (c>= 'A') && (c <= 'Z') || (c>= 'a') && (c <= 'z'); + } + +} \ No newline at end of file From 6e304cb482e8ccd572c8a39a7f0a1c0ce005c61e Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: 2026年3月23日 20:08:11 +0900 Subject: [PATCH 109/526] add sollution for number of 1 bits --- number-of-1-bits/Hyeri1ee.java | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 number-of-1-bits/Hyeri1ee.java diff --git a/number-of-1-bits/Hyeri1ee.java b/number-of-1-bits/Hyeri1ee.java new file mode 100644 index 0000000000..119a05a678 --- /dev/null +++ b/number-of-1-bits/Hyeri1ee.java @@ -0,0 +1,20 @@ +import java.util.*; + + +class Solution { + public int hammingWeight(int n) { + + int answer =0; + while (n> 0){ + if ((n & 1) == 1){ + answer++; + + } + n>>>= 1;//unsigned shift + + } + + return answer; + + } +} \ No newline at end of file From e7357b1a5545f9253c66281199b4a38c9eec8968 Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: 2026年3月23日 20:14:44 +0900 Subject: [PATCH 110/526] edit lint error --- number-of-1-bits/Hyeri1ee.java | 2 +- valid-palindrome/Hyeri1ee.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/number-of-1-bits/Hyeri1ee.java b/number-of-1-bits/Hyeri1ee.java index 119a05a678..781eee1896 100644 --- a/number-of-1-bits/Hyeri1ee.java +++ b/number-of-1-bits/Hyeri1ee.java @@ -17,4 +17,4 @@ public int hammingWeight(int n) { return answer; } -} \ No newline at end of file +} diff --git a/valid-palindrome/Hyeri1ee.java b/valid-palindrome/Hyeri1ee.java index 69e332b001..df5acf652e 100644 --- a/valid-palindrome/Hyeri1ee.java +++ b/valid-palindrome/Hyeri1ee.java @@ -45,4 +45,4 @@ private static boolean isInRange(char c) { return (c>= 'A') && (c <= 'Z') || (c>= 'a') && (c <= 'z'); } -} \ No newline at end of file +} From cc9b88cb760d05df55b6b7250604555be73db17d Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年3月24日 13:35:57 +0900 Subject: [PATCH 111/526] add: maximumDepthOfBinary solution --- maximum-depth-of-binary-tree/Cyjin-jani.js | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 maximum-depth-of-binary-tree/Cyjin-jani.js diff --git a/maximum-depth-of-binary-tree/Cyjin-jani.js b/maximum-depth-of-binary-tree/Cyjin-jani.js new file mode 100644 index 0000000000..d7c1513fde --- /dev/null +++ b/maximum-depth-of-binary-tree/Cyjin-jani.js @@ -0,0 +1,28 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +var maxDepth = function (root) { + if (!root) return 0; + let answer = 0; + + function dfs(node, count) { + answer = Math.max(answer, count); + + if (!node.left && !node.right) return; + + if (node.left) dfs(node.left, count + 1); + if (node.right) dfs(node.right, count + 1); + } + dfs(root, 1); + + return answer; +}; From 22ff96cc5d05dedb941e80d480f1a9564d5ee555 Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年3月24日 00:45:54 -0700 Subject: [PATCH 112/526] merge two sorted lists solution --- merge-two-sorted-lists/jylee2033.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 merge-two-sorted-lists/jylee2033.py diff --git a/merge-two-sorted-lists/jylee2033.py b/merge-two-sorted-lists/jylee2033.py new file mode 100644 index 0000000000..8723e36486 --- /dev/null +++ b/merge-two-sorted-lists/jylee2033.py @@ -0,0 +1,27 @@ +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: + # Use a while loop to compare values and build the merged list + + # Create a new list + output = ListNode() + cur = output + + while list1 and list2: + if list1.val < list2.val: + cur.next = list1 + list1 = list1.next + else: + cur.next = list2 + list2 = list2.next + + cur = cur.next + + # Attach the remaining nodes + cur.next = list1 or list2 + + return output.next From 425459bd4957c63828744ce3c10bf5a166fa9161 Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年3月24日 00:53:08 -0700 Subject: [PATCH 113/526] add complexity --- merge-two-sorted-lists/jylee2033.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/merge-two-sorted-lists/jylee2033.py b/merge-two-sorted-lists/jylee2033.py index 8723e36486..439dd983e0 100644 --- a/merge-two-sorted-lists/jylee2033.py +++ b/merge-two-sorted-lists/jylee2033.py @@ -25,3 +25,6 @@ def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> cur.next = list1 or list2 return output.next + +# Time Complexity : O(n + m), n - lenght of list1, m - length of list2 +# Space Complexity : O(1) From 4a2e8577c434a4a0d49036d6ef75c814b65fcc23 Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: 2026年3月24日 20:33:19 +0900 Subject: [PATCH 114/526] merge two sorted lists solution --- merge-two-sorted-lists/robinyoon-dev.js | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 merge-two-sorted-lists/robinyoon-dev.js diff --git a/merge-two-sorted-lists/robinyoon-dev.js b/merge-two-sorted-lists/robinyoon-dev.js new file mode 100644 index 0000000000..1a00fa9ad5 --- /dev/null +++ b/merge-two-sorted-lists/robinyoon-dev.js @@ -0,0 +1,37 @@ +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} list1 + * @param {ListNode} list2 + * @return {ListNode} + */ +var mergeTwoLists = function (list1, list2) { + + let dummy = new ListNode(-1); + let current = dummy; + + while (list1 !== null && list2 !== null) { + if (list1.val <= list2.val) { + current.next = list1; + list1 = list1.next; + } else { + current.next = list2; + list2 = list2.next; + } + current = current.next; + } + + if (list1 !== null) { + current.next = list1; + } else { + current.next = list2; + } + + return dummy.next; +}; + From a1645c892ad3860810244a893aebad2c4494f494 Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: 2026年3月24日 20:56:17 +0900 Subject: [PATCH 115/526] maximum depth of binary tree solution --- maximum-depth-of-binary-tree/robinyoon-dev.js | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 maximum-depth-of-binary-tree/robinyoon-dev.js diff --git a/maximum-depth-of-binary-tree/robinyoon-dev.js b/maximum-depth-of-binary-tree/robinyoon-dev.js new file mode 100644 index 0000000000..0d9caf223b --- /dev/null +++ b/maximum-depth-of-binary-tree/robinyoon-dev.js @@ -0,0 +1,24 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +var maxDepth = function (root) { + + //NOTE: 현재 노드의 최대 깊이는 왼쪽 자식 트리의 최대 깊이와 오른쪽 자식 트리의 최대 깊이 중 큰 값에 1(현재 노드)을 더한 값 + if (root === null) { + return 0; + } + + const leftDepth = maxDepth(root.left); + const rightDepth = maxDepth(root.right); + + return Math.max(leftDepth, rightDepth) + 1; +}; From 0160870f04acc2f1edabaa30b343d017ad247548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=EC=98=81?= Date: 2026年3月24日 21:42:51 +0900 Subject: [PATCH 116/526] =?UTF-8?q?merge-two-sorted-lists=20=ED=92=80?= =?UTF-8?q?=EC=9D=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- merge-two-sorted-lists/junzero741.ts | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 merge-two-sorted-lists/junzero741.ts diff --git a/merge-two-sorted-lists/junzero741.ts b/merge-two-sorted-lists/junzero741.ts new file mode 100644 index 0000000000..a3b8c55fe5 --- /dev/null +++ b/merge-two-sorted-lists/junzero741.ts @@ -0,0 +1,30 @@ + class ListNode { + val: number + next: ListNode | null + constructor(val?: number, next?: ListNode | null) { + this.val = (val===undefined ? 0 : val) + this.next = (next===undefined ? null : next) + } + } + + +function mergeTwoLists(list1: ListNode | null, list2: ListNode | null): ListNode | null { + + const dummy = new ListNode(); + let tail = dummy; + + while (list1 && list2) { + if (list1.val <= list2.val) { + tail.next = list1; + list1 = list1.next; + } else { + tail.next = list2; + list2 = list2.next; + } + tail = tail.next; + } + + tail.next = list1 || list2; + + return dummy.next; +}; From 4f87fdb1004db54a77e617c87aa3bc73bddac1ce Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: 2026年3月25日 11:12:25 +0900 Subject: [PATCH 117/526] find minimum in rotated sorted array --- .../robinyoon-dev.js | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/robinyoon-dev.js diff --git a/find-minimum-in-rotated-sorted-array/robinyoon-dev.js b/find-minimum-in-rotated-sorted-array/robinyoon-dev.js new file mode 100644 index 0000000000..eb3f2a76df --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/robinyoon-dev.js @@ -0,0 +1,22 @@ +/** + * @param {number[]} nums + * @return {number} + */ +var findMin = function(nums) { + // nums는 rotated 된 array + // return 값은 이 nums에서 최솟값을 return 해야함. + const NUMS_LENGTH = nums.length; + + let result = nums[0]; + + for(let i = 0; i < NUMS_LENGTH; i++ ){ + let currentIndex = NUMS_LENGTH - i; + + if(nums[currentIndex - 1]> nums[currentIndex]){ + result = nums[currentIndex]; + }else{ + continue; + } + } + return result; +}; From 95c217481799e3782aa87e13d03d308bde883b56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=EC=98=81?= Date: 2026年3月25日 11:35:22 +0900 Subject: [PATCH 118/526] =?UTF-8?q?maximum-depth-of-binary-tree=20?= =?UTF-8?q?=ED=92=80=EC=9D=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- maximum-depth-of-binary-tree/junzero741.ts | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 maximum-depth-of-binary-tree/junzero741.ts diff --git a/maximum-depth-of-binary-tree/junzero741.ts b/maximum-depth-of-binary-tree/junzero741.ts new file mode 100644 index 0000000000..2069f88bb3 --- /dev/null +++ b/maximum-depth-of-binary-tree/junzero741.ts @@ -0,0 +1,38 @@ +class TreeNode { + val: number + left: TreeNode | null + right: TreeNode | null + constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + this.val = (val===undefined ? 0 : val) + this.left = (left===undefined ? null : left) + this.right = (right===undefined ? null : right) + } +} + +// TC: O(N) +// SC: O(N) +function maxDepth(root: TreeNode | null): number { + if(!root) { + return 0; + } + + let maxLv = 1; + + function dfs(node: TreeNode, lv: number) { + if(node.left) { + dfs(node.left, lv+1) + } + if(node.right) { + dfs(node.right, lv+1) + } + maxLv = Math.max(maxLv, lv) + } + + + dfs(root, 1); + + + return maxLv; + + +}; From c159fc11948240ccaed98714eeb8c7994f353e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年3月25日 14:51:17 +0900 Subject: [PATCH 119/526] Add solution for Word Search problem using backtracking --- word-search/gcount85.py | 42 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 word-search/gcount85.py diff --git a/word-search/gcount85.py b/word-search/gcount85.py new file mode 100644 index 0000000000..c54cfeb842 --- /dev/null +++ b/word-search/gcount85.py @@ -0,0 +1,42 @@ +""" +# Intuition +백트래킹으로 풀었습니다. + +# Complexity +- Time complexity: O(M*N*3^L) => M*N 보드 한 칸을 모두 방문하며, +word 의 길이(L) 횟수 단계 만큼 탐색해야 한다. 매 단계 탐색할 때는 매번 3갈래씩 길을 찾는다. + +- Space complexity: 재귀 스택 O(L), visited 크기 O(L) +""" + + +class Solution: + def exist(self, board: list[list[str]], word: str) -> bool: + m, n = len(board[0]), len(board) + direction = [[0, 1], [0, -1], [1, 0], [-1, 0]] + + def dfs(x, y, cur_step, visited): + if cur_step == len(word) - 1: + return True + + for dx, dy in direction: + nx, ny = x + dx, y + dy + if nx < 0 or ny < 0 or nx>= n or ny>= m: + continue + if board[nx][ny] != word[cur_step + 1]: + continue + if (nx, ny) in visited: + continue + visited.add((nx, ny)) + if dfs(nx, ny, cur_step + 1, visited): + return True + visited.discard((nx, ny)) + return False + + for x, row in enumerate(board): + for y, start_word in enumerate(row): + if word[0] != start_word: + continue + if dfs(x, y, 0, {(x, y)}): + return True + return False From 99719580ef912306a464ac1942fbb73183c5d374 Mon Sep 17 00:00:00 2001 From: SamTheKorean Date: 2026年3月25日 19:41:11 -0400 Subject: [PATCH 120/526] solve : merge two lists --- merge-two-sorted-lists/samthekorean.go | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 merge-two-sorted-lists/samthekorean.go diff --git a/merge-two-sorted-lists/samthekorean.go b/merge-two-sorted-lists/samthekorean.go new file mode 100644 index 0000000000..9f5a169e23 --- /dev/null +++ b/merge-two-sorted-lists/samthekorean.go @@ -0,0 +1,27 @@ +// TC : O(n) n being the length of list +// SC : O(n) n being the size of the two list +func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode { + // Create a dummy node to simplify edge cases + dummy := &ListNode{} + current := dummy + + // Merge lists + for list1 != nil && list2 != nil { + if list1.Val < list2.Val { + current.Next = list1 + list1 = list1.Next + } else { + current.Next = list2 + list2 = list2.Next + } + current = current.Next + } + + if list1 != nil { + current.Next = list1 + } else { + current.Next = list2 + } + + return dummy.Next +} From f7989cd31310d6469d2800021a3e8c0930641b74 Mon Sep 17 00:00:00 2001 From: Dale Seo <5466341+daleseo@users.noreply.github.com> Date: 2026年3月25日 21:34:14 -0400 Subject: [PATCH 121/526] maximum-depth-of-binary-tree --- maximum-depth-of-binary-tree/DaleSeo.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 maximum-depth-of-binary-tree/DaleSeo.rs diff --git a/maximum-depth-of-binary-tree/DaleSeo.rs b/maximum-depth-of-binary-tree/DaleSeo.rs new file mode 100644 index 0000000000..39cce76f2c --- /dev/null +++ b/maximum-depth-of-binary-tree/DaleSeo.rs @@ -0,0 +1,19 @@ +// TC: O(n) +// SC: O(n) +use std::cell::RefCell; +use std::rc::Rc; + +impl Solution { + pub fn max_depth(root: Option>>) -> i32 { + match root { + None => 0, + Some(node) => { + let node = node.borrow(); + 1 + std::cmp::max( + Self::max_depth(node.left.clone()), + Self::max_depth(node.right.clone()), + ) + } + } + } +} From 31ed407796eab978398db171fcb1b41d389c5fc8 Mon Sep 17 00:00:00 2001 From: Ted Date: 2026年3月25日 22:48:40 -0400 Subject: [PATCH 122/526] add week 4 solution --- .../tedkimdev.go | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/tedkimdev.go diff --git a/find-minimum-in-rotated-sorted-array/tedkimdev.go b/find-minimum-in-rotated-sorted-array/tedkimdev.go new file mode 100644 index 0000000000..225bf05f2c --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/tedkimdev.go @@ -0,0 +1,26 @@ +// TC: O(log n) +// SC: O(1) +func findMin(nums []int) int { + min := nums[0] + l, r := 0, len(nums)-1 + + for l <= r { + if nums[l] < min { + min = nums[l] + } + break + } + + m := l + (r-l)/2 + if nums[m] < min { + min = nums[m] + } + + if nums[m]>= nums[l] { + l = m + 1 + } else { + r = m - 1 + } + } + return min +} From 3629dbe90f8b13a5132067d02ca03a710ed9eb2b Mon Sep 17 00:00:00 2001 From: juhui Date: 2026年3月26日 12:51:18 +0900 Subject: [PATCH 123/526] WEEK 04 Solutions --- maximum-depth-of-binary-tree/juhui-jeong.java | 27 ++++++++++++++ merge-two-sorted-lists/juhui-jeong.java | 35 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 maximum-depth-of-binary-tree/juhui-jeong.java create mode 100644 merge-two-sorted-lists/juhui-jeong.java diff --git a/maximum-depth-of-binary-tree/juhui-jeong.java b/maximum-depth-of-binary-tree/juhui-jeong.java new file mode 100644 index 0000000000..17554de07b --- /dev/null +++ b/maximum-depth-of-binary-tree/juhui-jeong.java @@ -0,0 +1,27 @@ +/** + * 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 int maxDepth(TreeNode root) { + if (root == null) { + return 0; + } + + int leftDepth = maxDepth(root.left); + int rightDepth = maxDepth(root.right); + + return Math.max(leftDepth, rightDepth) +1; + } +} diff --git a/merge-two-sorted-lists/juhui-jeong.java b/merge-two-sorted-lists/juhui-jeong.java new file mode 100644 index 0000000000..32ee87ae08 --- /dev/null +++ b/merge-two-sorted-lists/juhui-jeong.java @@ -0,0 +1,35 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode mergeTwoLists(ListNode list1, ListNode list2) { + ListNode dummy = new ListNode(0); + ListNode current = dummy; + + while(list1 != null && list2 != null) { + if (list1.val <= list2.val) { + current.next = list1; + list1 = list1.next; + } else { + current.next = list2; + list2 = list2.next; + } + current = current.next; + } + + if (list1 != null) { + current.next = list1; + } else { + current.next = list2; + } + + return dummy.next; + } +} From af39f1ff4a4f43358b94434119e6832a80382a5c Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年3月25日 22:34:36 -0700 Subject: [PATCH 124/526] maximum depth of binary tree solution --- maximum-depth-of-binary-tree/jylee2033.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 maximum-depth-of-binary-tree/jylee2033.py diff --git a/maximum-depth-of-binary-tree/jylee2033.py b/maximum-depth-of-binary-tree/jylee2033.py new file mode 100644 index 0000000000..575d96dd19 --- /dev/null +++ b/maximum-depth-of-binary-tree/jylee2033.py @@ -0,0 +1,20 @@ +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def maxDepth(self, root: Optional[TreeNode]) -> int: + # Recursive approach + + if not root: + return 0 + + left_depth = self.maxDepth(root.left) + right_depth = self.maxDepth(root.right) + + return max(left_depth, right_depth) + 1 + +# Time Complexity: O(n) +# Space Complexity: O(n) From 65e96d034dbf6c9ad6d42586b40f6086f4d35943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年3月26日 15:13:06 +0900 Subject: [PATCH 125/526] Add solution for Coin Change problem using dynamic programming --- coin-change/gcount85.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 coin-change/gcount85.py diff --git a/coin-change/gcount85.py b/coin-change/gcount85.py new file mode 100644 index 0000000000..9debbd3698 --- /dev/null +++ b/coin-change/gcount85.py @@ -0,0 +1,26 @@ +""" +# Intuition +dp[n]은 n원을 만드는데 필요한 최소 동전 개수 +e.g. n = 11일 때, 11원을 만들기 위한 최소 동전 개수는 11에서 coins의 원소를 뺀 dp 값 + 1이다. + +# Complexity +- Time complexity: O(amount * coins.length)인데, coins 배열 길이가 상수라서 무시 => O(amount) + +- Space complexity: dp 배열 생성으로 O(amount) +""" + + +class Solution: + def coinChange(self, coins: list[int], amount: int) -> int: + coins.sort() + INF = float("inf") + dp = [INF] * (amount + 1) + dp[0] = 0 + for i in range(amount + 1): + if dp[i] == INF: + continue + for c in coins: + if i + c> amount: + break + dp[i + c] = min(dp[i + c], dp[i] + 1) + return dp[-1] if dp[-1] != INF else -1 From df92478e767196c8ae14b3d000589d77237de74c Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年3月26日 15:32:36 +0900 Subject: [PATCH 126/526] add: findMinInRotatedSortedArr solution --- .../Cyjin-jani.js | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/Cyjin-jani.js diff --git a/find-minimum-in-rotated-sorted-array/Cyjin-jani.js b/find-minimum-in-rotated-sorted-array/Cyjin-jani.js new file mode 100644 index 0000000000..93a4e66e30 --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/Cyjin-jani.js @@ -0,0 +1,43 @@ +// math의 min을 이용하는 방법 +// tc: O(n) +// sc: 잘 몰랐는데 모든 요소를 함수 인자로 풀어 콜스택에 올린다 하여 O(n)이 된다고 함.. +// (대용량의 배열 시 maximum exceed 에러가 날 수 있음) +const findMin_use_math_min = function (nums) { + return Math.min(...nums); +}; + +// 메서드를 사용하지 않은 풀이. +// tc: O(n) +// sc: O(1) +const findMin_naive = function (nums) { + let min = nums[0]; + + for (let i = 1; i < nums.length; i++) { + if (nums[i] <= min) { + min = nums[i]; + break; + } + } + + return min; +}; + +// 시간복잡도를 문제의 요구사항에 맞도록 줄여본 풀이 +// tc: O(logn) +// sc: O(1) +const findMin = function (nums) { + let left = 0, + right = nums.length - 1; + + while (left < right) { + let mid = Math.floor((left + right) / 2); + + if (nums[mid]> nums[right]) { + left = mid + 1; + } else { + right = mid; + } + } + + return nums[left]; +}; From ff09514377981348b64dbe208eb51f5157c2f86b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年3月26日 16:06:56 +0900 Subject: [PATCH 127/526] Add solution for Find Minimum in Rotated Sorted Array using binary search --- .../gcount85.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/gcount85.py diff --git a/find-minimum-in-rotated-sorted-array/gcount85.py b/find-minimum-in-rotated-sorted-array/gcount85.py new file mode 100644 index 0000000000..c7d7276917 --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/gcount85.py @@ -0,0 +1,27 @@ +""" +# Intuition +이진탐색으로 찾는다. + +# Complexity +- Time complexity: nums의 길이 N일때, O(logN) + +- Space complexity: 재귀스택 O(logN) +""" + + +class Solution: + def findMin(self, nums: list[int]) -> int: + l, m, r = 0, len(nums) // 2, len(nums) - 1 + + def findMinimum(l, m, r): + if l == m or r == m: + return min(nums[l], nums[r]) + + # 오른쪽 구간 + if nums[m]> nums[r]: + return findMinimum(m, (m + r) // 2, r) + + # 왼쪽 구간 + return findMinimum(l, (l + m) // 2, m) + + return findMinimum(l, m, r) From b0f7da238af3d5829c3abe695ec274a33f09755e Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: 2026年3月26日 16:11:10 +0900 Subject: [PATCH 128/526] word search solution --- word-search/robinyoon-dev.js | 57 ++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 word-search/robinyoon-dev.js diff --git a/word-search/robinyoon-dev.js b/word-search/robinyoon-dev.js new file mode 100644 index 0000000000..69b71c6efc --- /dev/null +++ b/word-search/robinyoon-dev.js @@ -0,0 +1,57 @@ +/** + * @param {character[][]} board + * @param {string} word + * @return {boolean} + */ +var exist = function (board, word) { + + let tempResult = false; + + for (let i = 0; i < board.length; i++) { + for (let j = 0; j < board[0].length; j++) { + if (board[i][j] === word[0]) { + tempResult = dfs(i, j, 0); + if (tempResult) { + return true; + } + } else { + continue; + } + } + } + + + return tempResult; + + + + function dfs(x, y, currentIndex) { + + if (x < 0 || y < 0 || x>= board.length || y>= board[0].length) { + return false; + } + + if (board[x][y] !== word[currentIndex]) { + return false; + } + + let nextIndex = currentIndex + 1; + + if (nextIndex === word.length) { + return true; + } + + let tempChar = board[x][y]; + board[x][y] = '*'; + + + let hasCharOnTheLeft = dfs(x - 1, y, nextIndex); + let hasCharOnTheRight = dfs(x + 1, y, nextIndex); + let hasCharAtTheTop = dfs(x, y + 1, nextIndex); + let hasCharAtTheBottom = dfs(x, y - 1, nextIndex); + + board[x][y] = tempChar; + + return hasCharOnTheLeft || hasCharOnTheRight || hasCharAtTheTop || hasCharAtTheBottom; + } +}; From 97931a0777d3edb4b232f8e1fb953c429a4c7a45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年3月26日 16:20:47 +0900 Subject: [PATCH 129/526] Add solution for merging two sorted lists --- merge-two-sorted-lists/gcount85.py | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 merge-two-sorted-lists/gcount85.py diff --git a/merge-two-sorted-lists/gcount85.py b/merge-two-sorted-lists/gcount85.py new file mode 100644 index 0000000000..cb338b5118 --- /dev/null +++ b/merge-two-sorted-lists/gcount85.py @@ -0,0 +1,34 @@ +""" +# Intuition +각각의 리스트의 첫 노드를 가리키면서 병합 리스트를 생성한다. + +# Complexity +- Time complexity: list1과 list2의 길이 N, M일때 O(N+M) + +- Space complexity: 기존 노드 연결만 바꿈 O(1) +""" + + +class Solution: + def mergeTwoLists( + self, list1: Optional[ListNode], list2: Optional[ListNode] + ) -> Optional[ListNode]: + dummy = ListNode(0) + tail = dummy + + while list1 and list2: + if list1.val <= list2.val: + tail.next = list1 + list1 = list1.next + else: + tail.next = list2 + list2 = list2.next + tail = tail.next + + # 남은 쪽 붙이기 + if list1: + tail.next = list1 + else: + tail.next = list2 + + return dummy.next From afdd5ede83f43c7a3b5fdc829a59dc2bdf0915c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年3月26日 16:28:46 +0900 Subject: [PATCH 130/526] Refactor maxDepth function implementation for clarity and conciseness --- maximum-depth-of-binary-tree/gcount85.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/maximum-depth-of-binary-tree/gcount85.py b/maximum-depth-of-binary-tree/gcount85.py index b705564184..1e8bc6982b 100644 --- a/maximum-depth-of-binary-tree/gcount85.py +++ b/maximum-depth-of-binary-tree/gcount85.py @@ -2,7 +2,7 @@ # Intuition 1) BFS + 큐 2) DFS + 재귀 -1번으로 풀었다가 2번이 코드가 더 간결해서 바꿨습니다. +1번으로 풀었다가 2번이 코드가 더 간결해서 바꿨습니다. # Complexity - Time complexity: 모든 노드를 다 봐야 하므로 O(N) @@ -10,10 +10,9 @@ - Space complexity: 재귀 깊이만큼 O(H) """ + class Solution: def maxDepth(self, root: Optional[TreeNode]) -> int: if not root: return 0 return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right)) - - \ No newline at end of file From f5193a7f7a2ef31eea6968c8af9b676faaf00b3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=EC=98=81?= Date: 2026年3月26日 19:30:19 +0900 Subject: [PATCH 131/526] =?UTF-8?q?find-minimum-in-rotated-sorted-array=20?= =?UTF-8?q?=ED=92=80=EC=9D=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../junzero741.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/junzero741.ts diff --git a/find-minimum-in-rotated-sorted-array/junzero741.ts b/find-minimum-in-rotated-sorted-array/junzero741.ts new file mode 100644 index 0000000000..927c53061c --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/junzero741.ts @@ -0,0 +1,18 @@ +// TC: O(logN) +// SC: O(1) +function findMin(nums: number[]): number { + let left = 0; + let right = nums.length - 1; + + while (left < right) { + const mid = Math.floor((left+right)/2); + if(nums[mid]> nums[right]) { + left = mid + 1; + } else { + right = mid; + } + } + + return nums[left]; + +}; From 8d5456c373806cdf158a4513a81413842436958a Mon Sep 17 00:00:00 2001 From: Yu-Won Date: 2026年3月26日 22:09:46 +0900 Subject: [PATCH 132/526] merge two sorted list solution --- merge-two-sorted-lists/Yu-Won.js | 35 ++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 merge-two-sorted-lists/Yu-Won.js diff --git a/merge-two-sorted-lists/Yu-Won.js b/merge-two-sorted-lists/Yu-Won.js new file mode 100644 index 0000000000..820d48d723 --- /dev/null +++ b/merge-two-sorted-lists/Yu-Won.js @@ -0,0 +1,35 @@ +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + * + * 문제: https://leetcode.com/problems/merge-two-sorted-lists/ + * 요구사항: 정의된 ListNode 를 활용해서 정렬된 배열을 리턴 + */ +/** + * @param {ListNode} list1 + * @param {ListNode} list2 + * @return {ListNode} + */ + + +const mergeTwoLists = (list1, list2) => { + const dummy = new ListNode(0); + let cur = dummy; + + while (list1 && list2) { + if (list1.val <= list2.val) { + cur.next = list1; + list1 = list1.next; + } else { + cur.next = list2; + list2 = list2.next; + } + cur = cur.next; + } + + cur.next = list1 ?? list2; + return dummy.next; +}; From 7b641d38f791a39bb6e20041f54d53ac8d65aabb Mon Sep 17 00:00:00 2001 From: Yu-Won Date: 2026年3月26日 22:27:06 +0900 Subject: [PATCH 133/526] merge depth solution --- maximum-depth-of-binary-tree/Yu-Won.js | 34 ++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 maximum-depth-of-binary-tree/Yu-Won.js diff --git a/maximum-depth-of-binary-tree/Yu-Won.js b/maximum-depth-of-binary-tree/Yu-Won.js new file mode 100644 index 0000000000..a387bc4cc6 --- /dev/null +++ b/maximum-depth-of-binary-tree/Yu-Won.js @@ -0,0 +1,34 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * + * 문제: https://leetcode.com/problems/maximum-depth-of-binary-tree/ + * 요구사항: 이진 트리의 최대 깊이를 반환하라. + */ +/** + * @param {TreeNode} root + * @return {number} + */ +const maxDepth = (root) => { + if(!root) return 0; + + let queue = [root]; + let depth = 0; + + while(queue.length) { + let size = queue.length; + + for(let i = 0; i < size; i++) { + let node = queue.shift(); + + if(node.left) queue.push(node.left); + if(node.right) queue.push(node.right); + } + depth++; + } + return depth; +}; From 90d3c1240aa76f53d25a18d008d6bb18dce406d8 Mon Sep 17 00:00:00 2001 From: grapefruit Date: 2026年3月26日 22:33:22 +0900 Subject: [PATCH 134/526] solution of maximum depth of binary tree --- maximum-depth-of-binary-tree/grapefruit13.ts | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 maximum-depth-of-binary-tree/grapefruit13.ts diff --git a/maximum-depth-of-binary-tree/grapefruit13.ts b/maximum-depth-of-binary-tree/grapefruit13.ts new file mode 100644 index 0000000000..8df7c81cc1 --- /dev/null +++ b/maximum-depth-of-binary-tree/grapefruit13.ts @@ -0,0 +1,23 @@ +class TreeNode { + val: number; + left: TreeNode | null; + right: TreeNode | null; + constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + this.val = val === undefined ? 0 : val; + this.left = left === undefined ? null : left; + this.right = right === undefined ? null : right; + } +} + +/** + * Time Complexity: O(n) + * Space Complexity: O(h) + */ +function maxDepth(root: TreeNode | null): number { + if (root === null) return 0; + + let left = maxDepth(root.left); + let right = maxDepth(root.right); + + return 1 + Math.max(left, right); +} From e55157c7945375e2a08efca5bac797b2ad74d5eb Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年3月26日 23:00:48 +0900 Subject: [PATCH 135/526] [7th batch] week 4 - maximum depth of binary tree --- maximum-depth-of-binary-tree/liza0525.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/maximum-depth-of-binary-tree/liza0525.py b/maximum-depth-of-binary-tree/liza0525.py index 423ca7731d..d248e53ada 100644 --- a/maximum-depth-of-binary-tree/liza0525.py +++ b/maximum-depth-of-binary-tree/liza0525.py @@ -36,3 +36,25 @@ def find_max_depth(cur_node, depth): max_depth = find_max_depth(root, 0) return max_depth + + +# 7기 풀이 +# 시간복잡도: O(n) +# - 트리의 모든 노드를 한 번 씩 방문하므로, 전체 노드 수 n만큼 시간이 걸림 +# 공간복잡도: O(n) +# - 트리의 높이만큼 재귀 스택이 쌓임. 최악의 경우는 트리가 한 쪽으로 치우쳤을 때이므로 노드 n만큼의 최대 스택을 쌓게 됨 +class Solution: + def maxDepth(self, root: Optional[TreeNode]) -> int: + def find_depth(node, depth): + if not node: + # node가 None일 때는 depth을 그대로 반환 + return depth + # 현재 노드 기준 왼쪽 노드 쪽의 깊이 탐색 + left_depth = find_depth(node.left, depth + 1) + # 현재 노드 기준 오른쪽 노드 쪽의 깊이 탐색 + right_depth = find_depth(node.right, depth + 1) + + # 왼쪽과 오른쪽 중 더 깊은 depth를 반환 + return max(left_depth, right_depth) + + return find_depth(root, 0) From a651ff5f917fd4fcec358ec192440405e356b8b2 Mon Sep 17 00:00:00 2001 From: grapefruit Date: 2026年3月26日 23:01:22 +0900 Subject: [PATCH 136/526] solution of merge two sorted lists --- merge-two-sorted-lists/grapefruit13.ts | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 merge-two-sorted-lists/grapefruit13.ts diff --git a/merge-two-sorted-lists/grapefruit13.ts b/merge-two-sorted-lists/grapefruit13.ts new file mode 100644 index 0000000000..8002e81abc --- /dev/null +++ b/merge-two-sorted-lists/grapefruit13.ts @@ -0,0 +1,33 @@ +class ListNode { + val: number; + next: ListNode | null; + constructor(val?: number, next?: ListNode | null) { + this.val = val === undefined ? 0 : val; + this.next = next === undefined ? null : next; + } +} + +/** + * Time Complexity: O(n + m) + * Space Complexity: O(1) + */ +function mergeTwoLists( + list1: ListNode | null, + list2: ListNode | null +): ListNode | null { + const dummy = new ListNode(0); + let current = dummy; + + while (list1 && list2) { + if (list1.val < list2.val) { + current.next = list1; + list1 = list1.next; + } else { + current.next = list2; + list2 = list2.next; + } + current = current.next; + } + current.next = list1 || list2; + return dummy.next; +} From cf57e148d41b7ef86edf2cd7f34b09cbe5b2a1b8 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年3月26日 23:08:18 +0900 Subject: [PATCH 137/526] [7th batch] week 4 - search in rotated sorted array --- search-in-rotated-sorted-array/liza0525.py | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 search-in-rotated-sorted-array/liza0525.py diff --git a/search-in-rotated-sorted-array/liza0525.py b/search-in-rotated-sorted-array/liza0525.py new file mode 100644 index 0000000000..18fbf3f0d4 --- /dev/null +++ b/search-in-rotated-sorted-array/liza0525.py @@ -0,0 +1,30 @@ +# 7기 풀이 +# 시간 복잡도: O(log n) +# - binary search를 이용했기 때문에 최악의 경우는 log n +# 공간 복잡도: O(1) +# - 몇 가지 변수만 사용됨 +class Solution: + def findMin(self, nums: List[int]) -> int: + # 양 끝을 먼저 잡아준다 + left, right = 0, len(nums) - 1 + + # left보다 right가 클 때 계속 루프를 돈다 + # 이는 left와 right가 같아질 때까지 돈다는 말과 동일하다 + while left < right: + # 중간 index 계산 + mid = (left + right) // 2 + + if nums[mid]> nums[right]: + # 중간 index의 값이 오른쪽 index의 값보다 크다는 것은 + # 최소 값이 mid 기준 오른쪽 구역에 존재하기 때문에 left을 mid쪽으로 움직인다. + # mid의 값 자체는 최소값이 될 수 없기 때문에 left는 이보다 한 칸 옆으로 움직여야 함 + left = mid + 1 + else: + # 중간 index의 값이 오른쪽 index의 값보다 작다는 것은 + # 최소 값이 mid 기준 왼쪽 구역에 존재하기 때문에 right를 mid쪽으로 움직인다. + # mid의 값 자체는 최소값이 될 수 있기 때문에 right는 mid 값을 할당한다. + right = mid + + # left와 right가 같아질 때(최소값을 찾았을 때) 루프 탈출을 하기 때문에 + # nums[left] 또는 nums[right]를 반환 + return nums[left] From 08a7d6cb5d87cb0720800195fa6adac97f0ac594 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年3月26日 23:22:23 +0900 Subject: [PATCH 138/526] [7th batch] week 4 - word search --- word-search/liza0525.py | 70 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/word-search/liza0525.py b/word-search/liza0525.py index 8db031f723..5083c2f765 100644 --- a/word-search/liza0525.py +++ b/word-search/liza0525.py @@ -65,3 +65,73 @@ def dfs(i, j, str_index): # 모든 시도를 해도 못 찾으면 False return False + + +# 7기 풀이 +# 시간 복잡도: O((n * m) * 4 ^ d) +# - depth의 길이(d)만큼 네 방향을 탐색하며, 출발점의 개수 n * m 모두 탐색할 때 최악의 시간 +# 공간 복잡도: O(n * m) +# - visited 변수를 사용하기 때문에 행 * 열의 개수만큼의 공간을 필요로 함 +class Solution: + def exist(self, board: List[List[str]], word: str) -> bool: + # 보드의 행, 열의 길이를 미리 저장 + num_rows = len(board) + num_cols = len(board[0]) + + # dfs 탐색 시 이미 방문한 경우를 체크하기 위한 visited를 생성 + visited = [[0 for _ in range(num_cols)] for _ in range(num_rows)] + + # dfs 탐색 시 한 칸을 기준으로 하여 4방향으로 탐색 가능하게 directions을 만든다. + # 순서대로 아래로 진출, 위로 진출, 왼쪽으로 진출, 오른쪽으로 진출 + directions = [(0, 1), (0, -1), (-1, 0), (1, 0)] + + def check_exist_word(i, j, depth): + if depth == len(word) - 1: + # depth가 word의 길이에 가까워지면(배열이라 -1 해줌) + # 탐색을 마쳤으므로 True를 반환 + return True + + # 현재의 칸은 방문했다는 의미로 1로 변경 + visited[i][j] = 1 + for dir_i, dir_j in directions: + # 네 방향을 순차로 탐색한다. + # 다음 칸의 위치를 나타내는 next_i와 next_j를 먼저 계산 + next_i, next_j = i + dir_i, j + dir_j + if not ( + 0 <= next_i < num_rows # 다음 칸의 행 번호가 행의 길이 내에 있고 + and 0 <= next_j < num_cols # 다음 칸의 열 번호가 열의 길이 내에 있고 + and not visited[next_i][next_j] # 아직 방문하지 않았으며 + and board[next_i][next_j] == word[depth + 1] # 다음 글자가 word의 다음 글자에 해당해야 함 + ): + # 그렇지 않은 경우에는 탐색할 필요가 없으므로 다음 방향을 찾는다 + continue + + # 위의 조건을 모두 만족하면 탐색해도 된다. + exist_word = check_exist_word( + next_i, + next_j, + depth + 1 # word의 다음 index를 찾아야 함 + ) + if exist_word: + # 단어를 찾았다고 하면 early return + return True + + # 백트래킹을 위해 현재 칸의 visited 값을 원복한다. + visited[i][j] = 0 + + # 단어를 찾지 못했을 땐 False 반환 + return False + + for i in range(num_rows): + for j in range(num_cols): + if board[i][j] != word[0]: + # 출발 글자가 word의 첫 글자랑 같지 않으면 탐색할 필요가 없으므로 넘긴다. + continue + + exist_word = check_exist_word(i, j, 0) + if exist_word: + # 단어를 찾았으면 탐색을 더이상 하지 않아도 되므로 early return + return True + + # 보드의 모든 탐색을 해도 찾지 못한 경우에는 False 반환 + return False From ede4dae3d4bce3fc3180c7d1be223bf90c1d3f4f Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年3月26日 23:29:19 +0900 Subject: [PATCH 139/526] [7th batch] week 4 - merge two sorted lists --- merge-two-sorted-lists/liza0525.py | 37 ++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/merge-two-sorted-lists/liza0525.py b/merge-two-sorted-lists/liza0525.py index e47564eca5..d8d906f659 100644 --- a/merge-two-sorted-lists/liza0525.py +++ b/merge-two-sorted-lists/liza0525.py @@ -41,3 +41,40 @@ def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> # dummy 노드 다음부터가 실제 머지된 리스트의 시작점 return root_node.next + + +# 7기 풀이 +# 시간 복잡도: O(n + m) +# - list1의 길이 n, list2의 길이 m의 개수를 번갈아가며 탐색할 때 최악 +# 공간 복잡도: O(1) +# - dummy 노드와 curr 만 사용하므로 추가 공간 없음 +class Solution: + def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: + dummy = ListNode() # dummy node를 만들어 dummy.next부터 리스트들을 머지하도록 한다. + curr = dummy # curr 포인트를 dummy에 둔다 + + # list1과 list2 모두가 있을 때 루프를 돈다. + # 둘 중 하나라도 None이 되는 순간 루프 탈출 + while list1 and list2: + if list1.val < list2.val: + # list1의 숫자가 더 작을 땐 curr.next에 list1의 헤드를 넣고, + # 포인터를 next node로 옮김 + curr.next = list1 + list1 = list1.next + else: + # list2의 숫자가 더 작을 땐 curr.next에 list2의 헤드를 넣고, + # 포인터를 next node로 옮김 + curr.next = list2 + list2 = list2.next + + # 다음 노드 merge를 위해 curr도 포인터를 next로 변경 + curr = curr.next + + # 루프 탈출 후 남아 있는 리스트가 있다면 curr의 next에 남은 리스트를 머지한다. + if list1: + curr.next = list1 + elif list2: + curr.next = list2 + + # dummy 노드는 예비용, dummy.next를 리턴 + return dummy.next From a5769ca63027d24249cdcffe26e5f69d97484b0f Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年3月26日 23:32:44 +0900 Subject: [PATCH 140/526] =?UTF-8?q?feat:=20=EC=86=8D=EB=8F=84=EB=8A=94=20?= =?UTF-8?q?=EB=B9=A0=EB=A5=B4=EC=A7=80=EB=A7=8C=20=EB=B3=B5=EC=9E=A1?= =?UTF-8?q?=ED=95=9C=20=EB=A1=9C=EC=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- valid-parentheses/gyeo-ri.py | 47 ++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 valid-parentheses/gyeo-ri.py diff --git a/valid-parentheses/gyeo-ri.py b/valid-parentheses/gyeo-ri.py new file mode 100644 index 0000000000..848c3604e5 --- /dev/null +++ b/valid-parentheses/gyeo-ri.py @@ -0,0 +1,47 @@ +from collections import deque + + +class Solution: + def isValid(self, s: str) -> bool: + character_map = { + "(": ")", + "{": "}", + "[": "]", + } + s_stack = deque() + + for c in s: + if c in character_map.keys(): + s_stack.append(c) + + else: + if len(s_stack)> 0: + previous = s_stack.pop() + if character_map[previous] != c: + return False + else: + return False + + if len(s_stack)> 0: + return False + else: + return True + + +if __name__ == "__main__": + test_cases = [ + ("{{{[[[(([{{}}]))]]]}}}", True), + ("{{{]}}", False), + ("{", False), + ("}}]", False), + ("{}[]()", True), + ("{[]}[()]", True), + ] + + solution = Solution() + for idx, case_ in enumerate(test_cases): + s, answer = case_ + result = solution.isValid(s) + assert ( + answer == result + ), f"Test Case {idx} Failed: Expected {answer}, Got {result}" From 1da388c1e20a6ddbe45c3819ec53ec2db2191d7d Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年3月26日 23:51:18 +0900 Subject: [PATCH 141/526] [7th batch] week 4 - coin change --- coin-change/liza0525.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 coin-change/liza0525.py diff --git a/coin-change/liza0525.py b/coin-change/liza0525.py new file mode 100644 index 0000000000..677c9ed23c --- /dev/null +++ b/coin-change/liza0525.py @@ -0,0 +1,38 @@ +# 7기 풀이 +# 시간 복잡도: O(n * k) +# - 타겟 코인 값(amount, 복잡도 계산에선 n으로 표기)과 coins의 길이 만큼 탐색하며 계산 +# 공간 복잡도: O(n) +# - 타겟 코인 값(amount, 복잡도 계산에선 n으로 표기) 만큼의 min_coin_count 계산 array를 생성 +class Solution: + # 해당 문제는 현재 갖고 있는 돈으로 각 코인 값을 만드는 데에 동전을 얼마나 쓰는지 계산하여 + # 그 조합 중 가장 작은 값을 계속 찾아가는 문제로, min_coin_count를 사용한다. + def coinChange(self, coins: List[int], amount: int) -> int: + min_coin_count = [-1 for _ in range(amount + 1)] # 각 인덱스는 코인 값, value는 해당 코인 값을 만들 수 있는 동전의 개수(만들 수 없을 땐 -1) + min_coin_count[0] = 0 # 코인 값이 0일 때는 동전을 쓰지 않으면 되므로 무조건 0이 된다. + + for target_amount in range(1, len(min_coin_count)): + # 각 코인 값에 대해 최소 동전 개수를 찾는다. + for coin in coins: + if target_amount - coin < 0: + # 대상 코인 값보다 체크할 코인 값이 큰 경우에는 조합을 만들 수 없으므로 넘긴다 + continue + if min_coin_count[target_amount - coin] < 0: + # target_amount - coin(보수)을 만들 수 없으면 target_amount도 만들 수 없음 + # 예시) coin=3 → 보수 2를 못 만들면 5도 못 만듦 + continue + + # 위 두 가지 조건만 넘어가면 동전 개수를 min_coin_count[target_amount]에 정해서 넣을 수 있다는 의미 + if min_coin_count[target_amount] == -1: + # 값이 -1인 경우에는 처음으로 계산해서 넣는 것이기 때문에 + # min_coin_count[target_amount - coin]에다가 1을 더해서(coin 한 개를 추가 한다는 의미) min_coin_count[target_amount]에 할당 + min_coin_count[target_amount] = min_coin_count[target_amount - coin] + 1 + else: + # 값이 -1이 아닌 경우는 이전에 저장된 동전 개수가 있으므로 + # 이전 결과 값과 min_coin_count[target_amount - coin] + 1의 값을 비교하여 더 적은 수를 저장한다. + min_coin_count[target_amount] = min( + min_coin_count[target_amount], + min_coin_count[target_amount - coin] + 1 + ) + + # 모두 계산한 후 min_coin_count[amount]를 반환한다. (== amount를 만드는 동전의 최소 개수) + return min_coin_count[amount] From 2ffbb37ca1e63a0befbb63f5320e2ce545a69e66 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年3月27日 00:04:54 +0900 Subject: [PATCH 142/526] =?UTF-8?q?fix:=20=EB=A1=9C=EC=A7=81=EC=9D=80=20?= =?UTF-8?q?=EC=9C=A0=EC=A7=80=ED=95=9C=20=EC=B1=84=EB=A1=9C=20=EA=B0=80?= =?UTF-8?q?=EB=8F=85=EC=84=B1=20/=20=EB=A9=94=EB=AA=A8=EB=A6=AC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9D=84=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- valid-parentheses/gyeo-ri.py | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/valid-parentheses/gyeo-ri.py b/valid-parentheses/gyeo-ri.py index 848c3604e5..cfeec1d54d 100644 --- a/valid-parentheses/gyeo-ri.py +++ b/valid-parentheses/gyeo-ri.py @@ -1,31 +1,19 @@ -from collections import deque - - class Solution: def isValid(self, s: str) -> bool: - character_map = { - "(": ")", - "{": "}", - "[": "]", - } - s_stack = deque() + character_map = {"(": ")", "{": "}", "[": "]"} + s_list = [] for c in s: - if c in character_map.keys(): - s_stack.append(c) + if c in character_map: + s_list.append(character_map[c]) else: - if len(s_stack)> 0: - previous = s_stack.pop() - if character_map[previous] != c: - return False - else: - return False + if len(s_list)> 0: + if s_list.pop() == c: + continue + return False - if len(s_stack)> 0: - return False - else: - return True + return len(s_list) == 0 if __name__ == "__main__": From 55c4df444405cc6fbf6976814457e43a45414736 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年3月27日 00:09:01 +0900 Subject: [PATCH 143/526] =?UTF-8?q?fix:=20=EC=B5=9C=EC=A0=81=20=EC=95=8C?= =?UTF-8?q?=EA=B3=A0=EB=A6=AC=EC=A6=98=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=EA=B0=80=EB=8F=85=EC=84=B1=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- valid-parentheses/gyeo-ri.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/valid-parentheses/gyeo-ri.py b/valid-parentheses/gyeo-ri.py index cfeec1d54d..f6e2b96782 100644 --- a/valid-parentheses/gyeo-ri.py +++ b/valid-parentheses/gyeo-ri.py @@ -1,3 +1,12 @@ +""" +[결과 요약] +# 재시도횟수: 3회 + 1. 조건에는 맞지만 메모리를 많이 사용 / 빈번한 False 리턴을 사용한 방법:: O(n)/O(n) + 2. 1의 로직의 가독성과 메모리 사용량 개선하기: O(n)/O(n) + 3. 실제로는 if/else문으로 풀어도 최적의 성능이 나오면서 가독성 측면에서도 유리: : O(n)/O(n) +""" + + class Solution: def isValid(self, s: str) -> bool: character_map = {"(": ")", "{": "}", "[": "]"} @@ -16,6 +25,25 @@ def isValid(self, s: str) -> bool: return len(s_list) == 0 +""" +# 실제로는 복잡한 로직 없이 if/else로 직접 비교하는 쪽이 성능과 코드 가독성 면에서 모두 유리 +class Solution: + def isValid(self, s: str) -> bool: + s_list = [] + + for c in s: + if c == '(': + s_list.append(')') + elif c == '{': + s_list.append('}') + elif c == '[': + s_list.append(']') + else: + if not s_list or s_list.pop() != c: + return False +""" + + if __name__ == "__main__": test_cases = [ ("{{{[[[(([{{}}]))]]]}}}", True), From 3b1d10951971b841decab8a27a5ad25cb882d0a5 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年3月27日 11:53:00 +0900 Subject: [PATCH 144/526] =?UTF-8?q?4=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=202=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Merge Two Sorted Lists - Maximum Depth of Binary Tree --- maximum-depth-of-binary-tree/hwi-middle.cpp | 38 +++++++++++++++++++++ merge-two-sorted-lists/hwi-middle.cpp | 38 +++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 maximum-depth-of-binary-tree/hwi-middle.cpp create mode 100644 merge-two-sorted-lists/hwi-middle.cpp diff --git a/maximum-depth-of-binary-tree/hwi-middle.cpp b/maximum-depth-of-binary-tree/hwi-middle.cpp new file mode 100644 index 0000000000..c754d4b8c8 --- /dev/null +++ b/maximum-depth-of-binary-tree/hwi-middle.cpp @@ -0,0 +1,38 @@ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { + ListNode dummy; // head 초기화의 복잡성을 낮추기 위한 더미노드 + ListNode* tail = &dummy; + + while (list1 != nullptr && list2 != nullptr) + { + if (list1->val < list2->val) + { + tail->next = list1; + list1 = list1->next; + } + else + { + tail->next = list2; + list2 = list2->next; + } + + tail = tail->next; + } + + tail->next = (list1 == nullptr) ? list2 : list1; + + return dummy.next; + } +} +; diff --git a/merge-two-sorted-lists/hwi-middle.cpp b/merge-two-sorted-lists/hwi-middle.cpp new file mode 100644 index 0000000000..c754d4b8c8 --- /dev/null +++ b/merge-two-sorted-lists/hwi-middle.cpp @@ -0,0 +1,38 @@ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { + ListNode dummy; // head 초기화의 복잡성을 낮추기 위한 더미노드 + ListNode* tail = &dummy; + + while (list1 != nullptr && list2 != nullptr) + { + if (list1->val < list2->val) + { + tail->next = list1; + list1 = list1->next; + } + else + { + tail->next = list2; + list2 = list2->next; + } + + tail = tail->next; + } + + tail->next = (list1 == nullptr) ? list2 : list1; + + return dummy.next; + } +} +; From 05c577093de0dc23dc97b4e3f336ec81b6048573 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年3月27日 12:53:40 +0900 Subject: [PATCH 145/526] =?UTF-8?q?4=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=201=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Find Minimum in Rotated Sorted Array --- .../hwi-middle.cpp | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/hwi-middle.cpp diff --git a/find-minimum-in-rotated-sorted-array/hwi-middle.cpp b/find-minimum-in-rotated-sorted-array/hwi-middle.cpp new file mode 100644 index 0000000000..42bebd662e --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/hwi-middle.cpp @@ -0,0 +1,42 @@ +class Solution { +public: + int findMin(vector& nums) { + return solve(nums, 0, nums.size() - 1); + } + + int solve(vector& num, int start, int end) + { + if (end - start < 2) + { + return min(num[start], num[end]); + } + + // 중간 인덱스 계산 + int mid = (start + end) / 2; + + // 오름차순 정렬이 깨지기 시작한 부분 -> 최솟값 발견 + if (num[mid] < num[mid - 1]) + { + return num[mid]; + } + + // 왼쪽 영역이 정렬되어 있는 경우 + if (num[start] <= num[mid]) + { + // 그리고 오른쪽 영역까지도 정렬된 경우 + if (num[mid] <= num[end]) + { + // 가장 왼쪽에 있는 값이 최솟값 + return num[start]; + } + + // 왼쪽 영역만 정렬된 경우 + // 오른쪽 영역에서 정렬이 깨지는 부분 찾으러 가기 + return solve(num, mid + 1, end); + } + + // 오른쪽 영역이 정렬된 경우 + // 왼쪽 영역에서 정렬이 깨지는 부분 찾으러 가기 + return solve(num, start, mid - 1); + } +}; From bf2a30b5c82e4ae12df0327189a900300eba5d22 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年3月27日 14:10:26 +0900 Subject: [PATCH 146/526] =?UTF-8?q?4=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=201=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Word Search --- word-search/hwi-middle.cpp | 65 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 word-search/hwi-middle.cpp diff --git a/word-search/hwi-middle.cpp b/word-search/hwi-middle.cpp new file mode 100644 index 0000000000..3d484a3e46 --- /dev/null +++ b/word-search/hwi-middle.cpp @@ -0,0 +1,65 @@ +class Solution { +private: + int row; + int col; + +public: + bool exist(vector>& board, string word) { + row = board.size(); + col = board[0].size(); + for (int r = 0; r < row; ++r) + { + for (int c = 0; c < col; ++c) + { + if (solve(board, word, r, c, 0)) + { + return true; + } + } + } + + return false; + } + + // dfs 함수 + bool solve(vector>& board, string& word, int r, int c, int idx) + { + // 범위를 벗어난 경우 + if (r < 0 || r>= row || c < 0 || c>= col) + { + return false; + } + + // 글자가 맞지 않는 경우 + if (board[r][c] != word[idx]) + { + return false; + } + + // 단어를 찾은 경우 + if (idx == word.size() - 1) + { + return true; + } + + char ch = board[r][c]; + board[r][c] = '?'; // 이미 방문한 곳으로 돌아오지 않도록 입력으로 들어오지 않는 문자로 치환 + + // 상하좌우 탐색 + int dr[4] = { 1, 0, -1, 0 }; + int dc[4] = { 0, 1, 0, -1 }; + + for (int dir = 0; dir < 4; ++dir) + { + int nr = r + dr[dir]; + int nc = c + dc[dir]; + if (solve(board, word, nr, nc, idx + 1)) + { + return true; + } + } + + board[r][c] = ch; // 원래 문자로 되돌리기 + return false; + } +}; From 54df655a8a44f5dc6e9446740e5d8601ff4ef05d Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: 2026年3月27日 14:17:11 +0900 Subject: [PATCH 147/526] coin change solution --- coin-change/robinyoon-dev.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 coin-change/robinyoon-dev.js diff --git a/coin-change/robinyoon-dev.js b/coin-change/robinyoon-dev.js new file mode 100644 index 0000000000..bc6a8202f9 --- /dev/null +++ b/coin-change/robinyoon-dev.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} coins + * @param {number} amount + * @return {number} + */ +var coinChange = function (coins, amount) { + + let dp = new Array(amount + 1).fill(Infinity); + dp[0] = 0; + + for (let i = 1; i < dp.length; i++) { + for (let coin of coins) { + + if (coin> i) { + continue; + } + + let remain = i - coin; + dp[i] = Math.min(dp[i], dp[remain] + 1); + + } + }; + + let result = dp[amount] === Infinity ? -1 : dp[amount]; + return result; +} From a60bfb0526386d996f316dfb7595c1d1b1b29c42 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年3月27日 14:41:34 +0900 Subject: [PATCH 148/526] =?UTF-8?q?4=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=201=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Coin Change --- coin-change/hwi-middle.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 coin-change/hwi-middle.cpp diff --git a/coin-change/hwi-middle.cpp b/coin-change/hwi-middle.cpp new file mode 100644 index 0000000000..9a73b11910 --- /dev/null +++ b/coin-change/hwi-middle.cpp @@ -0,0 +1,32 @@ +class Solution { +public: + int coinChange(vector& coins, int amount) { + if (amount < 1) + { + return 0; + } + + vector v(amount); + return solve(coins, amount, v); + } + + int solve(vector& coins, int amount, vector& count) + { + if (amount < 0) return -1; + if (amount == 0) return 0; + if (count[amount - 1] != 0) return count[amount - 1]; + + int min = INT_MAX; + for (int coin : coins) + { + int res = solve(coins, amount - coin, count); // coin을 사용 + if (res>= 0 && res < min) // 결과가 유효하고 현재 최솟값보다 작으면 업데이트 + { + min = res + 1; // coin을 미리 사용하고 찾은 값이므로 1 더함 + } + } + + count[amount - 1] = (min == INT_MAX) ? -1 : min; + return count[amount - 1]; + } +}; From abea89556203bc4bc48b3752c350ba68a58b72b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=EC=98=81?= Date: 2026年3月27日 15:56:32 +0900 Subject: [PATCH 149/526] =?UTF-8?q?word-search=20=ED=92=80=EC=9D=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- word-search/junzero741.ts | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 word-search/junzero741.ts diff --git a/word-search/junzero741.ts b/word-search/junzero741.ts new file mode 100644 index 0000000000..a6ef4caa0e --- /dev/null +++ b/word-search/junzero741.ts @@ -0,0 +1,41 @@ +// TC: O(M*N*4^L) +// SC: O(L) +function exist(board: string[][], word: string): boolean { + const rows = board.length; + const cols = board[0].length; + + function dfs(r: number, c: number, index: number): boolean { + if (index === word.length) return true; + + if ( + r < 0 || r>= rows || + c < 0 || c>= cols || + board[r][c] !== word[index] + ) { + return false; + } + + const temp = board[r][c]; + board[r][c] = '#'; + + const found = + dfs(r + 1, c, index + 1) || + dfs(r - 1, c, index + 1) || + dfs(r, c + 1, index + 1) || + dfs(r, c - 1, index + 1); + + board[r][c] = temp; + + return found; + } + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (board[i][j] === word[0] && dfs(i, j, 0)) { + return true; + } + } + } + + return false; +} From c65e89fa738a93907cd76c2e972a7c4a9d9b6c8f Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年3月27日 16:38:29 +0900 Subject: [PATCH 150/526] add: wordSearch solution --- word-search/Cyjin-jani.js | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 word-search/Cyjin-jani.js diff --git a/word-search/Cyjin-jani.js b/word-search/Cyjin-jani.js new file mode 100644 index 0000000000..cfb60b4683 --- /dev/null +++ b/word-search/Cyjin-jani.js @@ -0,0 +1,41 @@ +//! dfs 구현 중에 막혀서 ai의 도움을 받아 풀이를 완성했습니다.. +var exist = function (board, word) { + const dx = [0, 0, -1, 1]; + const dy = [-1, 1, 0, 0]; + + for (let i = 0; i < board.length; i++) { + for (let j = 0; j < board[i].length; j++) { + if (board[i][j] === word[0]) { + if (dfs(j, i, 0)) return true; + } + } + } + + function dfs(x, y, index) { + // 성공 + if (index === word.length) return true; + + // 실패 + if (x < 0 || y < 0 || y>= board.length || x>= board[y].length) return false; + if (board[y][x] === '#') return false; + if (board[y][x] !== word[index]) return false; + + // 방문 표시 + const origin = board[y][x]; + board[y][x] = '#'; + + // 탐색 + for (let i = 0; i < 4; i++) { + const newDy = y + dy[i]; + const newDx = x + dx[i]; + + if (dfs(newDx, newDy, index + 1)) return true; + } + // 복원 + board[y][x] = origin; + + return false; + } + + return false; +}; From 394f06c371608f38181e185bb231ae288b83cfb3 Mon Sep 17 00:00:00 2001 From: Dia Date: 2026年3月27日 20:40:59 +0900 Subject: [PATCH 151/526] feat: add prev week solutions --- decode-ways/kangdaia.py | 28 +++++++++++++++++++ maximum-subarray/kangdaia.py | 52 ++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 decode-ways/kangdaia.py create mode 100644 maximum-subarray/kangdaia.py diff --git a/decode-ways/kangdaia.py b/decode-ways/kangdaia.py new file mode 100644 index 0000000000..a94f54d653 --- /dev/null +++ b/decode-ways/kangdaia.py @@ -0,0 +1,28 @@ +class Solution: + def numDecodings(self, s: str) -> int: + """1에서 26까지 숫자를 알파벳으로 치환할 수 있을때, + 주어진 숫자 문자열이 어떤 알파벳으로 치환 될 수 있는지 방법의 수를 찾는 함수 + + 방법: + 1. 경우의 수를 찾는 경우는 대부분 DP..? + - 케이스가 명확함. + 현 위치의 숫자가 0이 아닌 경우, 해당 자리가 앞 숫자와 별개로 1~9 사이의 숫자를 선택할 수 있다. + 만약 앞의 경우를 포함해서 숫자가 10에서 26사이면 앞의 경우를 포함해서 경우의 숫자를 생각해야 함. + 다만 첫번째 숫자가 0이면 넘어가야 함. + 시간 복잡도: O(n) 공간 복잡도: O(n) + + Args: + s (str): 숫자로 이루어진 문자열 + + Returns: + int: 문자열로 치환할 수 있는 알파벳 구성의 수 + """ + dp = [0] * len(s) + if s[0] != "0": + dp[0] = 1 + for i in range(1, len(s)): + if s[i] != "0": + dp[i] += dp[i - 1] + if "10" <= s[i - 1 : i + 1] <= "26": + dp[i] += dp[i - 2] if i> 1 else 1 + return dp[-1] diff --git a/maximum-subarray/kangdaia.py b/maximum-subarray/kangdaia.py new file mode 100644 index 0000000000..704cab9eb8 --- /dev/null +++ b/maximum-subarray/kangdaia.py @@ -0,0 +1,52 @@ +class Solution: + def maxSubArray(self, nums: list[int]) -> int: + """리스트의 이어진 문자열로 구성된 subarray중 최대 합을 찾는 함수 + + 방법: + 1. brute force. 다만 O(n)으로 만들 수 없어 탈락! + 2. 전역 최대합과 로컬 최대 합을 분리해서 생각하기. + 연속된 문자열이기 때문에, 현재 값이 이전의 합보다 크면 앞의 값을 버리는 방식 + => 시간 복잡도 O(n), 공간 복잡도 O(1) + 3. divide and conquer (Follow up) + + Args: + nums (list[int]): 정수 문자열 + + Returns: + int: 최대 합 + """ + max_sum = nums[0] + local_sum = nums[0] + for i in range(1, len(nums)): + if local_sum < 0 and local_sum < nums[i]: + local_sum = nums[i] + else: + local_sum += nums[i] + max_sum = max(max_sum, local_sum) + return max_sum + + def maxSubArraySubtle(self, nums: list[int]) -> int: + def divConq(left: int, right: int) -> int: + if left == right: + return nums[left] + mid = (left + right) // 2 + + left_max = divConq(left, mid) + right_max = divConq(mid + 1, right) + + curr_sum = 0 + left_suffix_max = -float("inf") + for idx in range(mid, left - 1, -1): + curr_sum += nums[idx] + left_suffix_max = max(left_suffix_max, curr_sum) + + curr_sum = 0 + right_prefix_max = -float("inf") + for idx in range(mid + 1, right + 1, 1): + curr_sum += nums[idx] + right_prefix_max = max(right_prefix_max, curr_sum) + + cross = left_suffix_max + right_prefix_max + return max(left_max, right_max, cross) + + return divConq(0, len(nums) - 1) From aa5706ca13fbf92d32a67a481cf25221706ebc9e Mon Sep 17 00:00:00 2001 From: Dia Date: 2026年3月27日 20:41:12 +0900 Subject: [PATCH 152/526] feat: add current week problems --- .../kangdaia.py | 27 +++++++++++++ maximum-depth-of-binary-tree/kangdaia.py | 26 +++++++++++++ merge-two-sorted-lists/kangdaia.py | 37 ++++++++++++++++++ word-search/kangdaia.py | 39 +++++++++++++++++++ 4 files changed, 129 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/kangdaia.py create mode 100644 maximum-depth-of-binary-tree/kangdaia.py create mode 100644 merge-two-sorted-lists/kangdaia.py create mode 100644 word-search/kangdaia.py diff --git a/find-minimum-in-rotated-sorted-array/kangdaia.py b/find-minimum-in-rotated-sorted-array/kangdaia.py new file mode 100644 index 0000000000..fcd0d1ff9a --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/kangdaia.py @@ -0,0 +1,27 @@ +class Solution: + def findMin(self, nums: list[int]) -> int: + """ + 정렬된 리스트에서 n번 돌아간 상태에서 기존의 첫번째 값 (가장 작은)을 찾는 함수 + + 방법: + Hint2의 Can you think of an algorithm which has O(logN) search complexity? + 에서 binary search! + + Args: + nums (list[int]): n번 돌아간 정수 리스트 + + Returns: + int: 최초 정렬된 리스트의 첫번째 값 + """ + if nums[0] <= nums[-1]: + return nums[0] + start, end = 0, len(nums) - 1 + while start < end: + if start == end: + break + mid = start + (end - start) // 2 + if nums[mid]> nums[end]: + start = mid + 1 + else: + end = mid + return nums[start] diff --git a/maximum-depth-of-binary-tree/kangdaia.py b/maximum-depth-of-binary-tree/kangdaia.py new file mode 100644 index 0000000000..98b7b44b16 --- /dev/null +++ b/maximum-depth-of-binary-tree/kangdaia.py @@ -0,0 +1,26 @@ +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution: + def maxDepth(self, root: TreeNode | None) -> int: + """주어진 binary tree의 최대 깊이를 찾는 함수 + + 방법: + 1. 재귀함수를 생각함. 인자로 현재 head node와 현재의 depth를 받는 재귀함수를 만들어 재귀 반복 + 2. 이 함수 자체가 재귀가 될 수 있다고 판단, 별도의 재귀함수를 삭제함. + depth를 넘겨주지 않아도, 앞에 +1을 함으로써 depth가 계산됨. + + Args: + root (TreeNode | None): binary tree + + Returns: + int: 최대 깊이 + """ + if root is None: + return 0 + return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right)) diff --git a/merge-two-sorted-lists/kangdaia.py b/merge-two-sorted-lists/kangdaia.py new file mode 100644 index 0000000000..65edd1ba9b --- /dev/null +++ b/merge-two-sorted-lists/kangdaia.py @@ -0,0 +1,37 @@ +# Definition for singly-linked list. +class ListNode: + def __init__(self, val=0, next=None): + self.val = val + self.next = next + + +class Solution: + def mergeTwoLists(self, list1: ListNode | None, list2: ListNode | None) -> ListNode | None: + """두개의 링크드 리스트를 합쳐서 하나의 sorted 링크드 리스트를 만드는 함수 + + 방법: + 1. 각각의 리스트 head에서 값을 비교하면서, + 1번보다 2번의 값이 작으면 1번의 head를 움직이고, + 반대의 경우 2번의 head를 움직이도록 함. + 움직이면서 합치는 리스트에 tail.next로 붙여줌 + + Args: + list1 (ListNode | None): 정렬된 양수 링크드 리스트 + list2 (ListNode | None): 정렬된 양수 링크드 리스트 2 + + Returns: + ListNode | None: 하나로 합쳐진 정렬된 링크드 리스트 + """ + final = ListNode() + tail = final + curr1, curr2 = list1, list2 + while curr1 and curr2: + if curr1.val < curr2.val: + tail.next = curr1 + curr1 = curr1.next + else: + tail.next = curr2 + curr2 = curr2.next + tail = tail.next + tail.next = curr1 if curr1 else curr2 + return final.next diff --git a/word-search/kangdaia.py b/word-search/kangdaia.py new file mode 100644 index 0000000000..18c99e3f89 --- /dev/null +++ b/word-search/kangdaia.py @@ -0,0 +1,39 @@ +class Solution: + def exist(self, board: list[list[str]], word: str) -> bool: + """m*n 사이즈 보드가 주어졌을 때, word를 만들 수 있는지 true/false로 return 하는 함수 + + 1. bfs로 queue에 모든 element를 추가하고, 매번 path를 파악해서 word인지 판단하도록 함 + -> 시간 효율이 안나옴 + 2. dfs 방식 적용. 현재 탐색 중일때, 보드를 #으로 치환해서, 이미 방문한 곳임을 체크 + - 시작점이 word[0]와 같을 때만 시작 + - dfs는 전체 path를 기록하지 않고, word가 볼 index를 인자로 받도록 함. + + Args: + board (list[list[str]]): 글자를 element로 가진 2d array + word (str): 찾아야 할 글자 목록 + + Returns: + bool: word가 board에 있는지 여부 + """ + m, n = len(board[0]), len(board) + + def dfs(row, col, idx): + if board[row][col] != word[idx]: + return False + if idx == len(word) - 1: + return True + visited = board[row][col] + board[row][col] = "#" + for r, c in [(row - 1, col), (row + 1, col), (row, col - 1), (row, col + 1)]: + if 0 <= r < n and 0 <= c < m: + if dfs(r, c, idx + 1): + board[row][col] = visited + return True + board[row][col] = visited + return False + + for ir in range(n): + for ic in range(m): + if board[ir][ic] == word[0] and dfs(ir, ic, 0): + return True + return False From 518ed711084f3276a84a8ed74f27aa33674b1565 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年3月27日 21:11:08 +0900 Subject: [PATCH 153/526] solved find-mi-in-rotated-sorted-array. --- .../sangbeenmoon.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/sangbeenmoon.py diff --git a/find-minimum-in-rotated-sorted-array/sangbeenmoon.py b/find-minimum-in-rotated-sorted-array/sangbeenmoon.py new file mode 100644 index 0000000000..f2a00960ab --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/sangbeenmoon.py @@ -0,0 +1,22 @@ +# TC : O(logN) +# SC : 1 + +class Solution: + def findMin(self, nums: List[int]) -> int: + + left = 0 + right = len(nums) - 1 + mid = (left + right) // 2 + + if len(nums) == 2: + return min(nums) + + while left < right: + mid = (left + right) // 2 + + if nums[mid]>= nums[right]: + left = mid + 1 + else: + right = mid + + return min(nums[left], nums[right], nums[mid]) From 00bdcdba6d12cf12f514d0ad400d38d45d9fb249 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年3月27日 21:41:22 +0900 Subject: [PATCH 154/526] solved word-search. --- word-search/sangbeenmoon.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 word-search/sangbeenmoon.py diff --git a/word-search/sangbeenmoon.py b/word-search/sangbeenmoon.py new file mode 100644 index 0000000000..c75805843b --- /dev/null +++ b/word-search/sangbeenmoon.py @@ -0,0 +1,36 @@ +# TC : O(m * n * 4^L) +# SC : O(m * n + L) + +class Solution: + answer = False + dx = [0,0,-1,1] + dy = [-1,1,0,0] + + def exist(self, board: List[List[str]], word: str) -> bool: + + for yy in range(len(board)): + for xx in range(len(board[0])): + if board[yy][xx] == word[0]: + self.visited = [ [False] * len(board[0]) for _ in range(len(board))] + self.visited[yy][xx] = True + self.dfs(board, word, xx, yy, 0) + + + return self.answer + + def dfs(self, board, word, cx, cy, idx): + print(cx, cy, idx) + if idx == len(word) - 1: + self.answer = True + + for i in range(4): + nx = cx + self.dx[i] + ny = cy + self.dy[i] + + if 0 <= nx and nx < len(board[0]): + if 0 <= ny and ny < len(board): + if self.visited[ny][nx] == False: + if idx + 1 <= len(word) - 1 and word[idx+1] == board[ny][nx]: + self.visited[ny][nx] = True + self.dfs(board, word, nx, ny, idx + 1) + self.visited[ny][nx] = False From 267b872952914e74593d63e96e40065bfc688a09 Mon Sep 17 00:00:00 2001 From: Dia Date: 2026年3月28日 00:13:35 +0900 Subject: [PATCH 155/526] feat: add coin change --- coin-change/kangdaia.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 coin-change/kangdaia.py diff --git a/coin-change/kangdaia.py b/coin-change/kangdaia.py new file mode 100644 index 0000000000..15590785ff --- /dev/null +++ b/coin-change/kangdaia.py @@ -0,0 +1,28 @@ +class Solution: + def coinChange(self, coins: list[int], amount: int) -> int: + """amount를 만들기 위해 최소한의 코인으로 구성할 수 있는 방안의 수를 구하는 함수 + 동일한 동전을 여러번 사용해도 됨 + + 방법: + - 방법 수를 보고 dp로 풀기로 함. 금액이 dp 단계가 됨. + 모든 금액별로, 코인 목록을 돌면서, 코인을 사용할 수 있으면 amount-coin한 금액의 방법수 + 1과 비교하기 + -> 조합이 불가능한 상태를 어떻게 판단하지? 에서 dp init을 0이 아니라 inf로 해야, 구분이 가능하다는 점. + -> 그래서 min 비교를 현재 인덱스 dp값과 i-coin의 dp 값 + 1으로 함 + coin이 정렬되지 않은 리스트라, 정렬해, coin 값이 amount를 넘어가면 pass + + Args: + coins (list[int]): 사용할 수 있는 동전 목록 + amount (int): 목표하는 금액 + + Returns: + int: 금액을 만들기 위해 구성할 수 있는 동전들 방안 수 + """ + dp = [float("inf")] * (amount + 1) + dp[0] = 0 + coins.sort() + for coin in coins: + if coin> amount: + continue + for i in range(coin, amount + 1): + dp[i] = min(dp[i], 1 + dp[i - coin]) + return dp[amount] if dp[amount] != float("inf") else -1 From 9fac6a2738b1d5d1f65619bd23227ace0efb1f10 Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年3月28日 00:25:56 +0900 Subject: [PATCH 156/526] week4: merge-two-sorted-lists --- merge-two-sorted-lists/reeseo3o.js | 42 ++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 merge-two-sorted-lists/reeseo3o.js diff --git a/merge-two-sorted-lists/reeseo3o.js b/merge-two-sorted-lists/reeseo3o.js new file mode 100644 index 0000000000..7b613d7802 --- /dev/null +++ b/merge-two-sorted-lists/reeseo3o.js @@ -0,0 +1,42 @@ +/** + * 1. Recursive approach + * Time complexity: O(n + m) + * Space complexity: O(n + m) + */ +// const mergeTwoLists = (list1, list2) => { +// if (!list1) return list2; +// if (!list2) return list1; +// +// if (list1.val <= list2.val) { +// list1.next = mergeTwoLists(list1.next, list2); +// return list1; +// } else { +// list2.next = mergeTwoLists(list1, list2.next); +// return list2; +// } +// }; + +/** + * 2. Iterative approach + Dummy Node + * Time complexity: O(n + m) + * Space complexity: O(1) + */ +const mergeTwoLists = (list1, list2) => { + const dummy = new ListNode(-1); + let current = dummy; + + while (list1 !== null && list2 !== null) { + if (list1.val <= list2.val) { + current.next = list1; + list1 = list1.next; + } else { + current.next = list2; + list2 = list2.next; + } + current = current.next; + } + + current.next = list1 ?? list2; + + return dummy.next; +}; From 4d795f09597205277e620ba4457cb1bcdabe162f Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年3月28日 00:33:00 +0900 Subject: [PATCH 157/526] =?UTF-8?q?=EC=9E=98=EB=AA=BB=20=EC=98=AC=EB=A6=B0?= =?UTF-8?q?=20=ED=92=80=EC=9D=B4=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- maximum-depth-of-binary-tree/hwi-middle.cpp | 44 +++++++++------------ 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/maximum-depth-of-binary-tree/hwi-middle.cpp b/maximum-depth-of-binary-tree/hwi-middle.cpp index c754d4b8c8..c4ee326958 100644 --- a/maximum-depth-of-binary-tree/hwi-middle.cpp +++ b/maximum-depth-of-binary-tree/hwi-middle.cpp @@ -1,38 +1,30 @@ /** - * Definition for singly-linked list. - * struct ListNode { + * Definition for a binary tree node. + * struct TreeNode { * int val; - * ListNode *next; - * ListNode() : val(0), next(nullptr) {} - * ListNode(int x) : val(x), next(nullptr) {} - * ListNode(int x, ListNode *next) : val(x), next(next) {} + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} * }; */ class Solution { public: - ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { - ListNode dummy; // head 초기화의 복잡성을 낮추기 위한 더미노드 - ListNode* tail = &dummy; + int maxDepth(TreeNode* root) { + return solve(root, 0); + } - while (list1 != nullptr && list2 != nullptr) + int solve(TreeNode* root, int depth) + { + if (root == nullptr) { - if (list1->val < list2->val) - { - tail->next = list1; - list1 = list1->next; - } - else - { - tail->next = list2; - list2 = list2->next; - } - - tail = tail->next; + return depth; } - tail->next = (list1 == nullptr) ? list2 : list1; + int l = solve(root->left, depth); + int r = solve(root->right, depth); - return dummy.next; + return max(l, r) + 1; } -} -; +}; From 2267c00a766b4750835fd506a52cf55fc767b78e Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年3月27日 17:55:48 -0700 Subject: [PATCH 158/526] find minimum in rotated sorted array solution --- .../jylee2033.py | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/jylee2033.py diff --git a/find-minimum-in-rotated-sorted-array/jylee2033.py b/find-minimum-in-rotated-sorted-array/jylee2033.py new file mode 100644 index 0000000000..3e5821afbe --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/jylee2033.py @@ -0,0 +1,21 @@ +class Solution: + def findMin(self, nums: List[int]) -> int: + # Binary Search: compare mid with right + # nums[mid]> nums[right] -> min is in right half + # nums[mid] < nums[right] -> min is in left half (including mid) + + left = 0 + right = len(nums) - 1 + + while left < right: + mid = (left + right) // 2 + + if nums[mid]> nums[right]: + left = mid + 1 + elif nums[mid] < nums[right]: + right = mid + + return nums[left] + +# Time Complexity: O(log n) +# Space Complexity: O(1) From 8cb51ccf21f6a1b99869751b1f8cd98e3a4033a6 Mon Sep 17 00:00:00 2001 From: YOOHYOJEONG Date: 2026年3月28日 11:00:47 +0900 Subject: [PATCH 159/526] week04_1_2_solution --- maximum-depth-of-binary-tree/YOOHYOJEONG.py | 18 +++++++++++ merge-two-sorted-lists/YOOHYOJEONG.py | 36 +++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 maximum-depth-of-binary-tree/YOOHYOJEONG.py create mode 100644 merge-two-sorted-lists/YOOHYOJEONG.py diff --git a/maximum-depth-of-binary-tree/YOOHYOJEONG.py b/maximum-depth-of-binary-tree/YOOHYOJEONG.py new file mode 100644 index 0000000000..72b50f3a55 --- /dev/null +++ b/maximum-depth-of-binary-tree/YOOHYOJEONG.py @@ -0,0 +1,18 @@ +# https://leetcode.com/problems/maximum-depth-of-binary-tree + +class Solution: + def maxDepth(self, root): + # base case: + # 현재 노드가 없으면 (빈 트리 또는 leaf의 자식) + # 깊이는 0 + if not root: + return 0 + + # 왼쪽 서브트리의 최대 깊이를 재귀적으로 계산 + left_depth = self.maxDepth(root.left) + + # 오른쪽 서브트리의 최대 깊이를 재귀적으로 계산 + right_depth = self.maxDepth(root.right) + + # 현재 노드를 포함해야 하므로 +1 + # 왼쪽과 오른쪽 중 더 깊은 쪽을 선택 \ No newline at end of file diff --git a/merge-two-sorted-lists/YOOHYOJEONG.py b/merge-two-sorted-lists/YOOHYOJEONG.py new file mode 100644 index 0000000000..58581c11ea --- /dev/null +++ b/merge-two-sorted-lists/YOOHYOJEONG.py @@ -0,0 +1,36 @@ +# https://leetcode.com/problems/merge-two-sorted-lists + +# gpt의 도움을 받아 해결했습니다 +class Solution: + def mergeTwoLists(self, list1, list2): + # base case 1: + # list1이 비어있으면, 남은 list2를 그대로 반환 + if not list1: + return list2 + + # base case 2: + # list2가 비어있으면, 남은 list1을 그대로 반환 + if not list2: + return list1 + + # 두 리스트의 현재 노드 값을 비교 + if list1.val < list2.val: + # list1의 값이 더 작으면 + # list1을 결과 리스트의 현재 노드로 선택 + + # list1의 다음 노드는 + # (list1.next와 list2를 다시 병합한 결과)로 연결 + list1.next = self.mergeTwoLists(list1.next, list2) + + # 현재 선택된 list1을 반환 + return list1 + else: + # list2의 값이 더 작거나 같으면 + # list2를 결과 리스트의 현재 노드로 선택 + + # list2의 다음 노드는 + # (list1과 list2.next를 다시 병합한 결과)로 연결 + list2.next = self.mergeTwoLists(list1, list2.next) + + # 현재 선택된 list2를 반환 + return list2 \ No newline at end of file From ec51c39cecbd61a78976dd727c61e02843acd775 Mon Sep 17 00:00:00 2001 From: YOOHYOJEONG Date: 2026年3月28日 11:02:05 +0900 Subject: [PATCH 160/526] week04_1_2_solution --- maximum-depth-of-binary-tree/YOOHYOJEONG.py | 2 +- merge-two-sorted-lists/YOOHYOJEONG.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/maximum-depth-of-binary-tree/YOOHYOJEONG.py b/maximum-depth-of-binary-tree/YOOHYOJEONG.py index 72b50f3a55..9d9219d1df 100644 --- a/maximum-depth-of-binary-tree/YOOHYOJEONG.py +++ b/maximum-depth-of-binary-tree/YOOHYOJEONG.py @@ -15,4 +15,4 @@ def maxDepth(self, root): right_depth = self.maxDepth(root.right) # 현재 노드를 포함해야 하므로 +1 - # 왼쪽과 오른쪽 중 더 깊은 쪽을 선택 \ No newline at end of file + # 왼쪽과 오른쪽 중 더 깊은 쪽을 선택 diff --git a/merge-two-sorted-lists/YOOHYOJEONG.py b/merge-two-sorted-lists/YOOHYOJEONG.py index 58581c11ea..c12161d1cb 100644 --- a/merge-two-sorted-lists/YOOHYOJEONG.py +++ b/merge-two-sorted-lists/YOOHYOJEONG.py @@ -33,4 +33,4 @@ def mergeTwoLists(self, list1, list2): list2.next = self.mergeTwoLists(list1, list2.next) # 현재 선택된 list2를 반환 - return list2 \ No newline at end of file + return list2 From b10f3d9f9603f83c5a11d6e892414784a2bd038f Mon Sep 17 00:00:00 2001 From: yihyun-kim1 Date: 2026年3月28日 13:42:00 +0900 Subject: [PATCH 161/526] add solution: coin-change --- coin-change/yihyun-kim1.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 coin-change/yihyun-kim1.js diff --git a/coin-change/yihyun-kim1.js b/coin-change/yihyun-kim1.js new file mode 100644 index 0000000000..fefc6b7d07 --- /dev/null +++ b/coin-change/yihyun-kim1.js @@ -0,0 +1,21 @@ +/** + * @param {number[]} coins + * @param {number} amount + * @return {number} + */ + +// dp +const coinChange = (coins, amount) => { + const dp = new Array(amount + 1).fill(Infinity); + dp[0] = 0; + + for (let i = 1; i <= amount; i++) { + for (const coin of coins) { + if (i - coin>= 0) { + dp[i] = Math.min(dp[i], dp[i - coin] + 1); + } + } + } + + return dp[amount] === Infinity ? -1 : dp[amount]; +}; From 67962c77dd8399318540b9ebc49515b8d141eb55 Mon Sep 17 00:00:00 2001 From: yihyun-kim1 Date: 2026年3月28日 13:42:19 +0900 Subject: [PATCH 162/526] add solution: find-minimum-in-rotated-sorted-array --- .../yihyun-kim1.js | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/yihyun-kim1.js diff --git a/find-minimum-in-rotated-sorted-array/yihyun-kim1.js b/find-minimum-in-rotated-sorted-array/yihyun-kim1.js new file mode 100644 index 0000000000..e2f28b72c2 --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/yihyun-kim1.js @@ -0,0 +1,20 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const findMin = (nums) => { + let left = 0; + let right = nums.length - 1; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + + if (nums[mid]> nums[right]) { + left = mid + 1; + } else { + right = mid; + } + } + + return nums[left]; +}; From c6260ae030ce1abaae7d1f1d71e36e16723b7a40 Mon Sep 17 00:00:00 2001 From: yihyun-kim1 Date: 2026年3月28日 13:42:31 +0900 Subject: [PATCH 163/526] add solution: merge-two-sorted-lists --- merge-two-sorted-lists/yihyun-kim1.js | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 merge-two-sorted-lists/yihyun-kim1.js diff --git a/merge-two-sorted-lists/yihyun-kim1.js b/merge-two-sorted-lists/yihyun-kim1.js new file mode 100644 index 0000000000..9d4a66d6a1 --- /dev/null +++ b/merge-two-sorted-lists/yihyun-kim1.js @@ -0,0 +1,31 @@ +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} list1 + * @param {ListNode} list2 + * @return {ListNode} + */ +const mergeTwoLists = (list1, list2) => { + const dummy = new ListNode(0); + let current = dummy; + + while (list1 !== null && list2 !== null) { + if (list1.val <= list2.val) { + current.next = list1; + list1 = list1.next; + } else { + current.next = list2; + list2 = list2.next; + } + current = current.next; + } + + current.next = list1 || list2; + + return dummy.next; +}; From 2dccaf5dd8331721407aae33474a21c89c616e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=A4=EC=99=95=ED=83=9D=5FT6102=28Wang-Taek=20Oh=29?= Date: 2026年3月28日 16:54:12 +0900 Subject: [PATCH 164/526] solve merge two sorted list --- merge-two-sorted-lists/ohkingtaek.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 merge-two-sorted-lists/ohkingtaek.py diff --git a/merge-two-sorted-lists/ohkingtaek.py b/merge-two-sorted-lists/ohkingtaek.py new file mode 100644 index 0000000000..817cafd54e --- /dev/null +++ b/merge-two-sorted-lists/ohkingtaek.py @@ -0,0 +1,26 @@ +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]: + """ + 시간복잡도: O(n) + 공간복잡도: O(1) + 1. 두 리스트를 합쳐서 새로운 리스트 반환 + 2. 두 리스트를 돌면서 작은 값을 새로운 리스트에 추가 + 3. 두 리스트를 모두 순회하면 남은 것을 새로운 리스트에 추가 + """ + root = ListNode(None) + node = root + while list1 and list2: + if list1.val < list2.val: + node.next = list1 + list1 = list1.next + else: + node.next = list2 + list2 = list2.next + node = node.next + node.next = list1 or list2 + return root.next From 4615d6bcf73da8780b3f6df7bb722a7d80852414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=A4=EC=99=95=ED=83=9D=5FT6102=28Wang-Taek=20Oh=29?= Date: 2026年3月28日 16:54:37 +0900 Subject: [PATCH 165/526] solve maximum depth of binary tree --- maximum-depth-of-binary-tree/ohkingtaek.py | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 maximum-depth-of-binary-tree/ohkingtaek.py diff --git a/maximum-depth-of-binary-tree/ohkingtaek.py b/maximum-depth-of-binary-tree/ohkingtaek.py new file mode 100644 index 0000000000..0d36c04cbd --- /dev/null +++ b/maximum-depth-of-binary-tree/ohkingtaek.py @@ -0,0 +1,25 @@ +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def maxDepth(self, root: Optional[TreeNode]) -> int: + """ + 시간복잡도: O(n) + 공간복잡도: O(n) + 이진 트리 탐색하며 뎁스 증가 계속 하며 진행 + """ + depth = 0 + if not root: + return 0 + array = [(root, 1)] + while array: + node, d = array.pop() + depth = max(d, depth) + if node.left: + array.append((node.left, d + 1)) + if node.right: + array.append((node.right, d + 1)) + return depth From 503daed6837d9b5af1428689b81f47ddd9b7bebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=A4=EC=99=95=ED=83=9D=5FT6102=28Wang-Taek=20Oh=29?= Date: 2026年3月28日 16:54:58 +0900 Subject: [PATCH 166/526] solve find minimum depth of binary tree --- find-minimum-in-rotated-sorted-array/ohkingtaek.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/ohkingtaek.py diff --git a/find-minimum-in-rotated-sorted-array/ohkingtaek.py b/find-minimum-in-rotated-sorted-array/ohkingtaek.py new file mode 100644 index 0000000000..3959159a59 --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/ohkingtaek.py @@ -0,0 +1,8 @@ +class Solution: + def findMin(self, nums: List[int]) -> int: + """ + 시간복잡도: O(n) + 공간복잡도: O(1) + 왜 이렇게 해도 solve가 되네요..ᄒᄒ + """ + return min(nums) From 6338bf06a388bdadbbc6e5dd8b3fb06ce3f2fd69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=A4=EC=99=95=ED=83=9D=5FT6102=28Wang-Taek=20Oh=29?= Date: 2026年3月28日 16:55:11 +0900 Subject: [PATCH 167/526] solve word search --- word-search/ohkingtaek.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 word-search/ohkingtaek.py diff --git a/word-search/ohkingtaek.py b/word-search/ohkingtaek.py new file mode 100644 index 0000000000..b86e311e9a --- /dev/null +++ b/word-search/ohkingtaek.py @@ -0,0 +1,32 @@ +class Solution: + def exist(self, board: List[List[str]], word: str) -> bool: + """ + 시간 복잡도: O(M * N * 4^L) + 공간 복잡도: O(M * N) + 1. 행렬을 순회하며 단어의 첫 번째 문자와 일치하는 위치를 찾기 + 2. 찾은 위치에서 상하좌우로 이동하며 단어의 다음 문자와 일치하는 위치를 찾기 + 3. 단어의 마지막 문자까지 찾으면 True를 반환, 못 찾으면 False + """ + m, n = len(board), len(board[0]) + + def dfs(i, j, k): + if i < 0 or i>= m or j < 0 or j>= n or board[i][j] != word[k]: + return False + if k == len(word) - 1: + return True + t = board[i][j] + board[i][j] = "#" + dx, dy = (1, -1, 0, 0), (0, 0, 1, -1) + ok = False + for d in range(4): + if dfs(i + dx[d], j + dy[d], k + 1): + ok = True + break + board[i][j] = t + return ok + + for i in range(m): + for j in range(n): + if dfs(i, j, 0): + return True + return False From 68408c98da1827dd472c7603d9e1b361f566b265 Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年3月28日 18:37:38 +0900 Subject: [PATCH 168/526] week4: maximum-subarray --- maximum-subarray/reeseo3o.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 maximum-subarray/reeseo3o.js diff --git a/maximum-subarray/reeseo3o.js b/maximum-subarray/reeseo3o.js new file mode 100644 index 0000000000..a01f3711c5 --- /dev/null +++ b/maximum-subarray/reeseo3o.js @@ -0,0 +1,34 @@ +/** + * Time complexity: O(n) + * Space complexity: O(h) - h is the height of the tree, worst case O(n) + */ +const maxDepth = (root) => { + if (root === null) return 0; + + const leftDepth = maxDepth(root.left); + const rightDepth = maxDepth(root.right); + + return 1 + Math.max(leftDepth, rightDepth); +}; + +// BFS - TC: O(n) | SC: O(n) +const maxDepthBFS = (root) => { + if (root === null) return 0; + + const queue = [root]; + let depth = 0; + + while (queue.length> 0) { + const levelSize = queue.length; + + for (let i = 0; i < levelSize; i++) { + const node = queue.shift(); + if (node.left) queue.push(node.left); + if (node.right) queue.push(node.right); + } + + depth++; + } + + return depth; +}; From fde6a4a74b5965d0bf91efe65a6cb6571dc5f1cd Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年3月28日 18:40:24 +0900 Subject: [PATCH 169/526] docs: add complexity comments for maximum-subarray --- maximum-subarray/reeseo3o.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/maximum-subarray/reeseo3o.js b/maximum-subarray/reeseo3o.js index a01f3711c5..1332a6f056 100644 --- a/maximum-subarray/reeseo3o.js +++ b/maximum-subarray/reeseo3o.js @@ -1,4 +1,5 @@ -/** +/** + * DFS * Time complexity: O(n) * Space complexity: O(h) - h is the height of the tree, worst case O(n) */ @@ -11,7 +12,11 @@ const maxDepth = (root) => { return 1 + Math.max(leftDepth, rightDepth); }; -// BFS - TC: O(n) | SC: O(n) +/** + * BFS + * Time complexity: O(n) + * Space complexity: O(n) + */ const maxDepthBFS = (root) => { if (root === null) return 0; From 3b8b30e1863f25a9b3ac207ef0ec6a582f5c2778 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年3月28日 19:40:46 +0900 Subject: [PATCH 170/526] solved max-depth-of-binary-tree. --- maximum-depth-of-binary-tree/sangbeenmoon.py | 27 ++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 maximum-depth-of-binary-tree/sangbeenmoon.py diff --git a/maximum-depth-of-binary-tree/sangbeenmoon.py b/maximum-depth-of-binary-tree/sangbeenmoon.py new file mode 100644 index 0000000000..1f2bde7ca9 --- /dev/null +++ b/maximum-depth-of-binary-tree/sangbeenmoon.py @@ -0,0 +1,27 @@ +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right + +# TC : O(n) +# SC : O(n) + +class Solution: + answer = 0 + + def go(self, cur: TreeNode, depth:int): + self.answer = max(self.answer, depth) + if cur.left != None: + self.go(cur.left, depth + 1) + if cur.right != None: + self.go(cur.right, depth + 1) + + def maxDepth(self, root: Optional[TreeNode]) -> int: + self.answer = 0 + + if root != None: + self.go(root, 1) + + return self.answer From 230c8a0da6186348883542bb5216994c37a1e112 Mon Sep 17 00:00:00 2001 From: robin Date: 2026年3月28日 19:48:40 +0900 Subject: [PATCH 171/526] 4 solutions --- .../nowrobin.js | 20 ++++++++++ maximum-depth-of-binary-tree/nowrobin.js | 20 ++++++++++ merge-two-sorted-lists/nowrobin.js | 29 +++++++++++++++ word-search/nowrobin.js | 37 +++++++++++++++++++ 4 files changed, 106 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/nowrobin.js create mode 100644 maximum-depth-of-binary-tree/nowrobin.js create mode 100644 merge-two-sorted-lists/nowrobin.js create mode 100644 word-search/nowrobin.js diff --git a/find-minimum-in-rotated-sorted-array/nowrobin.js b/find-minimum-in-rotated-sorted-array/nowrobin.js new file mode 100644 index 0000000000..37c5cfb9f1 --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/nowrobin.js @@ -0,0 +1,20 @@ +/** + * @param {number[]} nums + * @return {number} + */ +var findMin = function(nums) { + let left = 0; + let right = nums.length - 1; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + + if (nums[mid]> nums[right]) { + left = mid + 1; + } else { + right = mid; + } + } + + return nums[left]; +}; diff --git a/maximum-depth-of-binary-tree/nowrobin.js b/maximum-depth-of-binary-tree/nowrobin.js new file mode 100644 index 0000000000..9abaf17a8e --- /dev/null +++ b/maximum-depth-of-binary-tree/nowrobin.js @@ -0,0 +1,20 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +var maxDepth = function(root) { + if (root === null) return 0; + + const left = maxDepth(root.left); + const right = maxDepth(root.right); + + return Math.max(left, right) + 1; +}; diff --git a/merge-two-sorted-lists/nowrobin.js b/merge-two-sorted-lists/nowrobin.js new file mode 100644 index 0000000000..b588e2e7b4 --- /dev/null +++ b/merge-two-sorted-lists/nowrobin.js @@ -0,0 +1,29 @@ +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} list1 + * @param {ListNode} list2 + * @return {ListNode} + */ +var mergeTwoLists = function(list1, list2) { + let dummy = new ListNode(0); + let current = dummy; + while (list1 !== null && list2 !== null) { + if (list1.val < list2.val) { + current.next = list1; + list1 = list1.next; + } else { + current.next = list2; + list2 = list2.next; + } + current = current.next; + } + current.next = list1 !== null ? list1 : list2; + + return dummy.next; +}; diff --git a/word-search/nowrobin.js b/word-search/nowrobin.js new file mode 100644 index 0000000000..193cf49a3d --- /dev/null +++ b/word-search/nowrobin.js @@ -0,0 +1,37 @@ +/** + * @param {character[][]} board + * @param {string} word + * @return {boolean} + */ +var exist = function(board, word) { + const rows = board.length; + const cols = board[0].length; + + function dfs(r, c, index) { + if (r < 0 || c < 0 || r>= rows || c>= cols) return false; + if (board[r][c] !== word[index]) return false; + + if (index === word.length - 1) return true; + + const temp = board[r][c]; + board[r][c] = "#"; + + const found = + dfs(r + 1, c, index + 1) || + dfs(r - 1, c, index + 1) || + dfs(r, c + 1, index + 1) || + dfs(r, c - 1, index + 1); + + board[r][c] = temp; + + return found; + } + + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) { + if (dfs(r, c, 0)) return true; + } + } + + return false; +}; From 469b409857fae623477f5bdf6794e03ae2599bb4 Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: 2026年3月28日 20:40:07 +0900 Subject: [PATCH 172/526] sadie100: merge two sorted lists solution --- merge-two-sorted-lists/sadie100.ts | 51 ++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 merge-two-sorted-lists/sadie100.ts diff --git a/merge-two-sorted-lists/sadie100.ts b/merge-two-sorted-lists/sadie100.ts new file mode 100644 index 0000000000..700a1f6b5e --- /dev/null +++ b/merge-two-sorted-lists/sadie100.ts @@ -0,0 +1,51 @@ +/** + * Definition for singly-linked list. + * class ListNode { + * val: number + * next: ListNode | null + * constructor(val?: number, next?: ListNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + * } + */ + +/* +새 mergeList를 만들고 list1, list2를 순회하며 더 작은 값을 mergeList에 넣는다. +두 리스트의 next가 비게 되면 mergeList의 head를 리턴한다. + +시간복잡도 : O(N+K) (N은 list1의 길이, K는 list2의 길이) + +*/ + +function mergeTwoLists( + list1: ListNode | null, + list2: ListNode | null, +): ListNode | null { + let now = null + let head = null + + while (list1 || list2) { + if (!list2 || (list1 && list1.val <= list2.val)) { + if (!now) { + now = list1 + head = now + } else { + now.next = list1 + now = now.next + } + list1 = list1.next + } else { + if (!now) { + now = list2 + head = now + } else { + now.next = list2 + now = now.next + } + list2 = list2.next + } + } + + return head +} From c9eb708e42c5729af222afe2fa31a9ea5544aeac Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年3月28日 20:48:34 +0900 Subject: [PATCH 173/526] solved coin-change. --- coin-change/sangbeenmoon.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 coin-change/sangbeenmoon.py diff --git a/coin-change/sangbeenmoon.py b/coin-change/sangbeenmoon.py new file mode 100644 index 0000000000..ac0885863e --- /dev/null +++ b/coin-change/sangbeenmoon.py @@ -0,0 +1,32 @@ +# dp[i] = min(dp[i - c0], dp[i - c1], ... , dp[i - cn]) + 1 + +# TC : O(amount * len(coins)) +# SC : O(amount) + +class Solution: + dp = [] + def coinChange(self, coins: List[int], amount: int) -> int: + self.dp = [-2] * (amount + 10) # 아직 방문하지 않음 -> -2 + + return self.go(amount, coins) + + + def go(self, x: int, coins: List[int]) -> int: + if x == 0: + return 0 + + if self.dp[x] != -2: + return self.dp[x] + + mm = 100000 + + for coin in coins: + if x - coin>= 0: + sub = self.go(x - coin, coins) + if (sub == -1): # 불가능 -> -1 + continue + mm = min(mm, sub + 1) + + self.dp[x] = mm if mm != 100000 else -1 # memoization + + return self.dp[x] From bb9b1c392fef198ce7f3c1a28f965f67a8d9ba9e Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年3月28日 20:52:25 +0900 Subject: [PATCH 174/526] return nums[left] simply. --- find-minimum-in-rotated-sorted-array/sangbeenmoon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/find-minimum-in-rotated-sorted-array/sangbeenmoon.py b/find-minimum-in-rotated-sorted-array/sangbeenmoon.py index f2a00960ab..38fc422ed9 100644 --- a/find-minimum-in-rotated-sorted-array/sangbeenmoon.py +++ b/find-minimum-in-rotated-sorted-array/sangbeenmoon.py @@ -19,4 +19,4 @@ def findMin(self, nums: List[int]) -> int: else: right = mid - return min(nums[left], nums[right], nums[mid]) + return nums[left] From 1140238658dba76bdd5c0ca946d8b8e991ac5c93 Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: 2026年3月29日 00:14:36 +0900 Subject: [PATCH 175/526] sadie100: maximum depth of binary tree solution --- maximum-depth-of-binary-tree/sadie100.ts | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 maximum-depth-of-binary-tree/sadie100.ts diff --git a/maximum-depth-of-binary-tree/sadie100.ts b/maximum-depth-of-binary-tree/sadie100.ts new file mode 100644 index 0000000000..3b6219c5c5 --- /dev/null +++ b/maximum-depth-of-binary-tree/sadie100.ts @@ -0,0 +1,34 @@ +/** + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } + */ + +/* + DFS로 노드를 탐색해가며 최대깊이를 찾는다 + + 시간 복잡도 : O(N - binary tree의 깊이) + + */ + +function maxDepth(root: TreeNode | null): number { + let result = 0 + const search = (node, floor) => { + if (!node) return + result = Math.max(floor, result) + + search(node.left, floor + 1) + search(node.right, floor + 1) + } + + search(root, 1) + return result +} From 9ef6846590aa07c2ac7c25898827ec866fe73b42 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年3月29日 13:17:31 +0900 Subject: [PATCH 176/526] merge-two-sorted-lists solution --- merge-two-sorted-lists/hyeri0903.java | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 merge-two-sorted-lists/hyeri0903.java diff --git a/merge-two-sorted-lists/hyeri0903.java b/merge-two-sorted-lists/hyeri0903.java new file mode 100644 index 0000000000..22a57e2504 --- /dev/null +++ b/merge-two-sorted-lists/hyeri0903.java @@ -0,0 +1,40 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode mergeTwoLists(ListNode list1, ListNode list2) { + /** + time: O(n + m) + space: O(1) + */ + if(list1 == null) return list2; + if(list2 == null) return list1; + + ListNode res = new ListNode(); + ListNode tmp = res; + + while(list1 != null && list2 != null) { + if(list1.val> list2.val) { + tmp.next = list2; + list2 = list2.next; + } else { + tmp.next = list1; + list1 = list1.next; + } + tmp = tmp.next; + } + if(list1 == null) { + tmp.next = list2; + } else { + tmp.next = list1; + } + return res.next; + } +} From 166b93c73890b7038cb654f77eed9d52736d3adc Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年3月29日 13:18:03 +0900 Subject: [PATCH 177/526] maximum-depth-of-binary-tree solution --- maximum-depth-of-binary-tree/hyeri0903.java | 44 +++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 maximum-depth-of-binary-tree/hyeri0903.java diff --git a/maximum-depth-of-binary-tree/hyeri0903.java b/maximum-depth-of-binary-tree/hyeri0903.java new file mode 100644 index 0000000000..a2df24ca08 --- /dev/null +++ b/maximum-depth-of-binary-tree/hyeri0903.java @@ -0,0 +1,44 @@ +/** + * 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 int maxDepth(TreeNode root) { + /** + 문제: 바이너리트리의 maximum depth 구하기 + 조건 + - 노드의 개수는 0 ~ 10^4 + - node val 은 -100 ~ 100 + 풀이: dfs 로 depth 구하기 + - 주어진 트리는 binary tree + - time complexity : O(n) , O(log n) + - space complexity : O(h) + */ + + + if(root == null) return 0; + + int height = dfs(root); + return height; + } + + int dfs(TreeNode node) { + if(node == null) return 0; + + int left = dfs(node.left); + int right = dfs(node.right); + + return Math.max(left, right) + 1; + } +} From d84b261ae748a794d818d258a311241610d64775 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年3月29日 13:18:35 +0900 Subject: [PATCH 178/526] find-minimum-in-rotated-sorted-array solution --- .../hyeri0903.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/hyeri0903.java diff --git a/find-minimum-in-rotated-sorted-array/hyeri0903.java b/find-minimum-in-rotated-sorted-array/hyeri0903.java new file mode 100644 index 0000000000..dcb08bb91d --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/hyeri0903.java @@ -0,0 +1,47 @@ +class Solution { + public int findMin(int[] nums) { + /** + 1.problem: 오름차순 정렬된 original으로부터 최소횟수만큼 n번 rotate한다. 이 배열에서 최솟값 구하기 + 2.조건 + - 주어진 배열은 1 ~ n 번 rotated 되었다. + - 배열의 원소는 모두 unique 한 값 + - n = numslength + - O(log n)으로 풀이할것 + - n = 1 ~ 5000 + 3.풀이 + - bruteforce: nums 돌다가 작아지는 부분이 생기면 거기가 rotate 한 횟수, time : O(n), space: O(1) + - binary search: left, right 탐색 + + [1, 2, 3, 4, 5] + [5, 1, 2, 3, 4] -> 1 + [4, 5, 1, 2, 3] -> 2 + [3, 4, 5, 1, 2] -> 3 : index 3 구간에서 숫자 작아짐 + */ + int answer = nums[0]; + int n = nums.length; + if(n == 1) return answer; + + //sol 1) + // for(int i = 0; i < n-1; i++) { + // if(nums[i]> nums[i+1]) { + // return nums[i+1]; + // } + // } + //return answer; + + //sol 2) + int left = 0; + int right = n - 1; + while(left < right) { + int mid = (left + right) / 2; + if(nums[mid]> nums[right]) { + left = mid + 1; + } else { + right = mid; + } + } + + return nums[left]; + + } +} From 47f3660afe35e4340425e56059ba19cba629950d Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年3月29日 13:19:03 +0900 Subject: [PATCH 179/526] coin change solution --- coin-change/hyeri0903.java | 60 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 coin-change/hyeri0903.java diff --git a/coin-change/hyeri0903.java b/coin-change/hyeri0903.java new file mode 100644 index 0000000000..19cfba4a91 --- /dev/null +++ b/coin-change/hyeri0903.java @@ -0,0 +1,60 @@ +class Solution { + int minLen = Integer.MAX_VALUE; + public int coinChange(int[] coins, int amount) { + /** + 1.문제: amount 를 만족시킬 수 있는 가장 적은 수의 coins + 2.조건 + - 모두 다른 값 integer로 구성된 배열 + - amount 를 만들 수 없는 경우 -1 return + - coins.length 최소 1, 최대 12 + - 원소값 최소 = 1 + - amount 최소 = 0 + 3.풀이 + - amount 를 만족시키는 최소 조합 길이를 구한다. dfs? -> TLE + - dp + */ + + int n = coins.length; + //최대 코인개수 = amount + int[] dp = new int[amount + 1]; + Arrays.fill(dp, amount + 1); + dp[0] = 0; + + for(int i = 1; i <= amount; i++) { + for(int coin : coins) { + //코인 사용가능한 경우 + if(i - coin>= 0) { + dp[i] = Math.min(dp[i], dp[i-coin] + 1); + } + } + } + //amount 못만든 경우 + if(dp[amount]> amount) { + return -1; + } + return dp[amount]; + + // if(n != 0 && amount == 0) return 0; + // Arrays.sort(coins); + // dfs(n - 1, 0, coins, amount, 0); + // if(minLen == Integer.MAX_VALUE) { + // return -1; + // } + //return minLen; + } + + void dfs(int index, int total, int[] coins, int amount, int count) { + if(total> amount) return; + + if(total == amount) { + minLen = Math.min(minLen, count); + return; + } + + if(count>= minLen) return; + + for(int i = index; i>=0; i--) { + dfs(i, total + coins[i], coins, amount, count+1); + } + } +} From 62add02b1fdf4f7a0b0d6bc0bdda8fbc2188d996 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年3月29日 13:51:26 +0900 Subject: [PATCH 180/526] word-search solution --- word-search/hyeri0903.java | 40 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 word-search/hyeri0903.java diff --git a/word-search/hyeri0903.java b/word-search/hyeri0903.java new file mode 100644 index 0000000000..514559714a --- /dev/null +++ b/word-search/hyeri0903.java @@ -0,0 +1,40 @@ +class Solution { + public boolean exist(char[][] board, String word) { + /** + - backtracking (DFS) + - board[i][j] == word[0] 부터 start + - 상하좌우 탐색, 같은 칸 중복 탐색 x + - 틀리면 backtracking + + */ + + for(int i = 0; i< board.length; i++) { + for(int j = 0; j< board[i].length; j++) { + if(dfs(i, j, 0, board, word)) { + return true; + } + } + } + return false; + } + + boolean dfs(int i, int j, int index, char[][] board, String word) { + //모두 다 찾은 경우 + if(index == word.length()) return true; + + //out of bound check + if(i < 0 || j < 0 || i>= board.length || j>= board[i].length || board[i][j] != word.charAt(index)) return false; + + //방문처리 + char cur = board[i][j]; + board[i][j] = '#'; + + //4방향 탐색 + boolean found = dfs(i+1, j, index+1, board, word) || dfs(i-1, j, index+1, board, word) || dfs(i, j+1, index+1, board, word) || dfs(i, j-1, index+1, board, word); + + //backtracking + board[i][j] = cur; + + return found; + } +} From bdeaaafc2c45407086ce04e334b1def8f2000044 Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: 2026年3月29日 16:07:53 +0900 Subject: [PATCH 181/526] best time to buy and sell stock solution --- .../robinyoon-dev.js | 50 +++++++++++++++---- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/best-time-to-buy-and-sell-stock/robinyoon-dev.js b/best-time-to-buy-and-sell-stock/robinyoon-dev.js index d7dcb423e0..7e8d095bce 100644 --- a/best-time-to-buy-and-sell-stock/robinyoon-dev.js +++ b/best-time-to-buy-and-sell-stock/robinyoon-dev.js @@ -2,21 +2,49 @@ * @param {number[]} prices * @return {number} */ -var maxProfit = function(prices) { - - // NOTE: 해설 보고 쓴 코드입니다. - // i 번째 날에 prices[i]의 가격으로 주식을 팔아서 가장 큰 이익을 내려면 주식을 언제 샀어야 했을까? - // 정답은 바로 i 번째 날이 오기 전에 주식이 가장 쌌던 날 입니다! +var maxProfit = function (prices) { - let maxProfit = 0; let minPrice = prices[0]; + let maxProfit = 0; + + for (let i = 1; i < prices.length; i++) { + let currentPrice = prices[i]; - for(const price of prices){ - const profit = price - minPrice - maxProfit = Math.max(maxProfit, profit); - minPrice = Math.min(price, minPrice); + if (currentPrice < minPrice) { + minPrice = currentPrice; + } else{ + let profit = currentPrice - minPrice; + if(profit> maxProfit){ + maxProfit = profit; + } + } } return maxProfit; - }; + + +// -----아래는 이전에 작성한 답안입니다. +// /** +// * @param {number[]} prices +// * @return {number} +// */ +// var maxProfit = function(prices) { + +// // NOTE: 해설 보고 쓴 코드입니다. +// // i 번째 날에 prices[i]의 가격으로 주식을 팔아서 가장 큰 이익을 내려면 주식을 언제 샀어야 했을까? +// // 정답은 바로 i 번째 날이 오기 전에 주식이 가장 쌌던 날 입니다! + +// let maxProfit = 0; +// let minPrice = prices[0]; + +// for(const price of prices){ +// const profit = price - minPrice +// maxProfit = Math.max(maxProfit, profit); +// minPrice = Math.min(price, minPrice); +// } + +// return maxProfit; + +// }; + From 6f38b25af9c27a3b68ab515f18387a5a77dbecd2 Mon Sep 17 00:00:00 2001 From: soobing Date: 2026年3月29日 09:44:01 +0900 Subject: [PATCH 182/526] feat: coin change --- coin-change/soobing3.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 coin-change/soobing3.ts diff --git a/coin-change/soobing3.ts b/coin-change/soobing3.ts new file mode 100644 index 0000000000..07722a1f2c --- /dev/null +++ b/coin-change/soobing3.ts @@ -0,0 +1,13 @@ +function coinChange(coins: number[], amount: number): number { + const dp = new Array(amount + 1).fill(Infinity); + dp[0] = 0; + + for (let i = 0; i <= amount; i++) { + for(const coin of coins) { + if (i - coin>= 0 && dp[i - coin] !== Infinity) { + dp[i] = Math.min(dp[i], dp[i - coin] + 1); + } + } + } + return dp[amount] === Infinity ? -1 : dp[amount]; +}; From f522fdbae4e81606cf31123c2c849bffc8a21d0a Mon Sep 17 00:00:00 2001 From: soobing Date: 2026年3月29日 17:05:04 +0900 Subject: [PATCH 183/526] feat: exit --- word-search/soobing3.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 word-search/soobing3.ts diff --git a/word-search/soobing3.ts b/word-search/soobing3.ts new file mode 100644 index 0000000000..9c0784ace6 --- /dev/null +++ b/word-search/soobing3.ts @@ -0,0 +1,26 @@ +function exist(board: string[][], word: string): boolean { + const move = [[1, 0], [-1, 0], [0, 1], [0, -1]]; + + function dfs(row: number, col: number, index: number) { + if(board[row][col] !== word[index]) return false; + + const temp = board[row][col]; + board[row][col] = '#'; + + if(index === word.length - 1) return true; + for(const [dx, dy] of move) { + if(row + dx < 0 || row + dx>= board.length) continue; + if(col + dy < 0 || col + dy>= board[0].length) continue; + if(dfs(row + dx, col + dy, index + 1)) return true; + } + + board[row][col] = temp; + } + + for (let r = 0; r < board.length; r++) { + for (let c = 0; c < board[0].length; c++) { + if (dfs(r, c, 0)) return true; + } +} + return false; +}; \ No newline at end of file From a2f3b3e771f7f805ab518f78bdecc30b57062064 Mon Sep 17 00:00:00 2001 From: soobing Date: 2026年3月29日 17:19:48 +0900 Subject: [PATCH 184/526] feat: merge two sorted lists --- merge-two-sorted-lists/soobing3.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 merge-two-sorted-lists/soobing3.ts diff --git a/merge-two-sorted-lists/soobing3.ts b/merge-two-sorted-lists/soobing3.ts new file mode 100644 index 0000000000..d3ee4643f4 --- /dev/null +++ b/merge-two-sorted-lists/soobing3.ts @@ -0,0 +1,30 @@ + +class ListNode { + val: number + next: ListNode | null + constructor(val?: number, next?: ListNode | null) { + this.val = (val===undefined ? 0 : val) + this.next = (next===undefined ? null : next) + } +} + + +function mergeTwoLists(list1: ListNode | null, list2: ListNode | null): ListNode | null { + let mergedList = new ListNode(0, null); + const result = mergedList; + + while(list1 && list2) { + if(list1.val < list2.val) { + mergedList.next = list1; + list1 = list1.next; + } else { + mergedList.next = list2; + list2 = list2.next; + } + mergedList = mergedList.next; + } + + mergedList.next = list1 ?? list2; + + return result.next; +}; \ No newline at end of file From 1302f92b1dd5de6c7033a26b053967cdebd8f366 Mon Sep 17 00:00:00 2001 From: soobing Date: 2026年3月29日 17:36:01 +0900 Subject: [PATCH 185/526] feat: max depth --- maximum-depth-of-binary-tree/soobing3.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 maximum-depth-of-binary-tree/soobing3.ts diff --git a/maximum-depth-of-binary-tree/soobing3.ts b/maximum-depth-of-binary-tree/soobing3.ts new file mode 100644 index 0000000000..8e26db18a6 --- /dev/null +++ b/maximum-depth-of-binary-tree/soobing3.ts @@ -0,0 +1,16 @@ + +class TreeNode { + val: number + left: TreeNode | null + right: TreeNode | null + constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + this.val = (val===undefined ? 0 : val) + this.left = (left===undefined ? null : left) + this.right = (right===undefined ? null : right) + } +} + +function maxDepth(root: TreeNode | null): number { + if(!root) return 0; + return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)) +}; \ No newline at end of file From ff4c65581ada220c75b3764671d1c5bf26999769 Mon Sep 17 00:00:00 2001 From: soobing Date: 2026年3月29日 17:47:42 +0900 Subject: [PATCH 186/526] =?UTF-8?q?feat:=20=EA=B0=9C=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- coin-change/soobing3.ts | 1 + maximum-depth-of-binary-tree/soobing3.ts | 2 +- merge-two-sorted-lists/soobing3.ts | 2 +- word-search/soobing3.ts | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/coin-change/soobing3.ts b/coin-change/soobing3.ts index 07722a1f2c..e65c8f728c 100644 --- a/coin-change/soobing3.ts +++ b/coin-change/soobing3.ts @@ -11,3 +11,4 @@ function coinChange(coins: number[], amount: number): number { } return dp[amount] === Infinity ? -1 : dp[amount]; }; + diff --git a/maximum-depth-of-binary-tree/soobing3.ts b/maximum-depth-of-binary-tree/soobing3.ts index 8e26db18a6..565cd2f6e4 100644 --- a/maximum-depth-of-binary-tree/soobing3.ts +++ b/maximum-depth-of-binary-tree/soobing3.ts @@ -13,4 +13,4 @@ class TreeNode { function maxDepth(root: TreeNode | null): number { if(!root) return 0; return 1 + Math.max(maxDepth(root.left), maxDepth(root.right)) -}; \ No newline at end of file +}; diff --git a/merge-two-sorted-lists/soobing3.ts b/merge-two-sorted-lists/soobing3.ts index d3ee4643f4..461f176fb8 100644 --- a/merge-two-sorted-lists/soobing3.ts +++ b/merge-two-sorted-lists/soobing3.ts @@ -27,4 +27,4 @@ function mergeTwoLists(list1: ListNode | null, list2: ListNode | null): ListNode mergedList.next = list1 ?? list2; return result.next; -}; \ No newline at end of file +}; diff --git a/word-search/soobing3.ts b/word-search/soobing3.ts index 9c0784ace6..5056eaf7cd 100644 --- a/word-search/soobing3.ts +++ b/word-search/soobing3.ts @@ -23,4 +23,4 @@ function exist(board: string[][], word: string): boolean { } } return false; -}; \ No newline at end of file +}; From c97dba2edcd432ec799b409a796632c2dc2a189e Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: 2026年3月28日 17:54:51 +0900 Subject: [PATCH 187/526] Solution for Merge Two Sorted Lists #224 Fix condition in mergeTwoLists to simplify node comparison logic --- merge-two-sorted-lists/dohyeon2.java | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 merge-two-sorted-lists/dohyeon2.java diff --git a/merge-two-sorted-lists/dohyeon2.java b/merge-two-sorted-lists/dohyeon2.java new file mode 100644 index 0000000000..d90a360167 --- /dev/null +++ b/merge-two-sorted-lists/dohyeon2.java @@ -0,0 +1,38 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + // TC : O(n) + // SC : O(n) + public ListNode mergeTwoLists(ListNode list1, ListNode list2) { + // Initialize anonymous head for result + ListNode result = new ListNode(0); + // Initialize cursor to track list + ListNode cursor = result; + + // If any list remains + while(list1 != null || list2 != null){ + // Choose the smaller node + if(list2 == null + || (list1 != null && list1.val <= list2.val)){ + cursor.next = list1; + list1 = list1.next; + }else{ + cursor.next = list2; + list2 = list2.next; + } + //Set the cursor to the next + cursor = cursor.next; + } + + // Skip dummy head and return the actual merged list + return result.next; + } +} From 9bc45479f4caade74547a61a07ec28b92ced3f36 Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: 2026年3月28日 18:44:35 +0900 Subject: [PATCH 188/526] Solution for Maximum Depth of Binary Tree #227 Refactor maxDepth method and simplify dfs parameters for clarity --- maximum-depth-of-binary-tree/dohyeon2.java | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 maximum-depth-of-binary-tree/dohyeon2.java diff --git a/maximum-depth-of-binary-tree/dohyeon2.java b/maximum-depth-of-binary-tree/dohyeon2.java new file mode 100644 index 0000000000..820bdaa87a --- /dev/null +++ b/maximum-depth-of-binary-tree/dohyeon2.java @@ -0,0 +1,40 @@ +/** + * 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; + * } + * } + */ + +// Good solution from Leetcode +// class Solution{ +// public int maxDepth(TreeNode root){ +// if (root==null) return 0; +// return Math.max(maxDepth(root.left),maxDepth(root.right)) + 1; +// } +// } + +class Solution { + // TC : O(n) + // SC : O(h) height of tree(DFS), width of tree(BFS) + public int maxDepth(TreeNode root) { + return dfs(root, 0); + } + + private int dfs(TreeNode cursor, int depth) { + if (cursor == null) { + return depth; + } + return Math.max( + dfs(cursor.left, depth + 1), + dfs(cursor.right, depth + 1)); + } +} From 255b6931687f724967c9edc1c0951e0ba4909c56 Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: 2026年3月28日 20:09:56 +0900 Subject: [PATCH 189/526] Solution for Find Minimum In Rotated Sorted Array #245 --- .../dohyeon2.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/dohyeon2.java diff --git a/find-minimum-in-rotated-sorted-array/dohyeon2.java b/find-minimum-in-rotated-sorted-array/dohyeon2.java new file mode 100644 index 0000000000..c769780fbe --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/dohyeon2.java @@ -0,0 +1,47 @@ +public class Solution { + // TC : O(log n) + // SC : O(1) + public int findMin(int[] nums) { + // You must write an algorithm that runs in O(log n) time. => this means the solution is binary search + int left = 0; + int right = nums.length - 1; + + while(left < right){ + int mid = left + ((right - left) / 2); + + if(nums[right]> nums[mid]){ + right = mid; + }else{ + left = mid + 1; + } + } + + return nums[left]; + } +} + +// First attempt : the algorithm is correct but the condition is wrong. +// class Solution { +// public int findMin(int[] nums) { +// // You must write an algorithm that runs in O(log n) time. => this means the solution is binary search +// int cursor = (nums.length - 1) / 2; +// int left = 0; +// int right = nums.length - 1; + +// // 이전 값이 현재 값보다 커지는 경우가 종료 +// while(cursor - 1>= 0 && nums[cursor - 1] < nums[cursor]){ +// int n = nums[cursor]; +// int rn = nums[right]; + +// if(rn> n){ +// right = cursor; +// }else{ +// left = cursor; +// } + +// cursor = left + ((right - left) / 2); +// } + +// return nums[cursor]; +// } +// } From e477e2292c6de1966dcdd84bbe7f71a32084d9bd Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: 2026年3月28日 22:51:01 +0900 Subject: [PATCH 190/526] Solution for Word Search #255 --- word-search/dohyeon2.java | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 word-search/dohyeon2.java diff --git a/word-search/dohyeon2.java b/word-search/dohyeon2.java new file mode 100644 index 0000000000..9b74bd2903 --- /dev/null +++ b/word-search/dohyeon2.java @@ -0,0 +1,41 @@ +class Solution { + // TC : O(n*4^L); n = the number of the characters, L = the length of the word + // SC : O(m*n + L) m = a row of the board, n = a cell of the board, L = the length of the word + public boolean exist(char[][] board, String word) { + for (int y = 0; y < board.length; y++) { + for (int x = 0; x < board[0].length; x++) { + if(board[y][x] != word.charAt(0)){ + continue; + } + boolean[][] visited = new boolean[board.length][board[0].length]; + if (backtrack(x, y, 0, board, visited, word)) { + return true; + } + } + } + return false; + } + + private boolean backtrack(int x, int y, int index, char[][] board, boolean[][] visited, String word) { + if (index == word.length()) + return true; + + if (y < 0 || y>= board.length || x < 0 || x>= board[0].length) + return false; + + if (visited[y][x] || board[y][x] != word.charAt(index)) + return false; + + visited[y][x] = true; + + boolean found = backtrack(x + 1, y, index + 1, board, visited, word) || + backtrack(x - 1, y, index + 1, board, visited, word) || + backtrack(x, y + 1, index + 1, board, visited, word) || + backtrack(x, y - 1, index + 1, board, visited, word); + + visited[y][x] = false; // It failed on the first attempt because this line was missing. + + return found; + } + +} From 76e17dbad898edd7d2c7dc176ddf808f64c6193f Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: 2026年3月29日 00:03:53 +0900 Subject: [PATCH 191/526] Solution For Coin Change #269 --- coin-change/dohyeon2.java | 93 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 coin-change/dohyeon2.java diff --git a/coin-change/dohyeon2.java b/coin-change/dohyeon2.java new file mode 100644 index 0000000000..9991e9e157 --- /dev/null +++ b/coin-change/dohyeon2.java @@ -0,0 +1,93 @@ +import java.util.Arrays; + +class Solution { + // TC: O(amount * coins.length) + // SC: O(amount) + public int coinChange(int[] coins, int amount) { + int[] dp = new int[amount + 1]; + // Maximum depth = amount + // amount + 1 means undefined; set to use Math.min + Arrays.fill(dp, amount + 1); + + dp[0] = 0; + + for(int i = 1; i <= amount; i++){ + for(int coin : coins){ + if(i - coin>= 0){ + // depth without the coin + with the coin(1) + dp[i] = Math.min(dp[i], dp[i - coin] + 1); + } + } + } + + return dp[amount]> amount ? -1 : dp[amount]; + } +} + +// DFS + Memoization +// class Solution { +// public int coinChange(int[] coins, int amount) { +// int[] memo = new int[amount + 1]; +// Arrays.fill(memo, -2); // -2 = 아직 계산 안함 +// return dfs(0, coins, amount, memo); +// } + +// private int dfs(int depth, int[] coins, int amount, int[] memo){ +// if(amount < 0){ +// return -1; +// } +// if(amount == 0){ +// return depth; +// } + +// if(memo[amount] != -2) return memo[amount]; + +// int min = -1; +// for(int i = 0; i < coins.length; i++){ +// int descended = coins[coins.length - i - 1]; +// int d = dfs(depth + 1, coins, amount - descended, memo); +// if(d>= 0 && (d < min || min == -1)){ +// min = d; +// } +// } + +// if(memo[amount] == -2) memo[amount] = min; // 계산한 적 없는 경우에만 저장 +// return min; +// } +// } + +// BFS : 문제 서술과 가장 어울리는 풀이지만, Bottom-Up DP가 더 빠른 결과. +// class Solution { +// public int coinChange(int[] coins, int amount) { +// Queue queue = new LinkedList(); +// boolean[] visited = new boolean[amount + 1]; + +// queue.offer(amount); +// visited[amount] = true; + +// int level = 0; + +// while (!queue.isEmpty()) { +// int size = queue.size(); + +// for (int i = 0; i < size; i++) { +// int cur = queue.poll(); + +// if (cur == 0) return level; + +// for (int coin : coins) { +// int next = cur - coin; + +// if (next>= 0 && !visited[next]) { +// visited[next] = true; +// queue.offer(next); +// } +// } +// } + +// level++; +// } + +// return -1; +// } +// } From 0207044610faf33f775dd39359c30a5f4fa4b039 Mon Sep 17 00:00:00 2001 From: soobing Date: 2026年3月29日 18:53:03 +0900 Subject: [PATCH 192/526] feat: find-minimum-in-rotated-sorted-array --- find-minimum-in-rotated-sorted-array/soobing3.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/soobing3.ts diff --git a/find-minimum-in-rotated-sorted-array/soobing3.ts b/find-minimum-in-rotated-sorted-array/soobing3.ts new file mode 100644 index 0000000000..cbf3449843 --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/soobing3.ts @@ -0,0 +1,13 @@ +function findMin(nums: number[]): number { + let left = 0; + let right = nums.length - 1; + while(left < right) { + const mid = Math.floor((left + right) / 2); + if(nums[mid]> nums[right]) { + left = mid + 1; + } else { + right = mid; + } + } + return nums[left]; +}; From e7d2077a1212b0fb4961ead2c9f6803894847c44 Mon Sep 17 00:00:00 2001 From: Yu-Won Date: 2026年3月29日 22:13:29 +0900 Subject: [PATCH 193/526] find minimum in rotated sorted array solution --- .../Yu-Won.js | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/Yu-Won.js diff --git a/find-minimum-in-rotated-sorted-array/Yu-Won.js b/find-minimum-in-rotated-sorted-array/Yu-Won.js new file mode 100644 index 0000000000..fb701ec2c3 --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/Yu-Won.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} nums + * @return {number} + * + * 문제: https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/ + * 요구사항: 이진트리 활용 + */ +const findMin = (nums) => { + let left = 0; + let right = nums.length - 1; + + while (left < right) { + let mid = Math.floor((left + right) / 2); + + if (nums[mid]> nums[right]) { + left = mid + 1; + } else { + right = mid; + } + } + + return nums[left]; +}; \ No newline at end of file From f71f866845233d9ddde62d76d663a2cb991b0621 Mon Sep 17 00:00:00 2001 From: Yu-Won Date: 2026年3月29日 22:20:43 +0900 Subject: [PATCH 194/526] fix: bug --- find-minimum-in-rotated-sorted-array/Yu-Won.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/find-minimum-in-rotated-sorted-array/Yu-Won.js b/find-minimum-in-rotated-sorted-array/Yu-Won.js index fb701ec2c3..0ec381cae7 100644 --- a/find-minimum-in-rotated-sorted-array/Yu-Won.js +++ b/find-minimum-in-rotated-sorted-array/Yu-Won.js @@ -20,4 +20,4 @@ const findMin = (nums) => { } return nums[left]; -}; \ No newline at end of file +}; From 423d1775ec77b4f9cbd795ff9869c6806e7fa947 Mon Sep 17 00:00:00 2001 From: Yu-Won Date: 2026年3月29日 22:26:19 +0900 Subject: [PATCH 195/526] word search solution --- word-search/Yu-Won.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 word-search/Yu-Won.js diff --git a/word-search/Yu-Won.js b/word-search/Yu-Won.js new file mode 100644 index 0000000000..c758a345e7 --- /dev/null +++ b/word-search/Yu-Won.js @@ -0,0 +1,41 @@ +/** + * @param {character[][]} board + * @param {string} word + * @return {boolean} + * + * 문제: https://leetcode.com/problems/word-search/ + * 요구사항: 그리드 구조에서 word의 문자열 존재 여부에 따라 true/false를 리턴한다. + * 백트래킹, dfs + */ +const exist = (board, word) => { + let rows = board.length; + let cols = board[0].length; + + const dfs = (r, c, index) => { + if (index === word.length) return true; + + if (r < 0 || r>= rows || c < 0 || c>= cols || board[r][c] !== word[index]) { + return false; + } + + let temp = board[r][c]; + board[r][c] = '#'; + + let found = dfs(r + 1, c, index + 1) || + dfs(r - 1, c, index + 1) || + dfs(r, c + 1, index + 1) || + dfs(r, c - 1, index + 1); + + board[r][c] = temp; + + return found; + } + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (board[i][j] === word[0] && dfs(i, j, 0)) return true; + } + } + + return false; +}; From 4fb0d86582bebb6c1928d6c8b53ebedf54af2e7c Mon Sep 17 00:00:00 2001 From: Yu-Won Date: 2026年3月29日 22:32:55 +0900 Subject: [PATCH 196/526] coin change solution --- coin-change/Yu-Won.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 coin-change/Yu-Won.js diff --git a/coin-change/Yu-Won.js b/coin-change/Yu-Won.js new file mode 100644 index 0000000000..de89555ae7 --- /dev/null +++ b/coin-change/Yu-Won.js @@ -0,0 +1,21 @@ +/** + * @param {number[]} coins + * @param {number} amount + * @return {number} + * + * 문제: https://leetcode.com/problems/coin-change/ + * 요구사항: 동전과 총 금액이 주어질 때 해당 금액을 만드는데 최소 동전 개수를 반환 + */ +const coinChange = (coins, amount) => { + let dp = new Array(amount + 1).fill(amount + 1); + dp[0] = 0; + for (let i = 1; i <= amount; i++) { + for (const coin of coins) { + if (i - coin>= 0) { + dp[i] = Math.min(dp[i], dp[i - coin] + 1); + } + } + } + + return dp[amount]> amount ? -1 : dp[amount]; +}; From 72ac8bb8756914d8e61214f208bd74381d43da7a Mon Sep 17 00:00:00 2001 From: Dale Seo <5466341+daleseo@users.noreply.github.com> Date: 2026年3月29日 14:57:24 -0400 Subject: [PATCH 197/526] group-anagrams --- group-anagrams/DaleSeo.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 group-anagrams/DaleSeo.rs diff --git a/group-anagrams/DaleSeo.rs b/group-anagrams/DaleSeo.rs new file mode 100644 index 0000000000..258963e990 --- /dev/null +++ b/group-anagrams/DaleSeo.rs @@ -0,0 +1,17 @@ +// TC: O(n * k) where n = number of strings, k = max string length +// SC: O(n * k) +use std::collections::HashMap; + +impl Solution { + pub fn group_anagrams(strs: Vec) -> Vec> { + let mut anagrams: HashMap<[u8; 26], Vec> = HashMap::new(); + for s in strs { + let mut count = [0u8; 26]; + for b in s.bytes() { + count[(b - b'a') as usize] += 1; + } + anagrams.entry(count).or_default().push(s); + } + anagrams.into_values().collect() + } +} From 34258fadd551b06b31abaeb0b13b020dee478931 Mon Sep 17 00:00:00 2001 From: hyejj19 Date: 2026年3月30日 11:00:59 +0900 Subject: [PATCH 198/526] solve best-time-to-buy-and-sell-stock --- best-time-to-buy-and-sell-stock/hyejj19.ts | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/hyejj19.ts diff --git a/best-time-to-buy-and-sell-stock/hyejj19.ts b/best-time-to-buy-and-sell-stock/hyejj19.ts new file mode 100644 index 0000000000..9c66553811 --- /dev/null +++ b/best-time-to-buy-and-sell-stock/hyejj19.ts @@ -0,0 +1,26 @@ +function maxProfit(prices: number[]): number { + let minPrice = Number.MAX_SAFE_INTEGER; + let maxProfit = 0; + + for (let p of prices) { + if (minPrice>= p) { + minPrice = p; + continue; + } else { + let profit = p - minPrice; + if (profit> maxProfit) maxProfit = profit; + } + } + return maxProfit; +} + +function maxProfit(prices: number[]): number { + let minPrice = Infinity; + let maxProfit = 0; + + for (let p of prices) { + minPrice = Math.min(minPrice, p); + maxProfit = Math.max(maxProfit, p - minPrice); + } + return maxProfit; +} From 8d061e1ab9b5fd6e28bb3a762226eb259de306d4 Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年3月30日 16:48:40 +0900 Subject: [PATCH 199/526] add: bestTimeToBuyAndSellStock solution --- best-time-to-buy-and-sell-stock/Cyjin-jani.js | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/Cyjin-jani.js diff --git a/best-time-to-buy-and-sell-stock/Cyjin-jani.js b/best-time-to-buy-and-sell-stock/Cyjin-jani.js new file mode 100644 index 0000000000..9f844a76de --- /dev/null +++ b/best-time-to-buy-and-sell-stock/Cyjin-jani.js @@ -0,0 +1,42 @@ +// naive하게 풀면, time limit 초과함 +// O(n^2) 풀이가 되기 때문.. +const maxProfit_naive = function (prices) { + let profit = 0; + + for (let i = 0; i < prices.length - 1; i++) { + const buy = prices[i]; + for (let j = i + 1; j < prices.length; j++) { + const newProfit = prices[j] - buy; + if (newProfit> profit) { + profit = newProfit; + } + } + } + + return profit; +}; + +// 투포인터 사용하여 풀기 +// tc: O(n) +// sc: O(1) +const maxProfit = function (prices) { + let buyIdx = 0; + let sellIdx = 1; + + while (sellIdx < prices.length) { + let buyPrice = prices[buyIdx]; + let sellPrice = prices[sellIdx]; + + // 더 낮은 가격에 매수 가능한 날을 찾으면 바로 거기서부터 재탐색 + if (buyPrice> sellPrice) { + buyIdx = sellIdx; + } else { + let newProfit = sellPrice - buyPrice; + profit = Math.max(profit, newProfit); + } + + sellIdx++; + } + + return profit; +}; From 5b56357849057afa72e8476d0a6346eecc6bd618 Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: 2026年3月30日 19:45:40 +0900 Subject: [PATCH 200/526] add solution for merge two sorted lists --- merge-two-sorted-lists/Hyeri1ee.java | 37 ++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 merge-two-sorted-lists/Hyeri1ee.java diff --git a/merge-two-sorted-lists/Hyeri1ee.java b/merge-two-sorted-lists/Hyeri1ee.java new file mode 100644 index 0000000000..5348271762 --- /dev/null +++ b/merge-two-sorted-lists/Hyeri1ee.java @@ -0,0 +1,37 @@ +import java.util.*; + + + + +class Solution { + + + public ListNode mergeTwoLists(ListNode list1, ListNode list2) { + ListNode merged = new ListNode();//머지 된 노드 모음 + ListNode temp = merged; + while(list1 != null && list2 != null){ + + ListNode newNode = new ListNode();//새로운 노드 + if (list1.val> list2.val){ + //list2 + newNode.val = list2.val; + list2 =list2.next;//다음 가리키도록\ + // merged.next + }else{ + newNode.val =list1.val; + list1=list1.next;//다음 가리키도록 + } + + merged.next = newNode; + merged =merged.next; + + } + + if (list1==null) + merged.next= list2; + else if (list2 == null) + merged.next=list1; + + return temp.next; + } +} From 21ad745604c46410c19baac65b1950ed674e63b2 Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: 2026年3月30日 19:47:13 +0900 Subject: [PATCH 201/526] add solution for maximum depth of binary tree --- maximum-depth-of-binary-tree/Hyeri1ee.java | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 maximum-depth-of-binary-tree/Hyeri1ee.java diff --git a/maximum-depth-of-binary-tree/Hyeri1ee.java b/maximum-depth-of-binary-tree/Hyeri1ee.java new file mode 100644 index 0000000000..56246df21a --- /dev/null +++ b/maximum-depth-of-binary-tree/Hyeri1ee.java @@ -0,0 +1,32 @@ +/** + * 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; + * } + * } + */ + import java.util.*; +class Solution { + private static int solve(TreeNode root, int depth){ + if (root == null){ + return depth; + } + + //root가null이 아닌 경우 + return Math.max(solve(root.left, depth+1) , solve(root.right, depth+1)); + + } + public int maxDepth(TreeNode root) { + int result = solve(root, 0); + return result; + } +} + From c5ae96b7ef858ec87f29849e507e6c47de6c0ff5 Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: 2026年3月30日 23:48:29 +0900 Subject: [PATCH 202/526] add solution for find minimum in rotated sorted array --- find-minimum-in-rotated-sorted-array/Hyeri1ee.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/Hyeri1ee.java diff --git a/find-minimum-in-rotated-sorted-array/Hyeri1ee.java b/find-minimum-in-rotated-sorted-array/Hyeri1ee.java new file mode 100644 index 0000000000..4a84b49877 --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/Hyeri1ee.java @@ -0,0 +1,11 @@ +//맨뒤 요소 맨앞으로 +import java.util.*; + + +class Solution { + public int findMin(int[] nums) { + Arrays.sort(nums); + return nums[0]; + } +} + From 5d065338cdbfed0333fae7c49376e0fb80b20195 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年3月30日 23:56:13 +0900 Subject: [PATCH 203/526] best-time-to-by-and-sell-stock solution --- .../hyeri0903.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/hyeri0903.java diff --git a/best-time-to-buy-and-sell-stock/hyeri0903.java b/best-time-to-buy-and-sell-stock/hyeri0903.java new file mode 100644 index 0000000000..a5904c455a --- /dev/null +++ b/best-time-to-buy-and-sell-stock/hyeri0903.java @@ -0,0 +1,43 @@ +class Solution { + public int maxProfit(int[] prices) { + /** + 1. 하루에 팔아서 가장 최대 이익을 구하도록하는 max price return + 2. 조건 + - 미래 다른날짜에 판매 (이전 날짜에 판매 x) + - choosing a single day + - 배열 길이 min = 1, max = 10^5 + - 원소값 : min = 0, max = 10^4 + 3. 풀이 + - 1)brtueforce: time complexity O(n^2), space: O(1) + - 2)현재 값 - 이전 값 중 가장 최소값 -> maxProfit , 즉 min값을 계속 기억하다가 현재 값과의 차이 중 가장 큰 값을 구하면된다. + - time: O(n) + - space: O(1) + */ + + int maxProfit = 0; + int minStock = Integer.MAX_VALUE; + int n = prices.length; + + for(int i = 0; i 0 && prices[i] - minStock> maxProfit) { + maxProfit = Math.max(maxProfit, prices[i] - minStock); + } + } + return maxProfit; + + + // for(int i = 0; i < n; i++) { + // int curStock = prices[i]; + // for(int j= i + 1; j < n; j++) { + // if(curStock < prices[j]) { + // int curProfit = prices[j] - curStock; + // maxProfit = Math.max(maxProfit, curProfit); + // } + // } + // } + // return maxProfit; + } +} From 4d5facbede54493b9d31997a4000d967556f4d82 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年3月30日 23:56:42 +0900 Subject: [PATCH 204/526] group-anagrams solution --- group-anagrams/hyeri0903.java | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 group-anagrams/hyeri0903.java diff --git a/group-anagrams/hyeri0903.java b/group-anagrams/hyeri0903.java new file mode 100644 index 0000000000..2e248d261b --- /dev/null +++ b/group-anagrams/hyeri0903.java @@ -0,0 +1,42 @@ +class Solution { + public List> groupAnagrams(String[] strs) { + /** + 1.anagram 끼리 그룹화해서 return + 2.조건 + - answer in any order + - strs 길이 최소 = 1, 최대 = 10^4 + - 원소 하나당 길이 최소 = 0, 최대 = 100 + - 모두 소문자로 구성 + 3.풀이 + - 1) i번째 이후 단어를 비교해가면서 anagram check, time: O(n^2) + - 2) HashMap: string element 를 정렬해서 key 로 사용, 중복되는 Key 있으면 anagram, time: O(n) + */ + + int n = strs.length; + //anagram 체크할 Map + Map> map = new HashMap(); + + for(int i = 0; i < n; i++) { + String curStr = strs[i]; + char[] tmp = curStr.toCharArray(); + Arrays.sort(tmp); + String key = new String(tmp); + // System.out.println("curStr:" + curStr + ", key: " + key); + //Map 에 저장 + map.putIfAbsent(key, new ArrayList()); + map.get(key).add(curStr); + // if(!map.containsKey(key)) { + // List words = new ArrayList(); + // words.add(curStr); + // map.put(key, words); + // } else { + // List words = map.get(key); + // words.add(curStr); + // map.put(key, words); + // } + } + + + return new ArrayList(map.values()); + } +} From 7a1d0fb3ff3e135cd0f93d61189c8b0245eb25ac Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年3月30日 12:20:45 -0700 Subject: [PATCH 205/526] best time to buy and sell stock solution --- best-time-to-buy-and-sell-stock/jylee2033.py | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/jylee2033.py diff --git a/best-time-to-buy-and-sell-stock/jylee2033.py b/best-time-to-buy-and-sell-stock/jylee2033.py new file mode 100644 index 0000000000..0c39acca9d --- /dev/null +++ b/best-time-to-buy-and-sell-stock/jylee2033.py @@ -0,0 +1,25 @@ +class Solution: + def maxProfit(self, prices: List[int]) -> int: + # When length is 1, no profit possible + if len(prices) == 1: + return 0 + + buy = 10 ** 5 + profit = 0 + + # Iterate through prices + for i, price in enumerate(prices): + if price < buy: + buy = price + + for j in range(i + 1, len(prices)): + if prices[j] <= buy: + continue + + if prices[j] - buy> profit: + profit = prices[j] - buy + + return profit + +# Time Complexity: O(n^2) +# Space Complexity: O(1) From af8473fd5454744ca70695120aede00c5b281bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=EC=98=81?= Date: 2026年3月30日 12:34:20 +0900 Subject: [PATCH 206/526] =?UTF-8?q?best-time-to-buy-and-sell-stock=20?= =?UTF-8?q?=ED=92=80=EC=9D=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- best-time-to-buy-and-sell-stock/junzero741.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/junzero741.ts diff --git a/best-time-to-buy-and-sell-stock/junzero741.ts b/best-time-to-buy-and-sell-stock/junzero741.ts new file mode 100644 index 0000000000..857df55243 --- /dev/null +++ b/best-time-to-buy-and-sell-stock/junzero741.ts @@ -0,0 +1,15 @@ +// TC: O(N) +// SC: O(1) +function maxProfit(prices: number[]): number { + let maxProfit = 0 + let minPrice = Infinity + + for(const price of prices) { + maxProfit = Math.max(price - minPrice, maxProfit) + minPrice = Math.min(price, minPrice) + } + + return maxProfit + +}; + From 007f3261b796f5adb6a1c192bb914df6d1ebd8da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A4=80=EC=98=81?= Date: 2026年3月31日 10:48:49 +0900 Subject: [PATCH 207/526] =?UTF-8?q?group-anagrams=20=ED=92=80=EC=9D=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group-anagrams/junzero741.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 group-anagrams/junzero741.ts diff --git a/group-anagrams/junzero741.ts b/group-anagrams/junzero741.ts new file mode 100644 index 0000000000..2e8292dfdb --- /dev/null +++ b/group-anagrams/junzero741.ts @@ -0,0 +1,19 @@ +// TC: O(N*KlogK) +// SC: O(N*K) +function groupAnagrams(strs: string[]): string[][] { + + const idMap = new Map(); + + for(const str of strs) { + const id = str.split("").sort().join(""); + + if(!idMap.has(id)) { + idMap.set(id, []) + } + + idMap.get(id)!.push(str) + } + + return [...idMap.values()] + +}; From 7ce5e47cd5307a7443fd99ab50f667c5763546f9 Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年3月31日 18:12:54 +0900 Subject: [PATCH 208/526] add: groupAnagrams solution --- group-anagrams/Cyjin-jani.js | 95 ++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 group-anagrams/Cyjin-jani.js diff --git a/group-anagrams/Cyjin-jani.js b/group-anagrams/Cyjin-jani.js new file mode 100644 index 0000000000..d7d0745d47 --- /dev/null +++ b/group-anagrams/Cyjin-jani.js @@ -0,0 +1,95 @@ +const isAnagram = function (s, t) { + if (s.length !== t.length) return false; + + const data = new Map(); + + for (let char of s) { + data.set(char, (data.get(char) || 0) + 1); + } + + for (let char of t) { + if (!data.get(char)) return false; + data.set(char, data.get(char) - 1); + } + + return true; +}; + +// Time Limit Exceeded로 fail.. +// tc: O(n^2); +// sc: O(n) +const groupAnagrams_naive = function (strs) { + if (strs.length < 2) return [strs]; + + const answer = []; + + while (strs.length> 0) { + let temp = [strs[0]]; + + if (strs.length < 2) return answer; + + strs.splice(0, 1); + + for (let j = 0; j < strs.length; j++) { + if (isAnagram(temp[0], strs[j])) { + // 같다면, temp 배열에 넣음 + temp.push(strs[j]); + } + } + answer.push(temp); + + temp.forEach((t) => { + const idx = strs.indexOf(t); + if (idx !== -1) { + strs.splice(idx, 1); + } + }); + + if (strs.length === 1) { + answer.push(strs); + } + } + + return answer; +}; + +// splice 같은 로직이 없어서 겨우 TLE을 통과했지만 여전히 O(n2)인 점은 변함이 없음. +const groupAnagrams_set = function (strs) { + const visited = new Set(); + const answer = []; + + for (let i = 0; i < strs.length; i++) { + if (visited.has(i)) continue; + + const group = [strs[i]]; + + for (let j = i + 1; j < strs.length; j++) { + if (!visited.has(j) && isAnagram(strs[i], strs[j])) { + group.push(strs[j]); + visited.add(j); + } + } + + answer.push(group); + } + + return answer; +}; + +//! AI로부터 힌트를 얻어 풀어봤습니다.. +// tc: O(nlogn) +// sc: O(n) +const groupAnagrams = function (strs) { + const map = new Map(); + + for (const str of strs) { + const key = str.split('').sort().join(''); + + if (!map.has(key)) { + map.set(key, []); + } + map.get(key).push(str); + } + + return [...map.values()]; +}; From 514a084bde7d2305cef8f35da6e8f3945f1ecca9 Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: 2026年3月31日 22:45:29 +0900 Subject: [PATCH 209/526] add solution for word-search --- word-search/Hyeri1ee.java | 73 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 word-search/Hyeri1ee.java diff --git a/word-search/Hyeri1ee.java b/word-search/Hyeri1ee.java new file mode 100644 index 0000000000..94a916c941 --- /dev/null +++ b/word-search/Hyeri1ee.java @@ -0,0 +1,73 @@ +import java.util.*; + + +class Solution { + + //상,하,좌,우 + static int[] dx = {0,1,-1,0}; + static int[] dy = {1,0,0,-1}; + + static int m, n; + + static boolean result; //exist 함수가 호출될때마다 초기화해야함 + static char[][] map; //지역변수 board 저장용 + static String w; //word 저장용 + public boolean exist(char[][] board, String word) { + + result=false; + + m = board.length; + n = board[0].length; + + w = word; + //map <- board + map = new char[m][n]; + for(int i =0; i= 0 && x < m && y>= 0 && y < n; + } +} + From 29fcc2396107abb43de56813f71a65ef6d1332a7 Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: Wed, 1 Apr 2026 09:54:04 +0900 Subject: [PATCH 210/526] best time to buy and sell stock solution --- best-time-to-buy-and-sell-stock/robinyoon-dev.js | 1 - 1 file changed, 1 deletion(-) diff --git a/best-time-to-buy-and-sell-stock/robinyoon-dev.js b/best-time-to-buy-and-sell-stock/robinyoon-dev.js index 7e8d095bce..aefc150dd2 100644 --- a/best-time-to-buy-and-sell-stock/robinyoon-dev.js +++ b/best-time-to-buy-and-sell-stock/robinyoon-dev.js @@ -23,7 +23,6 @@ var maxProfit = function (prices) { return maxProfit; }; - // -----아래는 이전에 작성한 답안입니다. // /** // * @param {number[]} prices From 1fe3839f383b22a4c04a53b087af65f23a42c3a4 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: Wed, 1 Apr 2026 10:01:38 +0900 Subject: [PATCH 211/526] solved encode-and-decode-strings. --- encode-and-decode-strings/sangbeenmoon.py | 43 +++++++++++++++++++++++ group-anagrams/sangbeenmoon.py | 35 ++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 encode-and-decode-strings/sangbeenmoon.py create mode 100644 group-anagrams/sangbeenmoon.py diff --git a/encode-and-decode-strings/sangbeenmoon.py b/encode-and-decode-strings/sangbeenmoon.py new file mode 100644 index 0000000000..7478d851e0 --- /dev/null +++ b/encode-and-decode-strings/sangbeenmoon.py @@ -0,0 +1,43 @@ +class Solution: + """ + @param: strs: a list of strings + @return: encodes a list of strings to a single string. + """ + def encode(self, strs): + # write your code here + result = "" + + delimiter = ":;" + + for i, str in enumerate(strs): + result = result + str + if i != len(strs): + result = result + delimiter + + print(result) + + return result + + """ + @param: str: A string + @return: decodes a single string to a list of strings + """ + def decode(self, str): + result = [] + + i = 0 + delimiter = ":;" + + while i < len(str): + + j = i + while j < len(str) - 1: + if str[j:j+2] == delimiter: + result.append(str[i:j]) + break + else: + j = j + 1 + + i = j + 2 + + return result diff --git a/group-anagrams/sangbeenmoon.py b/group-anagrams/sangbeenmoon.py new file mode 100644 index 0000000000..72a260e00a --- /dev/null +++ b/group-anagrams/sangbeenmoon.py @@ -0,0 +1,35 @@ +# TC : O(m^2 * n) m : len(strs), n : len(strs[0]) +# SC : O(m * n) + +class Solution: + def groupAnagrams(self, strs: List[str]) -> List[List[str]]: + sorted_strs = [] + for str in strs: + sorted_strs.append(sorted(str)) + + answer = [] + + i = 0 + + visited = [False] * 10001 + + while i < len(strs): + if visited[i]: + i = i + 1 + continue + + sub_answer = [] + target = sorted_strs[i] + sub_answer.append(strs[i]) + + for j in range(i+1, len(strs)): + if sorted_strs[j] == target: + visited[j] = True + sub_answer.append(strs[j]) + + i = i + 1 + answer.append(sub_answer) + + return answer + + From 9075685a0892533b22be5083e78394d4cd6fecea Mon Sep 17 00:00:00 2001 From: yaeji Date: Wed, 1 Apr 2026 12:42:27 +0900 Subject: [PATCH 212/526] week5: best-time-to-buy-and-sell-stock --- best-time-to-buy-and-sell-stock/reeseo3o.js | 31 +++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/reeseo3o.js diff --git a/best-time-to-buy-and-sell-stock/reeseo3o.js b/best-time-to-buy-and-sell-stock/reeseo3o.js new file mode 100644 index 0000000000..637a660b8d --- /dev/null +++ b/best-time-to-buy-and-sell-stock/reeseo3o.js @@ -0,0 +1,31 @@ +// Step 1. 브루트 포스 +// 시간 복잡도: O(n2) +const maxProfitBrute = (prices) => { + let maxProfit = 0; + + for (let i = 0; i < prices.length; i++) { + for (let j = i + 1; j < prices.length; j++) { + const profit = prices[j] - prices[i]; + maxProfit = Math.max(maxProfit, profit); + } + } + + return maxProfit; +} + +// Step 2. 최적 풀이 +// 시간 복잡도: O(n) +const maxProfit = (prices) => { + let minPrice = Infinity; + let maxProfit = 0; + + for (const price of prices) { + if (price < minPrice) { + minPrice = price; + } else { + maxProfit = Math.max(maxProfit, price - minPrice); + } + } + + return maxProfit; +} From 823887cd5eb30f94a8dc9f703df55812eb0fce79 Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: Wed, 1 Apr 2026 13:39:54 +0900 Subject: [PATCH 213/526] group anagrams solution --- group-anagrams/robinyoon-dev.js | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 group-anagrams/robinyoon-dev.js diff --git a/group-anagrams/robinyoon-dev.js b/group-anagrams/robinyoon-dev.js new file mode 100644 index 0000000000..014866a870 --- /dev/null +++ b/group-anagrams/robinyoon-dev.js @@ -0,0 +1,45 @@ +/** + * @param {string[]} strs + * @return {string[][]} + */ + +// 문제는 풀었으나 시간 복잡도 측면에서 효율이 너무 떨어지는 풀이 방법.... +var groupAnagrams = function (strs) { + let outputArr = []; + let countArr = []; + + const A_ASCII = 'a'.charCodeAt(0); + const Z_ASCII = 'z'.charCodeAt(0); + + let charCounts = Z_ASCII - A_ASCII + 1; + let charCountArr = new Array(charCounts).fill(0); //인덱스가 알파벳을 나타냄. + + for (str of strs) { + let strCountString = getStrCountString(str); + + let hasSameCountIndex = countArr.findIndex((item) => item === strCountString); + + if (hasSameCountIndex !== -1) { + outputArr[hasSameCountIndex].push(str); + } else { + countArr.push(strCountString); + + outputArr.push([str]); + } + } + + return outputArr; + + function getStrCountString(str) { + let tempArr = [...charCountArr]; + + for (char of str) { + let charAscii = char.charCodeAt(0); + let charIndex = charAscii - A_ASCII; + tempArr[charIndex] += 1; + } + return tempArr.join(','); + } +}; + + From b8168edb3ce0d1d5bbaa4ebc88530245d542a510 Mon Sep 17 00:00:00 2001 From: Ted Date: Wed, 1 Apr 2026 01:58:49 -0400 Subject: [PATCH 214/526] add week 5 solutions --- best-time-to-buy-and-sell-stock/tedkimdev.go | 20 ++++++ encode-and-decode-strings/tedkimdev.go | 32 ++++++++++ group-anagrams/tedkimdev.go | 19 ++++++ implement-trie-prefix-tree/tedkimdev.go | 52 +++++++++++++++ word-break/tedkimdev.go | 67 ++++++++++++++++++++ 5 files changed, 190 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/tedkimdev.go create mode 100644 encode-and-decode-strings/tedkimdev.go create mode 100644 group-anagrams/tedkimdev.go create mode 100644 implement-trie-prefix-tree/tedkimdev.go create mode 100644 word-break/tedkimdev.go diff --git a/best-time-to-buy-and-sell-stock/tedkimdev.go b/best-time-to-buy-and-sell-stock/tedkimdev.go new file mode 100644 index 0000000000..bc7f9a3d3d --- /dev/null +++ b/best-time-to-buy-and-sell-stock/tedkimdev.go @@ -0,0 +1,20 @@ +// TC: O(n) +// SC: O(1) +func maxProfit(prices []int) int { + l, r := 0, 1 + max := 0 + + for r < len(prices) { + if prices[l] < prices[r] { + profit := prices[r] - prices[l] + if profit> max { + max = profit + } + } else { + l = r + } + r++ + } + + return max +} diff --git a/encode-and-decode-strings/tedkimdev.go b/encode-and-decode-strings/tedkimdev.go new file mode 100644 index 0000000000..1183a7b7d0 --- /dev/null +++ b/encode-and-decode-strings/tedkimdev.go @@ -0,0 +1,32 @@ +type Solution struct{} + +// TC: O(m) +// SC: O(m + n) +func (s *Solution) Encode(strs []string) string { + encoded := "" + for _, str := range strs { + encoded += fmt.Sprintf("%d|%s", len(str), str) + } + + return encoded +} + +// TC: O(m) +// SC: O(m + n) +func (s *Solution) Decode(encoded string) []string { + decoded := make([]string, 0) + + i := 0 + for i < len(encoded) { + j := i + for encoded[j] != '|' { + j++ + } + length, _ := strconv.Atoi(encoded[i:j]) + i = j + 1 + decoded = append(decoded, encoded[i:i+length]) + i += length + } + + return decoded +} diff --git a/group-anagrams/tedkimdev.go b/group-anagrams/tedkimdev.go new file mode 100644 index 0000000000..7315d5189b --- /dev/null +++ b/group-anagrams/tedkimdev.go @@ -0,0 +1,19 @@ +// TC: O(m * n) +// SC: O(m * n) +func groupAnagrams(strs []string) [][]string { + groups := map[[26]int][]string{} + + for _, s := range strs { + var count [26]int + for _, c := range s { + count[c-'a']++ + } + groups[count] = append(groups[count], s) + } + + result := [][]string{} + for _, group := range groups { + result = append(result, group) + } + return result +} diff --git a/implement-trie-prefix-tree/tedkimdev.go b/implement-trie-prefix-tree/tedkimdev.go new file mode 100644 index 0000000000..fb8e5757e9 --- /dev/null +++ b/implement-trie-prefix-tree/tedkimdev.go @@ -0,0 +1,52 @@ +// TC: O(n) +// SC: O(t) - Where n is the length of the string and t is the total number of TrieNodes created in the Trie. +type PrefixTree struct { + children map[rune]*PrefixTree + isWord bool +} + +func Constructor() PrefixTree { + return PrefixTree{ + children: map[rune]*PrefixTree{}, + isWord: false, + } +} + +func (this *PrefixTree) Insert(word string) { + cur := this + for _, c := range word { + if _, ok := cur.children[c]; !ok { + child := Constructor() + cur.children[c] = &child + cur = cur.children[c] + } else { + cur = cur.children[c] + } + } + cur.isWord = true +} + +func (this *PrefixTree) Search(word string) bool { + cur := this + for _, c := range word { + if _, ok := cur.children[c]; ok { + cur = cur.children[c] + } else { + return false + } + } + return cur.isWord +} + +func (this *PrefixTree) StartsWith(prefix string) bool { + cur := this + for _, c := range prefix { + if _, ok := cur.children[c]; ok { + cur = cur.children[c] + } else { + return false + } + } + + return cur != nil +} diff --git a/word-break/tedkimdev.go b/word-break/tedkimdev.go new file mode 100644 index 0000000000..e382241abb --- /dev/null +++ b/word-break/tedkimdev.go @@ -0,0 +1,67 @@ +// TC: O((n * t) + (m * t)) +// SC: O(n + (m * t)) +func wordBreak(s string, wordDict []string) bool { + trie := NewTrieNode() + maxLength := 0 + for _, word := range wordDict { + trie.Insert(word) + if len(word)> maxLength { + maxLength = len(word) + } + } + + dp := make([]bool, len(s)+1) + dp[len(s)] = true + + for i := len(s) - 1; i>= 0; i-- { + node := trie + for j := i; j < len(s) && j < i+maxLength; j++ { + c := s[j] + if _, ok := node.children[rune(c)]; !ok { + break + } + node = node.children[rune(c)] + + if node.isWord && dp[j+1] { + dp[i] = true + break + } + } + } + + return dp[0] +} + +type TrieNode struct { + children map[rune]*TrieNode + isWord bool +} + +func NewTrieNode() *TrieNode { + return &TrieNode{children: make(map[rune]*TrieNode)} +} + +func (t *TrieNode) Insert(word string) { + node := t + for _, char := range word { + if _, ok := node.children[char]; !ok { + node.children[char] = NewTrieNode() + } + node = node.children[char] + } + node.isWord = true +} + +// func (t *TrieNode) Search(s string, i, j int) bool { +// node := t +// for idx := i; idx <= j; idx++ { +// char := rune(s[idx]) +// if _, ok := node.children[char]; !ok { +// return false +// } +// node = node.children[char] +// } +// return node.isWord +// } + + From 628bc9e37541319fa077a3ac7677397e59928aa7 Mon Sep 17 00:00:00 2001 From: junzero741 Date: Wed, 1 Apr 2026 21:50:12 +0900 Subject: [PATCH 215/526] =?UTF-8?q?encode-and-decode-string=20=ED=92=80?= =?UTF-8?q?=EC=9D=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- encode-and-decode-strings/junzero741.ts | 102 ++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 encode-and-decode-strings/junzero741.ts diff --git a/encode-and-decode-strings/junzero741.ts b/encode-and-decode-strings/junzero741.ts new file mode 100644 index 0000000000..6740969cc9 --- /dev/null +++ b/encode-and-decode-strings/junzero741.ts @@ -0,0 +1,102 @@ +/** + * Because the string may contain any of the 256 legal ASCII characters, your algorithm must be able to handle any character that may appear + * + * Example 1: + * Input: ["lint","code","love","you"] + * Output: ["lint","code","love","you"] + * Explanation: + * One possible encode method is: "lint:;code:;love:;you" + * + * Example 2: + * Input: ["we", "say", ":", "yes"] + * Output: ["we", "say", ":", "yes"] + * Explanation: + * One possible encode method is: "we:;say:;:::;yes" + * + * + * + * encode: + * result = "" + * loop strs, + * + * loop str, + * char to charCode + * not last str AND last char ? charCode + "*" + * not last str AND not last char ? charCode + "+" + * + * + * + * decode: + * strs = [] + * split str with "*", => ["12+79+NaN", "92+32"] + * split each element with "+", => [ ["12", "79", "NaN"], ["92", "32"] ] + * loop outer array, + * str = null + * loop inner array, + * element is "NaN" ? "" + * element is not "NaN" ? String.fromCharCode(Number(element)) + * str += + * str is not null ? strs.push(str) + * + */ + +// TC: O(N) +// SC: O(N) +class Solution { + encode (strs: string[]): string { + return strs.map((str) => { + if(str.length === 0) { + return "EMPTY" + } + const codes = []; + for(let i = 0; i < str.length; i++) { + codes.push(str.charCodeAt(i)); + } + return codes.join('+'); + }).join("*") + + } + + decode(str: string): string[] { + if(str.length === 0) { + return []; + } + + return str.split("*").map((encodedStr) => { + if(encodedStr === "EMPTY") { + return ""; + } + + return encodedStr + .split("+") + .map((code) => String.fromCharCode(Number(code))) + .join(""); + }) + } +} +const solution = new Solution(); + + + +const tc = [ + ["lint","code","love","you"], // "72+79+80+94*12+34+56+78*" + ["we", "say", ":", "yes"], + ["", "a", "", "b"], // "NaN*74*NaN*75" + [";::''',,,,.....", ".....,,,,'''::;"], +] + +function runTc(tc: string[]): boolean { + const encoded = solution.encode(tc); + const decoded = solution.decode(encoded); + if(tc.length !== decoded.length) { + return false; + } + + return tc.every((el, idx) => el === decoded[idx]); +} + +const totalTc = tc.length; +const failedTc = tc.reduce((acc, cur) => runTc(cur) ? acc : acc+1, 0); + +console.log(`success: ${totalTc-failedTc}/${totalTc}`); + From b8602b84d6898c32d3eb67371451a16027c28e53 Mon Sep 17 00:00:00 2001 From: juhui Date: Thu, 2 Apr 2026 12:03:56 +0900 Subject: [PATCH 216/526] WEEK 05 Solutions --- .../juhui-jeong.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/juhui-jeong.java diff --git a/best-time-to-buy-and-sell-stock/juhui-jeong.java b/best-time-to-buy-and-sell-stock/juhui-jeong.java new file mode 100644 index 0000000000..2afdc7a2c7 --- /dev/null +++ b/best-time-to-buy-and-sell-stock/juhui-jeong.java @@ -0,0 +1,34 @@ +/* +시간복잡도: O(n2) +공간복잡도: O(1) +class Solution { + public int maxProfit(int[] prices) { + int maxStock = 0; + for(int i = 0; i < prices.length; i++) { + for (int j = 0; j < prices.length; j++) { + if (i <= j) break; + if (prices[i] - prices[j]> maxStock) { + maxStock = prices[i] - prices[j]; + } + } + } + return maxStock; + } +} + */ +// 시간복잡도: O(n) +// 공간복잡도: O(1) +class Solution { + public int maxProfit(int[] prices) { + int maxStock = 0; + int minPrice = prices[0]; + for (int price : prices) { + if (price < minPrice) { + minPrice = price; + } else { + maxStock = Math.max(price - minPrice, maxStock); + } + } + return maxStock; + } +} From f1aa488cce2ce198b2cadd931c92e4d13e3aa82d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: Thu, 2 Apr 2026 14:59:21 +0900 Subject: [PATCH 217/526] add solution for best time to buy and sell stock problem --- best-time-to-buy-and-sell-stock/gcount85.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/gcount85.py diff --git a/best-time-to-buy-and-sell-stock/gcount85.py b/best-time-to-buy-and-sell-stock/gcount85.py new file mode 100644 index 0000000000..238bf8cf5a --- /dev/null +++ b/best-time-to-buy-and-sell-stock/gcount85.py @@ -0,0 +1,21 @@ +""" +# Approach +지금까지의 최저 가격을 갱신함과 동시에 최선의 이익도 업데이트합니다. + +# Complexity +- Time complexity: O(N) + +- Space complexity: O(1) +""" + + +class Solution: + def maxProfit(self, prices: list[int]) -> int: + min_price = float("inf") + answer = 0 + + for price in prices: + min_price = min(min_price, price) + answer = max(answer, price - min_price) + + return answer From 4230e0b4eb3ccc869a4e7a2f9aa3a003b18ad78a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: Thu, 2 Apr 2026 15:13:28 +0900 Subject: [PATCH 218/526] add solution for grouping anagrams --- group-anagrams/gcount85.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 group-anagrams/gcount85.py diff --git a/group-anagrams/gcount85.py b/group-anagrams/gcount85.py new file mode 100644 index 0000000000..65d4890ddd --- /dev/null +++ b/group-anagrams/gcount85.py @@ -0,0 +1,21 @@ +""" +# Approach +strs 배열을 순회하며 문자열을 정규화(정렬)하고, +정규화 값이 같은 원소들끼리 모이도록 딕셔너리에 추가하여 최종 값을 반환한다. + +# Complexity +strs의 길이를 N, 문자열의 길이를 K라고 할 때, + +- Time complexity: O(N*KlogK) +- Space complexity: O(N*K) +""" + +from collections import defaultdict + + +class Solution: + def groupAnagrams(self, strs: list[str]) -> list[list[str]]: + anagram = defaultdict(list) # normalized str : str list + for s in strs: + anagram["".join(sorted(s))].append(s) + return list(anagram.values()) From e9eb1c431a66d5962aa3b9a6e94f74a7a1ca2a85 Mon Sep 17 00:00:00 2001 From: jla670 Date: Thu, 2 Apr 2026 01:02:14 -0700 Subject: [PATCH 219/526] group anagrams solution --- group-anagrams/jylee2033.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 group-anagrams/jylee2033.py diff --git a/group-anagrams/jylee2033.py b/group-anagrams/jylee2033.py new file mode 100644 index 0000000000..120e9cc5ba --- /dev/null +++ b/group-anagrams/jylee2033.py @@ -0,0 +1,14 @@ +class Solution: + def groupAnagrams(self, strs: List[str]) -> List[List[str]]: + anagram_map = {} + for word in strs: + key = "".join(sorted(word)) + if key not in anagram_map: + anagram_map[key] = [word] + else: + anagram_map[key].append(word) + + return list(anagram_map.values()) + +# Time Complexity: O(N * K log K), N - number of strings, K - maximum length of a string (for sorting) +# Space Complexity: O(N * K) From 635fcd7b9d6d620cf0740479982cb889c3ee2f03 Mon Sep 17 00:00:00 2001 From: hyerijung Date: Thu, 2 Apr 2026 21:25:48 +0900 Subject: [PATCH 220/526] workd-break solution --- word-break/hyeri0903.java | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 word-break/hyeri0903.java diff --git a/word-break/hyeri0903.java b/word-break/hyeri0903.java new file mode 100644 index 0000000000..810f012a9a --- /dev/null +++ b/word-break/hyeri0903.java @@ -0,0 +1,32 @@ +class Solution { + public boolean wordBreak(String s, List wordDict) { + /** + 1.문제: s 가 wordDict 로 쪼개질 수 있는지 true/false return + 2.조건 + - s 에는 wordDict 가 여러번 나올 수 있음. + - s.length() 최소 = 1, 최대 300 + - wordDict.size() 최소 1, 최대 1000 + - 한 단어 길이 최소=1, 최대 = 20 + - 모두 소문자. 모든 wordDict 값은 unique + 3.풀이 + - i번째까지 문자열을 만들 수 있는지 check + */ + + int n = s.length(); + boolean[] dp = new boolean[n+1]; + + dp[0] = true; //빈 문자열인 경우 + + for(int i = 1; i < n+1; i++) { + for(int j = 0; j < i; j++) { + String subStr = s.substring(j, i); + //앞단계 모두 만들 수 있고 && wordDict에 존재하는지 체크 + if(dp[j] && wordDict.contains(subStr)) { + dp[i] = true; + break; + } + } + } + return dp[n]; + } +} From 427ed1ce334277b7c08acbd01df923dffdececf5 Mon Sep 17 00:00:00 2001 From: hyerijung Date: Thu, 2 Apr 2026 21:37:09 +0900 Subject: [PATCH 221/526] encode-and-decode-strings solution --- encode-and-decode-strings/hyeri0903.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 encode-and-decode-strings/hyeri0903.py diff --git a/encode-and-decode-strings/hyeri0903.py b/encode-and-decode-strings/hyeri0903.py new file mode 100644 index 0000000000..d2f0c43da7 --- /dev/null +++ b/encode-and-decode-strings/hyeri0903.py @@ -0,0 +1,24 @@ +class Solution: + """ + @param: strs: a list of strings + @return: encodes a list of strings to a single string. + """ + def encode(self, strs: List[str]): + text = "" + for str in strs: + text += f"{len(str)}:{str}" + return text + + """ + @param: str: A string + @return: decodes a single string to a list of strings + """ + def decode(self, s: str): + output = [] + start = 0 + while start < len(s): + mid = s.find(":", start) + length = int(s[start:mid]) + output.append(s[mid + 1 : mid + 1 + length]) + start = mid + 1 + length + return output From d9a4fc92df9b31dec2ebf23ebca42fc558241e51 Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: Fri, 3 Apr 2026 13:07:30 +0900 Subject: [PATCH 222/526] sadie100: add 1 solution --- best-time-to-buy-and-sell-stock/sadie100.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/sadie100.ts diff --git a/best-time-to-buy-and-sell-stock/sadie100.ts b/best-time-to-buy-and-sell-stock/sadie100.ts new file mode 100644 index 0000000000..6073439a8f --- /dev/null +++ b/best-time-to-buy-and-sell-stock/sadie100.ts @@ -0,0 +1,21 @@ +/* +prices를 순회하며 현재 최저값과의 차이를 구해서 최대 profit을 갱신한 뒤 최저값(구매가)를 갱신, 최종값을 리턴한다 + +시간복잡도 O(N) - N은 prices의 length +*/ + +function maxProfit(prices: number[]): number { + let buy + let result = 0 + + for (let price of prices) { + if (buy === undefined) { + buy = price + continue + } + result = Math.max(result, price - buy) + buy = Math.min(price, buy) + } + + return result +} From e7a77c7befe1aa51724ad98358cfb81908d73e5c Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: Fri, 3 Apr 2026 14:29:19 +0900 Subject: [PATCH 223/526] implement trie prefix tree solution --- implement-trie-prefix-tree/robinyoon-dev.js | 66 +++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 implement-trie-prefix-tree/robinyoon-dev.js diff --git a/implement-trie-prefix-tree/robinyoon-dev.js b/implement-trie-prefix-tree/robinyoon-dev.js new file mode 100644 index 0000000000..ca89a183eb --- /dev/null +++ b/implement-trie-prefix-tree/robinyoon-dev.js @@ -0,0 +1,66 @@ +var TrieNode = function () { + this.children = {}; + this.isEnd = false; +} + +var Trie = function () { + this.root = new TrieNode(); +}; + +/** + * @param {string} word + * @return {void} + */ +Trie.prototype.insert = function (word) { + let currentNode = this.root; + for (let i = 0; i < word.length; i++) { + let char = word[i]; + if (!currentNode.children[char]) { + currentNode.children[char] = new TrieNode(); + + } + currentNode = currentNode.children[char]; + } + + currentNode.isEnd = true; +}; + +/** + * @param {string} word + * @return {boolean} + */ +Trie.prototype.search = function (word) { + let currentNode = this.root; + for (let i = 0; i < word.length; i++) { + let char = word[i]; + if (!currentNode.children[char]) { + return false; + } + currentNode = currentNode.children[char]; + } + return currentNode.isEnd; +}; + +/** + * @param {string} prefix + * @return {boolean} + */ +Trie.prototype.startsWith = function (prefix) { + let currentNode = this.root; + for (let i = 0; i < prefix.length; i++) { + let char = prefix[i]; + if (!currentNode.children[char]) { + return false; + } + currentNode = currentNode.children[char]; + } + return true; +}; + +/** + * Your Trie object will be instantiated and called as such: + * var obj = new Trie() + * obj.insert(word) + * var param_2 = obj.search(word) + * var param_3 = obj.startsWith(prefix) + */ From dafa5ee9c7578daf3d25318bc092c39ba539b2ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: Fri, 3 Apr 2026 15:36:45 +0900 Subject: [PATCH 224/526] add solution for word break problem --- word-break/gcount85.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 word-break/gcount85.py diff --git a/word-break/gcount85.py b/word-break/gcount85.py new file mode 100644 index 0000000000..ef5e4f014b --- /dev/null +++ b/word-break/gcount85.py @@ -0,0 +1,35 @@ +""" +# Intuition +wordDict를 word들의 길이로 분류하고, +s의 각 위치까지의 문자열을 완성할 수 있는지 dp 배열로 확인합니다. + +# Complexity +wordDict의 길이를 N, s의 길이를 K +- Time complexity: O(N+K) +- Space complexity: O(N+K) +""" + +from collections import defaultdict + + +class Solution: + def wordBreak(self, s: str, wordDict: list[str]) -> bool: + n = len(s) + dp = [False] * (n + 1) + word_dict = defaultdict(set) + for word in wordDict: + word_dict[len(word)].add(word) + + dp[0] = True + for i in range(1, n + 1): + for ( + k, + v, + ) in word_dict.items(): + if i + k - 1> n: + continue + if dp[i - 1] == False: + continue + if s[i - 1 : i + k - 1] in v: + dp[i + k - 1] = True + return dp[n] From 6adf92bf163c1e37d37e2d2a6a46365ec391aeb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: Fri, 3 Apr 2026 16:13:34 +0900 Subject: [PATCH 225/526] Add Implement Trie solution --- implement-trie-prefix-tree/gcount85.py | 41 ++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 implement-trie-prefix-tree/gcount85.py diff --git a/implement-trie-prefix-tree/gcount85.py b/implement-trie-prefix-tree/gcount85.py new file mode 100644 index 0000000000..764e78800a --- /dev/null +++ b/implement-trie-prefix-tree/gcount85.py @@ -0,0 +1,41 @@ +class TrieNode: + def __init__(self): + self.children = {} + self.is_end = False + + +class Trie: + + def __init__(self): + self.root = TrieNode() + + def insert(self, word: str) -> None: + node = self.root + for ch in word: + if ch not in node.children: + node.children[ch] = TrieNode() + node = node.children[ch] + node.is_end = True + + def search(self, word: str) -> bool: + node = self.root + for ch in word: + if ch not in node.children: + return False + node = node.children[ch] + return node.is_end + + def startsWith(self, prefix: str) -> bool: + node = self.root + for ch in prefix: + if ch not in node.children: + return False + node = node.children[ch] + return True + + +# Your Trie object will be instantiated and called as such: +# obj = Trie() +# obj.insert(word) +# param_2 = obj.search(word) +# param_3 = obj.startsWith(prefix) From 478d56d33cdd6fbc2ef583e126fad93e34305ed6 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Fri, 3 Apr 2026 14:48:11 +0900 Subject: [PATCH 226/526] [7th batch] week 5 - best time to buy and sell stock --- best-time-to-buy-and-sell-stock/liza0525.py | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/best-time-to-buy-and-sell-stock/liza0525.py b/best-time-to-buy-and-sell-stock/liza0525.py index 02d00761fd..9d69945a04 100644 --- a/best-time-to-buy-and-sell-stock/liza0525.py +++ b/best-time-to-buy-and-sell-stock/liza0525.py @@ -23,3 +23,25 @@ def maxProfit(self, prices: List[int]) -> int: # 최종적으로 기록된 max_profit이 답 return max_profit + + +# 7기 풀이 +# 시간 복잡도: O(n) +# - prices의 길이 n만큼 순회 +# 공간 복잡도: O(1) +# - 상수만 사용 +class Solution: + # 첫날부터 매일의 가격이 최소인지, 최대인지를 판단하여 가장 큰 이익을 낼 수 있는 값을 계산한다. + # 첫날부터 시간 순서대로 확인해야 함(기간 중 가장 최댓값이 가장 최솟값보다 빠를 수도 있기 때문) + def maxProfit(self, prices: List[int]) -> int: + min_sell_price = 10 ** 4 # 문제 조건에서 10의 4승이 최대라고 하여 이를 min_sell_price의 초기값으로 + max_profit = 0 + + for price in prices: + # 매일 순회하며 지나간 시간들 중에 가장 작은 price인지 확인하여 업데이트 + min_sell_price = min(min_sell_price, price) + + # 매일 순회하며 오늘 얻을 수 있는 profit과 이전에 얻었던 max_profit을 비교하여 업데이트 + max_profit = max(max_profit, price - min_sell_price) + + return max_profit From 7426ef7524bf20cf6ce7e194a1cef684a65c94de Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Fri, 3 Apr 2026 15:39:00 +0900 Subject: [PATCH 227/526] [7th batch] week 5 - encode and decode strings --- encode-and-decode-strings/liza0525.py | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 encode-and-decode-strings/liza0525.py diff --git a/encode-and-decode-strings/liza0525.py b/encode-and-decode-strings/liza0525.py new file mode 100644 index 0000000000..b804cb7d6f --- /dev/null +++ b/encode-and-decode-strings/liza0525.py @@ -0,0 +1,28 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - 인코딩 디코딩 모두 문자열 리스트의 길이에 따라 시간 복잡도가 결정됨 +# 공간 복잡도: O(1) +# - 정답 변수인 res를 제외하고는 변수만 쓰임 + + +DELIMITER = "^" + + +class Solution: + def encode(self, strs): + # DELIMITER를 사이에 두고 단어의 글자 수와 단어를 concat해서 저장한다. + # 예) ["cat", "is", "cute"] -> "3^cat2^is4^cute" + # 이렇게 해야 글자 수를 예측하고 split하기 쉬워진다. + return "".join(map(lambda x: f"{len(x)}{DELIMITER}{x}", strs)) + + def decode(self, s): + res = [] + i = 0 + while i < len(s): + # i번째 글자로부터 첫번째 DELIMITER가 나오는 인덱스를 j라고 칭함 + j = s.index(DELIMITER, i) + word_len = int(s[i:j]) # DELIMITER 앞의 글자는 '글자 수'이므로 int로 변환 + word = s[j + 1:j + word_len + 1] # i번째부터 글자 수 만큼 잘라서 word를 찾음 + res.append(word) + i = j + word_len + 1 # 자른 이후의 index를 새로운 i로 설정하여 다음 글자 찾음 + return res From 38fb272f4a2c30a4f5cbc0968d6d0af5bd93a2c9 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Fri, 3 Apr 2026 15:42:11 +0900 Subject: [PATCH 228/526] [7th batch] week 5 - group anagrams --- group-anagrams/liza0525.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 group-anagrams/liza0525.py diff --git a/group-anagrams/liza0525.py b/group-anagrams/liza0525.py new file mode 100644 index 0000000000..fe6ee203dd --- /dev/null +++ b/group-anagrams/liza0525.py @@ -0,0 +1,19 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - 입력 받은 strs 리스트의 길이 만큼 순회하므로 +# 공간 복잡도: O(1) +# - 결과로 반환할 result를 제외하고는 변수만 사용 +from collections import defaultdict + + +class Solution: + def groupAnagrams(self, strs: List[str]) -> List[List[str]]: + result = defaultdict(list) + + for str_ in strs: + # 아나그램의 key를 동일하게 만든다. 갖고 있는 문자열의 오름차순 결과를 key로 만듦 + anagram_key = "".join(sorted(list(str_))) + # 같은 key를 가진 것끼리 리스트로 묶어둔다. + result[anagram_key].append(str_) + + return list(result.values()) From ef0e0330d793f5bc0881bf9076841b30382c9e79 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Fri, 3 Apr 2026 15:48:28 +0900 Subject: [PATCH 229/526] [7th batch] week 5 - implement trie prefix tree --- implement-trie-prefix-tree/liza0525.py | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 implement-trie-prefix-tree/liza0525.py diff --git a/implement-trie-prefix-tree/liza0525.py b/implement-trie-prefix-tree/liza0525.py new file mode 100644 index 0000000000..88bee443ca --- /dev/null +++ b/implement-trie-prefix-tree/liza0525.py @@ -0,0 +1,45 @@ +# 7기 풀이 +# Trie 전체 공간 복잡도: 공간: O(n * m) +# - n은 단어 수, m은 평균 단어 길이 +# 각 메서드 마다 시간 복잡도와 공간 복잡도 작성 +class Node: + def __init__(self, val=None): + self.children = {} # 자식 노드를 담을 dictionary + self.is_end = False # 현재 노드를 끝으로 하는 단어가 저장되었는지에 대한 flag + + +class Trie: + def __init__(self): + self.root = Node() + + def insert(self, word: str) -> None: + # 시간: O(m) — m은 word의 길이, 문자 하나씩 순회 + # 공간: O(m) — 최악의 경우 m개의 새 노드 생성 (아무것도 공유 안할 때) + node = self.root + for s in word: + if s not in node.children: # 아직 저장이 되지 않은 문자라면 children에 노드로써 저장해둔다. + node.children[s] = Node(s) + node = node.children[s] # 다음 노드를 children node로 지정하여 후손까지 저장할 수 있도록 함 + node.is_end = True # 모든 노드를 저장한 후에는 단어의 끝을 알리도록 is_end를 True로 변경 + + def search(self, word: str) -> bool: + # 시간: O(m) — m은 word/prefix의 길이만큼 순회 + # 공간: O(1) — 새 노드 생성 없이 포인터만 이동 + node = self.root + for s in word: + if s not in node.children: # 찾으려는 단어의 문자가 저장되어 있지 않으면 search 실패이므로 False 반환 + return False + node = node.children[s] + + return node.is_end # 끝까지 돌아보고 해당 단어의 끝이 저장되어 있는지 아닌지를 반환하므로써 search의 성패 여부를 확인할 수 있음 + + def startsWith(self, prefix: str) -> bool: + # start with의 경우에는, search와 거의 로직이 동일하나, is_end의 여부를 볼 필요가 없으므로 모든 문자에 대한 search가 끝나면 무조건 True 반환 + node = self.root + for s in prefix: + if s not in node.children: + return False + node = node.children[s] + + return True + From da5597a3b86f590ad51030fbeb6fbf263e3399ed Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Fri, 3 Apr 2026 16:03:02 +0900 Subject: [PATCH 230/526] [7th batch] week 5 - word break --- word-break/liza0525.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 word-break/liza0525.py diff --git a/word-break/liza0525.py b/word-break/liza0525.py new file mode 100644 index 0000000000..ab3888ef59 --- /dev/null +++ b/word-break/liza0525.py @@ -0,0 +1,37 @@ +# 7기 풀이 +# 시간 복잡도: 시간복잡도: O(n * m) +# - n은 s의 길이, m은 wordDict의 평균 단어 길이 +# - 각 인덱스마다 wordDict를 순회하므로 +# 공간 복잡도: 공간복잡도: O(n) +# - memo에 최대 n개의 인덱스를 저장 +class Solution: + def wordBreak(self, s: str, wordDict: List[str]) -> bool: + memo = set() + + def dfs(i): + if i == len(s): + # i가 s의 길이가 되면 모든 탐색이 성공으로 끝났기 때문에 + # True로 반환 + return True + + memo.add(i) # 해당 인덱스에 대해서는 방문을 했기 때문에 memo + for word in wordDict: + if i + len(word) in memo: + # i + len(word)가 memoization해둔 인덱스라면 이미 성공한 케이스므로 통과 + continue + + if i + len(word)> len(s): + # i + len(word)가 len(s)보다 크면 탐색을 더이상 할 수 없으므로 continue + continue + + # 아직 방문을 하지 않은 index라면 단어를 slice하여 실제로 wordDict에 있는지 확인 + if s[i:i + len(word)] in wordDict: + # 다음 인덱스 i + len(word)로 dfs 탐색 + check = dfs(i + len(word)) + if check: + # 모든게 성공되었을 땐 True 반환 + return True + + return False + + return dfs(0) From 72a46d10c4f86ccb8415cc929a15b48c0cc3ebee Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: Fri, 3 Apr 2026 18:17:05 +0900 Subject: [PATCH 231/526] =?UTF-8?q?add:=20=EB=88=84=EB=9D=BD=EB=90=9C=20?= =?UTF-8?q?=EB=B3=80=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- best-time-to-buy-and-sell-stock/Cyjin-jani.js | 1 + 1 file changed, 1 insertion(+) diff --git a/best-time-to-buy-and-sell-stock/Cyjin-jani.js b/best-time-to-buy-and-sell-stock/Cyjin-jani.js index 9f844a76de..6885e33a40 100644 --- a/best-time-to-buy-and-sell-stock/Cyjin-jani.js +++ b/best-time-to-buy-and-sell-stock/Cyjin-jani.js @@ -22,6 +22,7 @@ const maxProfit_naive = function (prices) { const maxProfit = function (prices) { let buyIdx = 0; let sellIdx = 1; + let profit = 0; while (sellIdx < prices.length) { let buyPrice = prices[buyIdx]; From d2120555e299d7a649c2e657172fe75d42e5d68a Mon Sep 17 00:00:00 2001 From: hyerijung Date: Fri, 3 Apr 2026 19:31:06 +0900 Subject: [PATCH 232/526] implement-trie-prefix-tree solutions --- implement-trie-prefix-tree/hyeri0903.java | 68 +++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 implement-trie-prefix-tree/hyeri0903.java diff --git a/implement-trie-prefix-tree/hyeri0903.java b/implement-trie-prefix-tree/hyeri0903.java new file mode 100644 index 0000000000..1c1b6f2d57 --- /dev/null +++ b/implement-trie-prefix-tree/hyeri0903.java @@ -0,0 +1,68 @@ +class Trie { + class TrieNode { + TrieNode[] children; + boolean isEnd; + + public TrieNode() { + children = new TrieNode[26]; // a ~ z + isEnd = false; + } + } + + private TrieNode root; + + public Trie() { + root = new TrieNode(); + } + + public void insert(String word) { + TrieNode node = root; + + for(char c: word.toCharArray()) { + int index = c - 'a'; + //처음 들어오는 단어는 node 생성 + if(node.children[index] == null) { + node.children[index] = new TrieNode(); + } + //다음 노드로 이동 + node = node.children[index]; + } + //단어의 끝 표시 + node.isEnd = true; + } + + public boolean search(String word) { + TrieNode node = root; + for(char c: word.toCharArray()) { + int index = c - 'a'; + //존재하지 않으면 false return + if(node.children[index] == null) { + return false; + } + //다음 노드로 이동 + node = node.children[index]; + } + return node.isEnd; + } + + public boolean startsWith(String prefix) { + //중간에 null을 안만나면 true 반환 + TrieNode node = root; + for(char c: prefix.toCharArray()) { + int index = c - 'a'; + if(node.children[index] == null) { + return false; + } + node = node.children[index]; + } + return true; + } +} + +/** + * Your Trie object will be instantiated and called as such: + * Trie obj = new Trie(); + * obj.insert(word); + * boolean param_2 = obj.search(word); + * boolean param_3 = obj.startsWith(prefix); + */ From 30cb3a7c059c86746e741efaa12953b79ee67c98 Mon Sep 17 00:00:00 2001 From: Dia Date: Fri, 3 Apr 2026 20:10:36 +0900 Subject: [PATCH 233/526] feat: add solution for grouping anagrams --- best-time-to-buy-and-sell-stock/kangdaia.py | 20 ++++++++++++++++++ group-anagrams/kangdaia.py | 23 +++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/kangdaia.py create mode 100644 group-anagrams/kangdaia.py diff --git a/best-time-to-buy-and-sell-stock/kangdaia.py b/best-time-to-buy-and-sell-stock/kangdaia.py new file mode 100644 index 0000000000..ce6352533b --- /dev/null +++ b/best-time-to-buy-and-sell-stock/kangdaia.py @@ -0,0 +1,20 @@ +class Solution: + def maxProfit(self, prices: list[int]) -> int: + """ + 주식 가격 목록에서 최대 이익을 계산하는 함수. + + 시간 복잡도: O(N) + 공간 복잡도: O(1) + + Args: + prices (list[int]): 주식 가격 목록 + + Returns: + int: 최대 이익 + """ + min_price = prices[0] + max_profit = 0 + for price in prices[1:]: + max_profit = max(max_profit, price - min_price) + min_price = min(min_price, price) + return max_profit diff --git a/group-anagrams/kangdaia.py b/group-anagrams/kangdaia.py new file mode 100644 index 0000000000..dfaf60ad5f --- /dev/null +++ b/group-anagrams/kangdaia.py @@ -0,0 +1,23 @@ +class Solution: + def groupAnagrams(self, strs: list[str]) -> list[list[str]]: + """ + 단어 목록에서 애너그램끼리 그룹화해서, 그룹화된 단어 목록을 반환하는 함수. + + N은 단어의 개수, M은 단어의 최대 길이로 가정할 때, + 시간 복잡도: O(N * M log M) + 공간 복잡도: O(N * M) + + Args: + strs (list[str]): 단어 목록 + + Returns: + list[list[str]]: 애너그램 그룹화된 단어 목록 + """ + seen = dict() + for st in strs: + st_key = "".join(sorted(st)) + if st_key in seen: + seen[st_key].append(st) + else: + seen[st_key] = [st] + return list(seen.values()) From 151579c8bbccb4d1827bf4fa43a6741a5ca9c989 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: Fri, 3 Apr 2026 22:22:22 +0900 Subject: [PATCH 234/526] tried word-break. --- word-break/sangbeenmoon.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 word-break/sangbeenmoon.py diff --git a/word-break/sangbeenmoon.py b/word-break/sangbeenmoon.py new file mode 100644 index 0000000000..d580913361 --- /dev/null +++ b/word-break/sangbeenmoon.py @@ -0,0 +1,29 @@ +# 실패한 풀이. +# AC 를 받기는 했으나 test case 가 좀 더 촘촘했다면 TLE 에 걸렸을 것임. +# string 이 아닌 index 로 memoization 을 하는 걸 떠올려보자. + +class Solution: + answer = False + visited = {} + def wordBreak(self, s: str, wordDict: List[str]) -> bool: + + self.answer = False + self.visited = {} + self.go(0,s,wordDict) + + return self.answer + + def go(self, i:int, s: str, wordDict: List[str]): + if i>= (len(s)): + self.answer = True + return + + for word in wordDict: + if i + len(word)> len(s): + continue + + if word == s[i:i + len(word)]: + if not s[i + len(word) : ] in self.visited: + self.go(i + len(word), s, wordDict) + + self.visited[s[i:]] = False From e5cb04031e31282e9646a18a8667f8d10650ec9d Mon Sep 17 00:00:00 2001 From: Dia Date: Fri, 3 Apr 2026 22:25:00 +0900 Subject: [PATCH 235/526] feat: implement Trie data structure with insert, search, and startsWith methods --- implement-trie-prefix-tree/kangdaia.py | 60 ++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 implement-trie-prefix-tree/kangdaia.py diff --git a/implement-trie-prefix-tree/kangdaia.py b/implement-trie-prefix-tree/kangdaia.py new file mode 100644 index 0000000000..6a009f8bbd --- /dev/null +++ b/implement-trie-prefix-tree/kangdaia.py @@ -0,0 +1,60 @@ +class Node: + """ + Trie 자료구조의 노드를 나타내는 클래스. + + key: 노드의 키 (문자) + data: 노드에 저장된 데이터 (단어) + children: 자식 노드들을 저장함 (키: 문자, 값: Node 객체) + """ + def __init__(self, key, data=None): + self.key = key + self.data = data + self.children = {} + + +class Trie: + """ + Trie 자료구조를 구현한 클래스. + + head: Trie의 루트 노드 + + insert(word): 단어를 Trie에 삽입하는 메서드 + search(word): Trie에서 단어가 존재하는지 확인하는 메서드 + startsWith(prefix): Trie에서 접두사가 존재하는지 확인하는 메서드 + + - 시간 복잡도: O(M) (M은 단어의 길이) + - 공간 복잡도: O(N * M) (N은 단어의 개수, M은 단어의 최대 길이) + """ + def __init__(self): + self.head = Node(None) + + def insert(self, word: str) -> None: + curr = self.head + for char in word: + if char not in curr.children: + curr.children[char] = Node(char) + curr = curr.children[char] + curr.data = word + + def search(self, word: str) -> bool: + curr = self.head + for char in word: + if char not in curr.children: + return False + curr = curr.children[char] + return True if curr.data == word else False + + def startsWith(self, prefix: str) -> bool: + curr = self.head + for char in prefix: + if char not in curr.children: + return False + curr = curr.children[char] + return True + + +# Your Trie object will be instantiated and called as such: +# obj = Trie() +# obj.insert(word) +# param_2 = obj.search(word) +# param_3 = obj.startsWith(prefix) From 2f50432ec0ae649959ff072da352422e3453b6e5 Mon Sep 17 00:00:00 2001 From: jla670 Date: Fri, 3 Apr 2026 11:09:21 -0700 Subject: [PATCH 236/526] encode and decode strings solution --- encode-and-decode-strings/jylee2033.py | 58 ++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 encode-and-decode-strings/jylee2033.py diff --git a/encode-and-decode-strings/jylee2033.py b/encode-and-decode-strings/jylee2033.py new file mode 100644 index 0000000000..c11d44443e --- /dev/null +++ b/encode-and-decode-strings/jylee2033.py @@ -0,0 +1,58 @@ +class Solution: + """ + @param: strs: a list of strings + @return: encodes a list of strings to a single string. + """ + def encode(self, strs): + # write your code here + # Encode each word with its length prefix and a "#" + # ["C#", "&"] -> "2#C#1#&" + encoded_str = "" + + for word in strs: + encoded_str += f"{len(word)}#{word}" + + return encoded_str + + """ + @param: str: A string + @return: decodes a single string to a list of strings + """ + def decode(self, str): + # write your code here + # "2#C#1#&" -> ["C#", "&"] + decoded_lst = [] + char_count = 0 + reading_word = False + word = "" + length_str = "" + + if str == "": + return [""] + + for ch in str: + if ch == "#" and not reading_word: + # Finished reading the length prefix + # Switch to word-reading mode + char_count = int(length_str) + length_str = "" + reading_word = True + + elif not reading_word: + # Accumulate digits for the length prefix + length_str += ch + + else: + # reading_word is True + word += ch + char_count -= 1 + + if char_count == 0: + reading_word = False + decoded_lst.append(word) + word = "" + + return decoded_lst + +# Time Complexity: O(N) +# Space Complexity: O(N) From 2c75c1a82721de40b2d6e40325c0e170c2498656 Mon Sep 17 00:00:00 2001 From: juhui Date: Sat, 4 Apr 2026 10:30:06 +0900 Subject: [PATCH 237/526] WEEK 05 Solutions add --- group-anagrams/juhui-jeong.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 group-anagrams/juhui-jeong.java diff --git a/group-anagrams/juhui-jeong.java b/group-anagrams/juhui-jeong.java new file mode 100644 index 0000000000..5582fa19aa --- /dev/null +++ b/group-anagrams/juhui-jeong.java @@ -0,0 +1,21 @@ +/* +시간복잡도: O(k log k) +공간복잡도: O(n * k) +*/ +class Solution { + public List> groupAnagrams(String[] strs) { + Map> map = new HashMap(); + + for (String str: strs) { + char[] chars = str.toCharArray(); + Arrays.sort(chars); + String key = new String(chars); + + if (!map.containsKey(key)) { + map.put(key, new ArrayList()); + } + map.get(key).add(str); + } + return new ArrayList(map.values()); + } +} From 75a2e545d6426c54edd1c32e9cd50f147fbff3b4 Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: Sat, 4 Apr 2026 11:49:26 +0900 Subject: [PATCH 238/526] word break solution --- word-break/robinyoon-dev.js | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 word-break/robinyoon-dev.js diff --git a/word-break/robinyoon-dev.js b/word-break/robinyoon-dev.js new file mode 100644 index 0000000000..be9b73f534 --- /dev/null +++ b/word-break/robinyoon-dev.js @@ -0,0 +1,27 @@ +// 문풀 해설 보고 푼 문제 +/** + * @param {string} s + * @param {string[]} wordDict + * @return {boolean} + */ +var wordBreak = function (s, wordDict) { + + const dp = new Array(s.length + 1).fill(false); + dp[0] = true; + + let maxLength = 0; + for (let word of wordDict) { + maxLength = Math.max(maxLength, word.length); + } + + for (let i = 1; i <= s.length; i++) { + for (let j = Math.max(0, i - maxLength); j < i; j++) { + if (dp[j] && wordDict.includes(s.substring(j, i))) { + dp[i] = true; + break; + } + } + } + + return dp[s.length]; +}; From 367924409a15f9794cefbc693af9137fcbb9ebb4 Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: Sat, 4 Apr 2026 11:51:18 +0900 Subject: [PATCH 239/526] chore: add comment --- implement-trie-prefix-tree/robinyoon-dev.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/implement-trie-prefix-tree/robinyoon-dev.js b/implement-trie-prefix-tree/robinyoon-dev.js index ca89a183eb..20f86d866b 100644 --- a/implement-trie-prefix-tree/robinyoon-dev.js +++ b/implement-trie-prefix-tree/robinyoon-dev.js @@ -1,3 +1,5 @@ +// 문제풀이 해설 보고 푼 문제입니다. + var TrieNode = function () { this.children = {}; this.isEnd = false; From 802ddd791a2a09c50cf7bc9bc852f354cd02e450 Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: Sat, 4 Apr 2026 12:04:49 +0900 Subject: [PATCH 240/526] add solution for best time to buy and sell stock --- best-time-to-buy-and-sell-stock/Hyeri1ee.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/Hyeri1ee.java diff --git a/best-time-to-buy-and-sell-stock/Hyeri1ee.java b/best-time-to-buy-and-sell-stock/Hyeri1ee.java new file mode 100644 index 0000000000..757cac6ddb --- /dev/null +++ b/best-time-to-buy-and-sell-stock/Hyeri1ee.java @@ -0,0 +1,41 @@ +class Solution { + + + + + + //O(n)에 증가 한 경우 profitMax를 갱신시키며 판단 -> time limit + public int maxProfit(int[] prices) { + int profitMax = 0; + /* + for(int i=0; i< prices.length - 1; i++){ + int buy= prices[i]; + + + for(int d =i+1; d < prices.length; d++){ + int sellCandid = prices[d]; + if (sellCandid - buy> profitMax){ + profitMax = sellCandid - buy; + } + + } + }//end of for + + */ + + int priceMin = Integer.MAX_VALUE; + for(int i =0; i < prices.length; i++){ + if (prices[i] < priceMin){ + priceMin = prices[i]; + } + else{ + profitMax = Math.max(profitMax, prices[i] - priceMin); + } + } + + return profitMax; + + } + +} + From 1f581903b6883f8e421144a419c08e848577a00a Mon Sep 17 00:00:00 2001 From: yihyun-kim1 Date: Sat, 4 Apr 2026 14:17:06 +0900 Subject: [PATCH 241/526] add solution: word-break --- word-break/yihyun-kim1.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 word-break/yihyun-kim1.js diff --git a/word-break/yihyun-kim1.js b/word-break/yihyun-kim1.js new file mode 100644 index 0000000000..ca716981c5 --- /dev/null +++ b/word-break/yihyun-kim1.js @@ -0,0 +1,20 @@ +/** + * @param {string} s + * @param {string[]} wordDict + * @return {boolean} + */ +const wordBreak = (s, wordDict) => { + const dp = new Array(s.length + 1).fill(false); + dp[0] = true; + + for (let i = 1; i <= s.length; i++) { + for (const word of wordDict) { + const start = i - word.length; + if (start>= 0 && dp[start] && s.slice(start, i) === word) { + dp[i] = true; + } + } + } + + return dp[s.length]; +}; From 479a691f3359b22eeb6bf0198c743a90a037ee49 Mon Sep 17 00:00:00 2001 From: yihyun-kim1 Date: Sat, 4 Apr 2026 14:17:20 +0900 Subject: [PATCH 242/526] add solution: group-anagrams --- group-anagrams/yihyun-kim1.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 group-anagrams/yihyun-kim1.js diff --git a/group-anagrams/yihyun-kim1.js b/group-anagrams/yihyun-kim1.js new file mode 100644 index 0000000000..7b61ba4068 --- /dev/null +++ b/group-anagrams/yihyun-kim1.js @@ -0,0 +1,18 @@ +/** + * @param {string[]} strs + * @return {string[][]} + */ +const groupAnagrams = (strs) => { + const map = new Map(); + + for (const str of strs) { + const sorted = str.split("").sort().join(""); + + if (!map.has(sorted)) { + map.set(sorted, []); + } + map.get(sorted).push(str); + } + + return [...map.values()]; +}; From 2b976cde74193ea02fb078f34bdd11fda2e53d36 Mon Sep 17 00:00:00 2001 From: yihyun-kim1 Date: Sat, 4 Apr 2026 14:17:34 +0900 Subject: [PATCH 243/526] add solution: best-time-to-buy-and-sell-stock --- best-time-to-buy-and-sell-stock/yihyun-kim1.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/yihyun-kim1.js diff --git a/best-time-to-buy-and-sell-stock/yihyun-kim1.js b/best-time-to-buy-and-sell-stock/yihyun-kim1.js new file mode 100644 index 0000000000..a190dfeb69 --- /dev/null +++ b/best-time-to-buy-and-sell-stock/yihyun-kim1.js @@ -0,0 +1,15 @@ +/** + * @param {number[]} prices + * @return {number} + */ +const maxProfit = (prices) => { + let minPrice = prices[0]; + let maxProfit = 0; + + for (let i = 1; i < prices.length; i++) { + minPrice = Math.min(minPrice, prices[i]); + maxProfit = Math.max(maxProfit, prices[i] - minPrice); + } + + return maxProfit; +}; From f9fca83fda51aab1b77ef88a21dcf34ea44d4f94 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: Sat, 4 Apr 2026 16:31:20 +0900 Subject: [PATCH 244/526] =?UTF-8?q?5=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=205=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hwi-middle.cpp | 15 ++++ encode-and-decode-strings/hwi-middle.cpp | 33 +++++++++ group-anagrams/hwi-middle.cpp | 59 ++++++++++++++++ implement-trie-prefix-tree/hwi-middle.cpp | 68 +++++++++++++++++++ word-break/hwi-middle.cpp | 39 +++++++++++ 5 files changed, 214 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/hwi-middle.cpp create mode 100644 encode-and-decode-strings/hwi-middle.cpp create mode 100644 group-anagrams/hwi-middle.cpp create mode 100644 implement-trie-prefix-tree/hwi-middle.cpp create mode 100644 word-break/hwi-middle.cpp diff --git a/best-time-to-buy-and-sell-stock/hwi-middle.cpp b/best-time-to-buy-and-sell-stock/hwi-middle.cpp new file mode 100644 index 0000000000..9a493b9e22 --- /dev/null +++ b/best-time-to-buy-and-sell-stock/hwi-middle.cpp @@ -0,0 +1,15 @@ +class Solution { +public: + int maxProfit(vector& prices) { + int res = 0; + int minPrice = prices[0]; + int len = prices.size(); + for (int i = 0; i < len; ++i) + { + res = max(res, prices[i] - minPrice); + minPrice = min(minPrice, prices[i]); + } + + return res; + } +}; diff --git a/encode-and-decode-strings/hwi-middle.cpp b/encode-and-decode-strings/hwi-middle.cpp new file mode 100644 index 0000000000..934c715282 --- /dev/null +++ b/encode-and-decode-strings/hwi-middle.cpp @@ -0,0 +1,33 @@ +class Codec { +public: + + // Encodes a list of strings to a single string. + string encode(vector& strs) { + string str; + for(auto& s : strs) + { + str += s; + str.push_back(3); + } + + return str; + } + + // Decodes a single string to a list of strings. + vector decode(string s) { + vector v; + v.reserve(200); + string str_buf; + istringstream iss(s); + while (getline(iss, str_buf, (char)3)) + { + v.push_back(str_buf); + } + + return v; + } +}; + +// Your Codec object will be instantiated and called as such: +// Codec codec; +// codec.decode(codec.encode(strs)); diff --git a/group-anagrams/hwi-middle.cpp b/group-anagrams/hwi-middle.cpp new file mode 100644 index 0000000000..1d9badc1d1 --- /dev/null +++ b/group-anagrams/hwi-middle.cpp @@ -0,0 +1,59 @@ +class Solution { +private: + struct chnum + { + int cnt[26]; + + chnum() + { + memset(cnt, 0, sizeof(int) * 26); + } + + bool operator==(const chnum& other) const + { + for (int i = 0; i < 26; ++i) + { + if (this->cnt[i] != other.cnt[i]) return false; + } + return true; + } + }; + +struct chnumHash + { + size_t operator()(const chnum& key) const + { + size_t seed = 5381; + for (int i = 0; i < 26; ++i) + { + seed = ((seed << 5) + seed) + key.cnt[i]; + } + return seed; + } + }; + +public: + vector> groupAnagrams(vector& strs) { + unordered_map, chnumHash> ns; + for (auto& str : strs) + { + chnum n; + for (auto ch : str) + { + n.cnt[ch - 'a']++; + } + + ns[n].push_back(str); + } + + vector> v; + v.reserve(ns.size()); + + for (auto& p : ns) + { + v.push_back(move(p.second)); + } + + return v; + } +}; diff --git a/implement-trie-prefix-tree/hwi-middle.cpp b/implement-trie-prefix-tree/hwi-middle.cpp new file mode 100644 index 0000000000..32e946260a --- /dev/null +++ b/implement-trie-prefix-tree/hwi-middle.cpp @@ -0,0 +1,68 @@ +class Trie +{ +public: + Trie() + { + mRoot = make_unique(); + } + + void insert(string word) + { + Node* curNode = mRoot.get(); + for (char c : word) + { + auto& child = curNode->children[c - 'a']; + if (child == nullptr) + { + child = make_unique(); + } + + curNode = child.get(); + } + + curNode->isWord = true; + } + + bool search(string word) + { + Node* curNode = mRoot.get(); + for (char c : word) + { + auto& child = curNode->children[c - 'a']; + if (child == nullptr) + { + return false; + } + + curNode = child.get(); + } + + return curNode->isWord; + } + + bool startsWith(string prefix) + { + Node* curNode = mRoot.get(); + for (char c : prefix) + { + auto& child = curNode->children[c - 'a']; + if (child == nullptr) + { + return false; + } + + curNode = child.get(); + } + + return true; + } + +private: + struct Node + { + bool isWord = false; + unique_ptr children[26]; + }; + + unique_ptr mRoot; +}; diff --git a/word-break/hwi-middle.cpp b/word-break/hwi-middle.cpp new file mode 100644 index 0000000000..1f7ada6ed0 --- /dev/null +++ b/word-break/hwi-middle.cpp @@ -0,0 +1,39 @@ +class Solution { +public: + bool wordBreak(string s, vector& wordDict) { + this->s = s; + return solve(0, wordDict); + } + + bool solve(int start, vector& wordDict) + { + if (memo.contains(start)) + { + return memo[start]; + } + + if (start == s.size()) + { + return true; + } + + for (auto& str : wordDict) + { + if (s.substr(start, str.size()) == str) + { + if (solve(start + str.size(), wordDict)) + { + memo[start] = true; + return true; + } + } + } + + memo[start] = false; + return false; + } + +private: + string s; + unordered_map memo; +}; From b49044937a4b57be701f4c634738397ff5b25dd3 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: Sat, 4 Apr 2026 16:36:02 +0900 Subject: [PATCH 245/526] =?UTF-8?q?=EB=8B=B5=EC=95=88=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- best-time-to-buy-and-sell-stock/hwi-middle.cpp | 4 ++-- encode-and-decode-strings/hwi-middle.cpp | 6 +----- group-anagrams/hwi-middle.cpp | 7 ++++--- implement-trie-prefix-tree/hwi-middle.cpp | 4 ++-- word-break/hwi-middle.cpp | 9 ++++++++- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/best-time-to-buy-and-sell-stock/hwi-middle.cpp b/best-time-to-buy-and-sell-stock/hwi-middle.cpp index 9a493b9e22..99916b5079 100644 --- a/best-time-to-buy-and-sell-stock/hwi-middle.cpp +++ b/best-time-to-buy-and-sell-stock/hwi-middle.cpp @@ -6,8 +6,8 @@ class Solution { int len = prices.size(); for (int i = 0; i < len; ++i) { - res = max(res, prices[i] - minPrice); - minPrice = min(minPrice, prices[i]); + res = max(res, prices[i] - minPrice); // 수익 최대화: 지금까지 가장 쌌던 날에 사서 오늘 팔기 + minPrice = min(minPrice, prices[i]); // '지금까지 가장 쌌던 날' 업데이트 } return res; diff --git a/encode-and-decode-strings/hwi-middle.cpp b/encode-and-decode-strings/hwi-middle.cpp index 934c715282..e40f0db658 100644 --- a/encode-and-decode-strings/hwi-middle.cpp +++ b/encode-and-decode-strings/hwi-middle.cpp @@ -7,7 +7,7 @@ class Codec { for(auto& s : strs) { str += s; - str.push_back(3); + str.push_back(3); // 문제의 입력으로 오지 않는 값(ETX, End of Text)을 구분자로 사용 } return str; @@ -27,7 +27,3 @@ class Codec { return v; } }; - -// Your Codec object will be instantiated and called as such: -// Codec codec; -// codec.decode(codec.encode(strs)); diff --git a/group-anagrams/hwi-middle.cpp b/group-anagrams/hwi-middle.cpp index 1d9badc1d1..8731cde484 100644 --- a/group-anagrams/hwi-middle.cpp +++ b/group-anagrams/hwi-middle.cpp @@ -1,5 +1,6 @@ class Solution { private: + // 단어별로 알파벳 개수를 세는 구조체 struct chnum { int cnt[26]; @@ -34,16 +35,16 @@ struct chnumHash public: vector> groupAnagrams(vector& strs) { - unordered_map, chnumHash> ns; + unordered_map, chnumHash> ns; // 알파벳 개수를 넣으면 알파벳 구성을 갖는 문자열 배열이 나옴 for (auto& str : strs) { chnum n; for (auto ch : str) { - n.cnt[ch - 'a']++; + n.cnt[ch - 'a']++; // 알파벳 개수를 세고... } - ns[n].push_back(str); + ns[n].push_back(str); // 해시맵에 넣음 } vector> v; diff --git a/implement-trie-prefix-tree/hwi-middle.cpp b/implement-trie-prefix-tree/hwi-middle.cpp index 32e946260a..15ee3233a9 100644 --- a/implement-trie-prefix-tree/hwi-middle.cpp +++ b/implement-trie-prefix-tree/hwi-middle.cpp @@ -60,8 +60,8 @@ class Trie private: struct Node { - bool isWord = false; - unique_ptr children[26]; + bool isWord = false; // 이 노드가 단어의 끝인지 저장 + unique_ptr children[26]; // 자식 노드 저장 }; unique_ptr mRoot; diff --git a/word-break/hwi-middle.cpp b/word-break/hwi-middle.cpp index 1f7ada6ed0..e9ab14d091 100644 --- a/word-break/hwi-middle.cpp +++ b/word-break/hwi-middle.cpp @@ -5,13 +5,16 @@ class Solution { return solve(0, wordDict); } + // substr 시작 인덱스와 wordDict를 입력으로 받음 bool solve(int start, vector& wordDict) { + // 이미 계산한 적 있으면 메모이제이션으로 해결 if (memo.contains(start)) { return memo[start]; } + // 베이스컨디션 -> 끝까지 도달했으면 true if (start == s.size()) { return true; @@ -19,21 +22,25 @@ class Solution { for (auto& str : wordDict) { + // wordDict에 있는 단어들로 시작하는지 확인 if (s.substr(start, str.size()) == str) { + // 그리고 그 뒷 부분도 재귀를 통해 확인 if (solve(start + str.size(), wordDict)) { + // 뒷 부분까지 통과했으면 true memo[start] = true; return true; } } } + // 통과 못했으면 false memo[start] = false; return false; } private: string s; - unordered_map memo; + unordered_map memo; // 메모이제이션 }; From ab8ab3f934f1b350b0e1fa9cef3cc58c1699aea8 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: Sat, 4 Apr 2026 17:25:48 +0900 Subject: [PATCH 246/526] solved best-time-to-buy... --- best-time-to-buy-and-sell-stock/sangbeenmoon.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/sangbeenmoon.py diff --git a/best-time-to-buy-and-sell-stock/sangbeenmoon.py b/best-time-to-buy-and-sell-stock/sangbeenmoon.py new file mode 100644 index 0000000000..2fe1894930 --- /dev/null +++ b/best-time-to-buy-and-sell-stock/sangbeenmoon.py @@ -0,0 +1,13 @@ +# TC : O(n) +# SC : O(1) + +class Solution: + def maxProfit(self, prices: List[int]) -> int: + answer = 0 + mm = 10001 + + for price in prices: + mm = min(mm, price) + answer = max(answer, price - mm) + + return answer From 01e0baedaeaea5341ceca11ee6a95f64cb780dc2 Mon Sep 17 00:00:00 2001 From: Dia Date: Sat, 4 Apr 2026 18:13:08 +0900 Subject: [PATCH 247/526] feat: implement word break solution to determine if a string can be segmented into words from a dictionary --- word-break/kangdaia.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 word-break/kangdaia.py diff --git a/word-break/kangdaia.py b/word-break/kangdaia.py new file mode 100644 index 0000000000..b063601c19 --- /dev/null +++ b/word-break/kangdaia.py @@ -0,0 +1,26 @@ +class Solution: + def wordBreak(self, s: str, wordDict: list[str]) -> bool: + """ + 주어진 문자열 s를 단어 사전 wordDict의 단어들로 분할할 수 있는지 여부를 판단하는 함수. + N은 문자열 s의 길이, M은 단어 사전의 최대 단어 길이로 가정할 때, + 시간 복잡도: O(N * M) + 공간 복잡도: O(N) + + Args: + s (str): 주어진 문자열 + wordDict (list[str]): 사용가능한 단어 사전 + + Returns: + bool: 주어진 문자열을 단어 사전의 단어들로 분할할 수 있는지 여부 + """ + word_check = [False] * (len(s) + 1) + max_len = len(max(wordDict, key=len)) + word_check[0] = True + for i in range(len(s)): + if not word_check[i]: + continue + for j in range(i + 1, min(len(s), i + max_len) + 1): + # i까지의 단어가 사전에 있고, i부터 j까지의 단어가 사전에 있으면 모든 단어가 사전에 있는 상태로 판단 + if word_check[i] and s[i:j] in wordDict: + word_check[j] = True + return word_check[-1] From 4e7811fb97304781070100b5dda9b594121ffe71 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: Sat, 4 Apr 2026 18:35:26 +0900 Subject: [PATCH 248/526] solved implement-trie-prefix-tree. --- implement-trie-prefix-tree/sangbeenmoon.java | 57 ++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 implement-trie-prefix-tree/sangbeenmoon.java diff --git a/implement-trie-prefix-tree/sangbeenmoon.java b/implement-trie-prefix-tree/sangbeenmoon.java new file mode 100644 index 0000000000..67c598f6b3 --- /dev/null +++ b/implement-trie-prefix-tree/sangbeenmoon.java @@ -0,0 +1,57 @@ +import java.util.HashMap; +import java.util.Map; + +class Trie { + + Map map; + boolean isEnd = false; + + public Trie() { + map = new HashMap(); + } + + public void insert(String word) { + Trie trie; + if (map.containsKey(word.charAt(0))) { + trie = map.get(word.charAt(0)); + } else { + trie = new Trie(); + } + map.put(word.charAt(0), trie); + + if (word.length() == 1) { + map.get(word.charAt(0)).isEnd = true; + return; + } + + trie.insert(word.substring(1)); + } + + public boolean search(String word) { + if (map.containsKey(word.charAt(0))) { + if (word.length() == 1) { + return map.get(word.charAt(0)).isEnd; + } + return map.get(word.charAt(0)).search(word.substring(1)); + } + return false; + } + + public boolean startsWith(String prefix) { + if (map.containsKey(prefix.charAt(0))) { + if (prefix.length() == 1) { + return true; + } + return map.get(prefix.charAt(0)).startsWith(prefix.substring(1)); + } + return false; + } +} + +/** + * Your Trie object will be instantiated and called as such: + * Trie obj = new Trie(); + * obj.insert(word); + * boolean param_2 = obj.search(word); + * boolean param_3 = obj.startsWith(prefix); + */ From a7790ff66ec451aac05d99f1aee071840ee6af93 Mon Sep 17 00:00:00 2001 From: Dia Date: Sat, 4 Apr 2026 19:19:35 +0900 Subject: [PATCH 249/526] feat: add encode and decode functions for string manipulation --- encode-and-decode-strings/kangdaia.py | 37 +++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 encode-and-decode-strings/kangdaia.py diff --git a/encode-and-decode-strings/kangdaia.py b/encode-and-decode-strings/kangdaia.py new file mode 100644 index 0000000000..5cce3b6120 --- /dev/null +++ b/encode-and-decode-strings/kangdaia.py @@ -0,0 +1,37 @@ +class Solution: + def encode(self, strs: list[str]) -> str: + """ + 인코딩 함수 + 방식: %를 사용해 문자열의 길이 + % + 문자열로 인코딩 + + Args: + strs (list[str]): 인코딩할 문자열 목록 + + Returns: + str: 인코딩된 문자열 + """ + return "".join(f"{len(s)}%{s}" for s in strs) + + def decode(self, s: str) -> list[str]: + """ + 디코딩 함수 + 시간복잡도: O(N) + + Args: + s (str): 디코딩할 문자열 + + Returns: + list[str]: 디코딩된 문자열 목록 + """ + res = [] + i = 0 + while i < len(s): + j = i + while s[j] != "%": + j += 1 + length = int(s[i:j]) + start = j + 1 + end = start + length + res.append(s[start:end]) + i = end + return res From 27c1b4a7b5399b981ebc9c80e1605f7115c9fa93 Mon Sep 17 00:00:00 2001 From: reeseo3o Date: Sat, 4 Apr 2026 21:34:09 +0900 Subject: [PATCH 250/526] week5: group-anagrams --- group-anagrams/reeseo3o.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 group-anagrams/reeseo3o.js diff --git a/group-anagrams/reeseo3o.js b/group-anagrams/reeseo3o.js new file mode 100644 index 0000000000..f666480337 --- /dev/null +++ b/group-anagrams/reeseo3o.js @@ -0,0 +1,19 @@ +/** + * TC: O(n * k log k) — 각 단어(k) 정렬 ×ばつ n개 + * SC: O(n * k) + */ +const groupAnagrams = (strs) => { + const map = new Map(); + + for (const str of strs) { + const key = str.split("").sort().join(""); + + if (!map.has(key)) { + map.set(key, []); + } + + map.get(key).push(str); + } + + return Array.from(map.values()); +}; From 12a0147e0a93cccad3316d5abae34e5b20fa9cda Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: Sat, 4 Apr 2026 21:57:44 +0900 Subject: [PATCH 251/526] =?UTF-8?q?feat:=20if/else=20=EB=AC=B8=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- best-time-to-buy-and-sell-stock/gyeo-ri.py | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/gyeo-ri.py diff --git a/best-time-to-buy-and-sell-stock/gyeo-ri.py b/best-time-to-buy-and-sell-stock/gyeo-ri.py new file mode 100644 index 0000000000..cbb852925d --- /dev/null +++ b/best-time-to-buy-and-sell-stock/gyeo-ri.py @@ -0,0 +1,30 @@ +class Solution: + def maxProfit(self, prices: list[int]) -> int: + max_profit = 0 + buy_at = None + + for p in prices: + if buy_at is None: + buy_at = p + elif buy_at> p: + buy_at = p + elif buy_at < p: + max_profit = max(max_profit, p - buy_at) + + return max_profit + + +if __name__ == "__main__": + test_cases = [ + ([7, 1, 5, 3, 6, 4], 5), + ([7, 6, 4, 3, 1], 0), + ([2, 4, 1], 2), + ] + + solution = Solution() + for idx, case_ in enumerate(test_cases): + prices, answer = case_ + result = solution.maxProfit(prices) + assert ( + answer == result + ), f"Test Case {idx} Failed: Expected {answer}, Got {result}" From ecc9423ba106064e22a4b06f8473c2c139fb4252 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: Sat, 4 Apr 2026 22:19:27 +0900 Subject: [PATCH 252/526] =?UTF-8?q?fix:=20=EC=84=B1=EB=8A=A5=EC=9D=80=20?= =?UTF-8?q?=EB=B9=84=EC=8A=B7=ED=95=98=EB=82=98=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20=EA=B0=84=EC=86=8C=ED=99=94=ED=95=9C=20=EB=B2=84?= =?UTF-8?q?=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- best-time-to-buy-and-sell-stock/gyeo-ri.py | 25 +++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/best-time-to-buy-and-sell-stock/gyeo-ri.py b/best-time-to-buy-and-sell-stock/gyeo-ri.py index cbb852925d..8834e7dbb1 100644 --- a/best-time-to-buy-and-sell-stock/gyeo-ri.py +++ b/best-time-to-buy-and-sell-stock/gyeo-ri.py @@ -1,17 +1,25 @@ +""" +[결과 요약] +# 시도한 로직 수: 4 + 1. if/else 문으로 분기 처리(시간: O(n) / 공간: O(1)) + - + 2. if문 대신 min / max를 계속 계산하는 로식 + - None 대신 float(inf)를 사용하여 None 검증 분기 제거 + - inf 사용을 위해서 마지막 return에 int() 타입 변환 필요 + - 성능은 1과 큰 차이 없으며 코드가 간소화 +""" + + class Solution: def maxProfit(self, prices: list[int]) -> int: max_profit = 0 - buy_at = None + min_price = float("inf") for p in prices: - if buy_at is None: - buy_at = p - elif buy_at> p: - buy_at = p - elif buy_at < p: - max_profit = max(max_profit, p - buy_at) + min_price = min(min_price, p) + max_profit = max(max_profit, p - min_price) - return max_profit + return int(max_profit) if __name__ == "__main__": @@ -19,6 +27,7 @@ def maxProfit(self, prices: list[int]) -> int: ([7, 1, 5, 3, 6, 4], 5), ([7, 6, 4, 3, 1], 0), ([2, 4, 1], 2), + ([1, 2, 4, 10000, 2, 1, 3], 9999), ] solution = Solution() From 5cf7923d52ec72f9ec27771d8fd5af7164c4a9d0 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: Sat, 4 Apr 2026 22:20:19 +0900 Subject: [PATCH 253/526] =?UTF-8?q?fix:=20=EC=8B=9C=EB=8F=84=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- best-time-to-buy-and-sell-stock/gyeo-ri.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/best-time-to-buy-and-sell-stock/gyeo-ri.py b/best-time-to-buy-and-sell-stock/gyeo-ri.py index 8834e7dbb1..776d59e4fc 100644 --- a/best-time-to-buy-and-sell-stock/gyeo-ri.py +++ b/best-time-to-buy-and-sell-stock/gyeo-ri.py @@ -1,6 +1,6 @@ """ [결과 요약] -# 시도한 로직 수: 4 +# 시도한 로직 수: 2 1. if/else 문으로 분기 처리(시간: O(n) / 공간: O(1)) - 2. if문 대신 min / max를 계속 계산하는 로식 From b2768a10a649170c32664615c5440ff8cf42c986 Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: Sat, 4 Apr 2026 22:26:18 +0900 Subject: [PATCH 254/526] add solution for group anagrams --- group-anagrams/Hyeri1ee.java | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 group-anagrams/Hyeri1ee.java diff --git a/group-anagrams/Hyeri1ee.java b/group-anagrams/Hyeri1ee.java new file mode 100644 index 0000000000..d5fec4a6e2 --- /dev/null +++ b/group-anagrams/Hyeri1ee.java @@ -0,0 +1,30 @@ +import java.util.*; + +class Solution { + //static HashMap< + public List> groupAnagrams(String[] strs) { + HashMap> map = new HashMap(); + + for(int w = 0 ;w < strs.length; w++){ + String word = strs[w]; + char[] arr = word.toCharArray(); + + //정렬한거 + Arrays.sort(arr); + String newWord = new String(arr); + + map.putIfAbsent(newWord, new ArrayList()); + map.get(newWord).add(word); + + } + + + List> list = new ArrayList(); + for(List group : map.values()){ + list.add(group); + } + + return list; + } +} + From 3f7066f13d9cb664f1904a28b4ac90cf943c500d Mon Sep 17 00:00:00 2001 From: Dohyeon Ju Date: Sun, 5 Apr 2026 04:14:30 +0900 Subject: [PATCH 255/526] Solution For Best Time to Buy And Sell Stock #221 --- best-time-to-buy-and-sell-stock/dohyeon2.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/dohyeon2.java diff --git a/best-time-to-buy-and-sell-stock/dohyeon2.java b/best-time-to-buy-and-sell-stock/dohyeon2.java new file mode 100644 index 0000000000..05372e352a --- /dev/null +++ b/best-time-to-buy-and-sell-stock/dohyeon2.java @@ -0,0 +1,24 @@ +class Solution { + // TC : O(n) + // SC : O(1) + public int maxProfit(int[] prices) { + int maximumProfit = 0; + int cursor = 0; + + // 전체를 순회하면서 이익을 검증 + for(int i = 0; i < prices.length; i++){ + int profit = prices[i] - prices[cursor]; + + // 만약 현재 값이 커서의 값보다 더 작다면 현재 값부터 비교하기 시작 + if(profit < 0){ + cursor = i; + continue; + } + + // 이전에 커서로 추정한 값이 높더라도 Math.max로 보존됨 + maximumProfit = Math.max(profit, maximumProfit); + } + + return maximumProfit; + } +} From 4d39357337638b941b6c99a8006183e722e3dcce Mon Sep 17 00:00:00 2001 From: jla670 Date: Sat, 4 Apr 2026 12:23:23 -0700 Subject: [PATCH 256/526] update maxProfit --- best-time-to-buy-and-sell-stock/jylee2033.py | 23 ++++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/best-time-to-buy-and-sell-stock/jylee2033.py b/best-time-to-buy-and-sell-stock/jylee2033.py index 0c39acca9d..063bb8dae2 100644 --- a/best-time-to-buy-and-sell-stock/jylee2033.py +++ b/best-time-to-buy-and-sell-stock/jylee2033.py @@ -8,18 +8,23 @@ def maxProfit(self, prices: List[int]) -> int: profit = 0 # Iterate through prices - for i, price in enumerate(prices): + # for i, price in enumerate(prices): + # if price < buy: + # buy = price + # + # for j in range(i + 1, len(prices)): + # if prices[j] <= buy: + # continue + # + # if prices[j] - buy> profit: + # profit = prices[j] - buy + for price in prices: if price < buy: buy = price - - for j in range(i + 1, len(prices)): - if prices[j] <= buy: - continue - - if prices[j] - buy> profit: - profit = prices[j] - buy + elif price - buy> profit: + profit = price - buy return profit -# Time Complexity: O(n^2) +# Time Complexity: O(n) # Space Complexity: O(1) From 466f3be43dee59f2e3068ecdef1015dc80889f59 Mon Sep 17 00:00:00 2001 From: jla670 Date: Sat, 4 Apr 2026 12:26:03 -0700 Subject: [PATCH 257/526] update maxProfit --- best-time-to-buy-and-sell-stock/jylee2033.py | 23 ++++++++------------ 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/best-time-to-buy-and-sell-stock/jylee2033.py b/best-time-to-buy-and-sell-stock/jylee2033.py index 063bb8dae2..0c39acca9d 100644 --- a/best-time-to-buy-and-sell-stock/jylee2033.py +++ b/best-time-to-buy-and-sell-stock/jylee2033.py @@ -8,23 +8,18 @@ def maxProfit(self, prices: List[int]) -> int: profit = 0 # Iterate through prices - # for i, price in enumerate(prices): - # if price < buy: - # buy = price - # - # for j in range(i + 1, len(prices)): - # if prices[j] <= buy: - # continue - # - # if prices[j] - buy> profit: - # profit = prices[j] - buy - for price in prices: + for i, price in enumerate(prices): if price < buy: buy = price - elif price - buy> profit: - profit = price - buy + + for j in range(i + 1, len(prices)): + if prices[j] <= buy: + continue + + if prices[j] - buy> profit: + profit = prices[j] - buy return profit -# Time Complexity: O(n) +# Time Complexity: O(n^2) # Space Complexity: O(1) From 6aadb4bba5d6d7c4c1cbf0983e23c095bddf0b83 Mon Sep 17 00:00:00 2001 From: soobing Date: Sun, 5 Apr 2026 10:29:06 +0900 Subject: [PATCH 258/526] feat: best-time-to-buy-and-sell-stock --- best-time-to-buy-and-sell-stock/soobing3.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/soobing3.ts diff --git a/best-time-to-buy-and-sell-stock/soobing3.ts b/best-time-to-buy-and-sell-stock/soobing3.ts new file mode 100644 index 0000000000..373f8fec06 --- /dev/null +++ b/best-time-to-buy-and-sell-stock/soobing3.ts @@ -0,0 +1,15 @@ +function maxProfit(prices: number[]): number { + let left = 0; + let right = 1; + let max = 0; + + while(left < right && right < prices.length) { + if(prices[right] - prices[left]> 0) { + max = Math.max(max, prices[right] - prices[left]) + } else { + left = right; + } + right++; + } + return max; +}; From 61e5e54351f96cb3350ebb29b88ea07d34504452 Mon Sep 17 00:00:00 2001 From: soobing Date: Sun, 5 Apr 2026 10:38:50 +0900 Subject: [PATCH 259/526] feat: group-anagrams --- group-anagrams/soobing3.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 group-anagrams/soobing3.ts diff --git a/group-anagrams/soobing3.ts b/group-anagrams/soobing3.ts new file mode 100644 index 0000000000..3763f3e452 --- /dev/null +++ b/group-anagrams/soobing3.ts @@ -0,0 +1,10 @@ +function groupAnagrams(strs: string[]): string[][] { + const map = new Map(); + + for(const str of strs) { + const key = str.split('').sort().join(''); + const value = map.get(key); + map.set(key, value ? [...value, str] : [str]) + } + return Array.from(map.values()); +}; From 00dd7c7f1b805d0026d13194380d34492ba7ec4a Mon Sep 17 00:00:00 2001 From: jla670 Date: Sat, 4 Apr 2026 20:18:30 -0700 Subject: [PATCH 260/526] update maxProfit --- best-time-to-buy-and-sell-stock/jylee2033.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/best-time-to-buy-and-sell-stock/jylee2033.py b/best-time-to-buy-and-sell-stock/jylee2033.py index 0c39acca9d..8e4c7e416f 100644 --- a/best-time-to-buy-and-sell-stock/jylee2033.py +++ b/best-time-to-buy-and-sell-stock/jylee2033.py @@ -8,18 +8,20 @@ def maxProfit(self, prices: List[int]) -> int: profit = 0 # Iterate through prices - for i, price in enumerate(prices): - if price < buy: - buy = price + for price in prices: + # if price < buy: + # buy = price - for j in range(i + 1, len(prices)): - if prices[j] <= buy: - continue + # for j in range(i + 1, len(prices)): + # if prices[j] <= buy: + # continue - if prices[j] - buy> profit: - profit = prices[j] - buy + # if prices[j] - buy> profit: + # profit = prices[j] - buy + buy = min(buy, price) + profit = max(profit, price - buy) return profit -# Time Complexity: O(n^2) +# Time Complexity: O(n) # Space Complexity: O(1) From 53ba8fc1e6ea3e26f71ab1c2c24f1cd6a76d05c1 Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: Sun, 5 Apr 2026 16:45:18 +0900 Subject: [PATCH 261/526] sadie100: group anagrams solution --- group-anagrams/sadie100.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 group-anagrams/sadie100.ts diff --git a/group-anagrams/sadie100.ts b/group-anagrams/sadie100.ts new file mode 100644 index 0000000000..34f94bc007 --- /dev/null +++ b/group-anagrams/sadie100.ts @@ -0,0 +1,30 @@ +/* +strs의 문자열들을 등장빈도를 바탕으로 계산한 특수 문자열로 전환하고 같은 것끼리 묶는다. + +시간복잡도 : O(N * K) - N은 strs의 개수, K는 strs의 길이. N 순회 안에 K 순회 +*/ + +function groupAnagrams(strs: string[]): string[][] { + const anagramMap = {} + const result = strs.reduce((acc, cur) => { + const charArray = new Array(26).fill(0) + + for (let char of cur) { + const charIdx = char.charCodeAt(0) - 'a'.charCodeAt(0) + charArray[charIdx] += 1 + } + + const sortedValue = charArray.join('#') + + const targetIdx = anagramMap[sortedValue] + if (targetIdx !== undefined) { + acc[targetIdx].push(cur) + } else { + anagramMap[sortedValue] = acc.length + acc.push([cur]) + } + return acc + }, []) + + return result +} From 86366c48d717f4a2f27256a25eae8b335d396402 Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: Sun, 5 Apr 2026 17:29:21 +0900 Subject: [PATCH 262/526] =?UTF-8?q?sadie100:=20find=20minimum=20in=20rotat?= =?UTF-8?q?ed=20sorted=20array=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sadie100.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/sadie100.ts diff --git a/find-minimum-in-rotated-sorted-array/sadie100.ts b/find-minimum-in-rotated-sorted-array/sadie100.ts new file mode 100644 index 0000000000..645ec0b993 --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/sadie100.ts @@ -0,0 +1,28 @@ +/** +이분탐색으로 정렬 탐색. 최소값이 들어있는 범위를 바탕으로 계속 좁혀 간다 +중간값을 기준값으로 잡고, 마지막 값보다 큰지 작은지 확인한다 + 기준값이 마지막 값보다 작을 경우, 최소값은 왼쪽 반쪽에 있거나 기준값임. ex) 5 1 2 3 4 + -> range를 왼쪽 반쪽으로 줄이고(기준값 포함) 해당 중간값을 기준값으로 잡는다 + 기준값이 마지막 값보다 클 경우, 최소값은 오른쪽 반쪽에 있음. ex) 3 4 5 1 2 + -> range를 오른쪽 반쪽으로 줄이고 해당 중간값을 기준값으로 잡는다 + +최종적으로 start, end가 같아지는 값이 최소값이 된다. + +시간복잡도 : O(LogN) -> N은 nums의 개수. 이분탐색 + */ + +function findMin(nums: number[]): number { + let start = 0 + let end = nums.length - 1 + + while (start < end) { + let target = Math.floor((start + end) / 2) + if (nums[target] < nums[end]) { + end = target + } else { + start = target + 1 + } + } + + return nums[start] +} From 7161650d6f437450de992b7a5164627718a9adff Mon Sep 17 00:00:00 2001 From: soobing Date: Sun, 5 Apr 2026 20:39:22 +0900 Subject: [PATCH 263/526] feat: encode-and-decode-strings --- encode-and-decode-strings/soobing3.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 encode-and-decode-strings/soobing3.ts diff --git a/encode-and-decode-strings/soobing3.ts b/encode-and-decode-strings/soobing3.ts new file mode 100644 index 0000000000..e1b8dc8d29 --- /dev/null +++ b/encode-and-decode-strings/soobing3.ts @@ -0,0 +1,25 @@ +class Solution { + /** + * @param {string[]} strs + * @returns {string} + */ + encode(strs) { + return strs.map((str) => `${str.length}#${str}`).join(''); + } + + /** + * @param {string} str + * @returns {string[]} + */ + decode(str) { + const result: string[] = []; + let i = 0; + while(i < str.length) { + const j = str.indexOf('#', i); + const length = Number(str.slice(i, j)); + result.push(str.slice(j + 1, j + 1 + length)); + i = j + 1 + length; + } + return result; + } +} From 58b8612bd30f132dbd2cbbfeb4bd76a556f89755 Mon Sep 17 00:00:00 2001 From: soobing Date: Sun, 5 Apr 2026 21:47:09 +0900 Subject: [PATCH 264/526] feat: implement-trie-prefix-tree --- implement-trie-prefix-tree/soobing3.ts | 52 ++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 implement-trie-prefix-tree/soobing3.ts diff --git a/implement-trie-prefix-tree/soobing3.ts b/implement-trie-prefix-tree/soobing3.ts new file mode 100644 index 0000000000..0343ccfbcb --- /dev/null +++ b/implement-trie-prefix-tree/soobing3.ts @@ -0,0 +1,52 @@ +class TrieNode { + children: Map; + isEnd: boolean; + constructor() { + this.children = new Map(); + this.isEnd = false + } +} +class Trie { + root: TrieNode; + + constructor() { + this.root = new TrieNode(); + } + + insert(word: string): void { + let node = this.root; + for(const ch of word) { + if(!node.children.has(ch)) { + node.children.set(ch, new TrieNode()); + } + node = node.children.get(ch)! + } + node.isEnd = true; + } + + search(word: string): boolean { + let node = this.root; + for(const ch of word) { + if(!node.children.has(ch)) return false; + node = node.children.get(ch)!; + } + return node.isEnd; + } + + startsWith(prefix: string): boolean { + let node = this.root; + for(const ch of prefix) { + if(!node.children.has(ch)) return false; + node = node.children.get(ch)!; + } + return true; + } +} + +/** +* Your Trie object will be instantiated and called as such: +* var obj = new Trie() +* obj.insert(word) +* var param_2 = obj.search(word) +* var param_3 = obj.startsWith(prefix) +*/ From 7f20e49d19a892d5cb9b6782f71995abd13c6691 Mon Sep 17 00:00:00 2001 From: soobing Date: Sun, 5 Apr 2026 21:59:34 +0900 Subject: [PATCH 265/526] feat: word-break --- word-break/soobing3.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 word-break/soobing3.ts diff --git a/word-break/soobing3.ts b/word-break/soobing3.ts new file mode 100644 index 0000000000..42e3b0743f --- /dev/null +++ b/word-break/soobing3.ts @@ -0,0 +1,15 @@ +function wordBreak(s: string, wordDict: string[]): boolean { + const dp = new Array(s.length + 1).fill(false); + dp[0] = true; + + for (let i = 1; i <= s.length; i++) { + for (let j = 0; j < i; j++) { + if (dp[j] && wordDict.includes(s.slice(j, i))) { + dp[i] = true; + break; + } + } + } + + return dp[s.length]; +}; From 85ef5696828ca3f49e829fbd63f969fa23d4ee42 Mon Sep 17 00:00:00 2001 From: jla670 Date: Sun, 5 Apr 2026 16:28:00 -0700 Subject: [PATCH 266/526] valid parentheses solution --- valid-parentheses/jylee2033.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 valid-parentheses/jylee2033.py diff --git a/valid-parentheses/jylee2033.py b/valid-parentheses/jylee2033.py new file mode 100644 index 0000000000..1cffb25248 --- /dev/null +++ b/valid-parentheses/jylee2033.py @@ -0,0 +1,25 @@ +class Solution: + def isValid(self, s: str) -> bool: + close_to_open = {')': '(', '}': '{', ']': '['} + stack = [] # Open brackets + + if len(s) % 2 == 1: + return False + + for ch in s: + # Open bracket + if ch in close_to_open.values(): + stack.append(ch) + # Close bracket + else: + if len(stack) == 0: + return False + + expected = close_to_open[ch] + if stack.pop() != expected: + return False + + return len(stack) == 0 + +# Time Complexity: O(n) +# Space Complexity: O(n) From e3571def0ed6b9169be65f1eeaa040d01f47c428 Mon Sep 17 00:00:00 2001 From: hyerijung Date: Mon, 6 Apr 2026 17:54:37 +0900 Subject: [PATCH 267/526] valid-parentheses solution --- valid-parentheses/hyeri0903.py | 37 ++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 valid-parentheses/hyeri0903.py diff --git a/valid-parentheses/hyeri0903.py b/valid-parentheses/hyeri0903.py new file mode 100644 index 0000000000..fd914442b9 --- /dev/null +++ b/valid-parentheses/hyeri0903.py @@ -0,0 +1,37 @@ +class Solution: + def isValid(self, s: str) -> bool: + ''' + 문제: string s 에 대해서 valid parentheses 이면 true 아니면 false + conditions + - open brackets must be closed by the same type + - // must be closed in the correct order + - s 최소 길이 = 1, 최대 10^4 + solution + - open brackets -> st array 에 저장, close brackets -> st.pop -> check valid + - 마지막에 st array length 가 1 이상이면 return False + + - time complexity: O(n) + - space complexity: O(n) + ''' + + st = [] + + for i in range(len(s)): + if s[i] == '(' or s[i] == '{' or s[i] == '[': + st.append(s[i]) + else: + # check if st is empty + if len(st) <= 0: + return False + cur = st.pop() + if s[i] == ')' and cur != '(': + return False + if s[i] == '}' and cur != '{': + return False + if s[i] == ']' and cur != '[': + return False + if len(st)> 0: + return False + return True + + \ No newline at end of file From d31ada6fb4457ed4b52f23e4804440956123557e Mon Sep 17 00:00:00 2001 From: hyerijung Date: Mon, 6 Apr 2026 18:41:33 +0900 Subject: [PATCH 268/526] longest-increasing-subsequence solution --- longest-increasing-subsequence/hyeri0903.py | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 longest-increasing-subsequence/hyeri0903.py diff --git a/longest-increasing-subsequence/hyeri0903.py b/longest-increasing-subsequence/hyeri0903.py new file mode 100644 index 0000000000..f87953236a --- /dev/null +++ b/longest-increasing-subsequence/hyeri0903.py @@ -0,0 +1,26 @@ +class Solution: + def lengthOfLIS(self, nums: List[int]) -> int: + ''' + 모르겠어서 풀이봤습니다 ᅮᅮ + 1.problem: 증가하는 가장 긴 subsequence length return (최장 증가 부분 수열) + 2.조건 + - nums array 길이 최소 1 , 최대 2500 + - 원소 값 음수 가능 + 3.풀이 + - dp : time complexity O(n^2) + dp[i] = i번째 원소를 마지막으로하는 LIS + dp[i] max(dp[i], dp[j]+1) 나 보다 작은 애들 중 가장 긴 LIS + 1 + ''' + + n = len(nums) + dp = [1] * (n) + + for i in range(n): + for j in range(i): + #앞 숫자 nums[j]가 지금 nums[i]보다 더 작은 경우 dp[i] update + if nums[j] < nums[i]: + dp[i] = max(dp[i], dp[j] + 1) + return max(dp) + + + \ No newline at end of file From 282d4db22bfb3349b12c6ac3dee95d87423ff70e Mon Sep 17 00:00:00 2001 From: soobing Date: Mon, 6 Apr 2026 21:19:15 +0900 Subject: [PATCH 269/526] feat: problem-categories.json --- problem-categories.json | 607 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 607 insertions(+) create mode 100644 problem-categories.json diff --git a/problem-categories.json b/problem-categories.json new file mode 100644 index 0000000000..e34dab8d19 --- /dev/null +++ b/problem-categories.json @@ -0,0 +1,607 @@ +{ + "3sum": { + "difficulty": "Medium", + "categories": [ + "Array", + "Two Pointers", + "Sorting" + ], + "intended_approach": "배열을 정렬한 뒤, 각 원소를 기준으로 투 포인터를 사용해 O(n2)으로 풀어야 합니다." + }, + "alien-dictionary": { + "difficulty": "Hard", + "categories": [ + "Graph", + "Topological Sort" + ], + "intended_approach": "인접한 단어 쌍에서 문자 순서 관계를 엣지로 추출하고, 위상 정렬(BFS/DFS)로 순서를 결정합니다." + }, + "best-time-to-buy-and-sell-stock": { + "difficulty": "Easy", + "categories": [ + "Array", + "Dynamic Programming" + ], + "intended_approach": "한 번의 순회로 최솟값을 추적하면서 현재 가격과의 차이를 계산합니다. O(n), O(1)." + }, + "binary-tree-level-order-traversal": { + "difficulty": "Medium", + "categories": [ + "Tree", + "BFS" + ], + "intended_approach": "큐를 사용한 BFS로 레벨별로 노드를 처리합니다." + }, + "binary-tree-maximum-path-sum": { + "difficulty": "Hard", + "categories": [ + "Tree", + "DFS", + "Dynamic Programming" + ], + "intended_approach": "DFS로 각 노드에서의 최대 gain을 계산하고, 좌우 자식을 포함한 경로 합을 전역 최댓값과 비교합니다." + }, + "climbing-stairs": { + "difficulty": "Easy", + "categories": [ + "Dynamic Programming" + ], + "intended_approach": "dp[i] = dp[i-1] + dp[i-2] 피보나치 점화식으로 풀어야 합니다." + }, + "clone-graph": { + "difficulty": "Medium", + "categories": [ + "Graph", + "BFS", + "DFS", + "Hash Table" + ], + "intended_approach": "HashMap으로 원본 노드와 복제 노드를 매핑하면서 BFS 또는 DFS로 순회합니다." + }, + "coin-change": { + "difficulty": "Medium", + "categories": [ + "Dynamic Programming" + ], + "intended_approach": "dp[i] = amount i를 만드는 최소 동전 수로 정의하고, Bottom-up DP로 풀어야 합니다." + }, + "combination-sum": { + "difficulty": "Medium", + "categories": [ + "Array", + "Backtracking" + ], + "intended_approach": "백트래킹으로 후보 목록을 탐색하고, 중복 사용을 허용하기 위해 현재 인덱스부터 재귀합니다." + }, + "construct-binary-tree-from-preorder-and-inorder-traversal": { + "difficulty": "Medium", + "categories": [ + "Tree", + "DFS", + "Hash Table" + ], + "intended_approach": "preorder의 첫 원소가 루트이고, inorder에서 루트 위치를 HashMap으로 O(1) 조회해 재귀적으로 트리를 구성합니다." + }, + "container-with-most-water": { + "difficulty": "Medium", + "categories": [ + "Array", + "Two Pointers", + "Greedy" + ], + "intended_approach": "양 끝에서 시작해 더 짧은 쪽 포인터를 이동하는 투 포인터로 O(n)에 풀어야 합니다." + }, + "contains-duplicate": { + "difficulty": "Easy", + "categories": [ + "Array", + "Hash Table" + ], + "intended_approach": "HashSet에 원소를 추가하면서 이미 존재하는지 확인합니다. O(n), O(n)." + }, + "counting-bits": { + "difficulty": "Easy", + "categories": [ + "Dynamic Programming", + "Bit Manipulation" + ], + "intended_approach": "dp[i] = dp[i>> 1] + (i & 1) 점화식을 활용해 O(n)으로 풀어야 합니다." + }, + "course-schedule": { + "difficulty": "Medium", + "categories": [ + "Graph", + "Topological Sort", + "DFS" + ], + "intended_approach": "방향 그래프에서 사이클 존재 여부를 DFS(색칠 기법) 또는 BFS 위상 정렬로 감지합니다." + }, + "decode-ways": { + "difficulty": "Medium", + "categories": [ + "Dynamic Programming" + ], + "intended_approach": "dp[i] = s[:i]를 디코딩하는 경우의 수로 정의하고, 1자리/2자리 해석 가능 여부에 따라 Bottom-up DP로 풀어야 합니다." + }, + "design-add-and-search-words-data-structure": { + "difficulty": "Medium", + "categories": [ + "Trie", + "DFS" + ], + "intended_approach": "Trie를 구현하고, '.' 와일드카드 처리를 위해 DFS로 모든 자식 노드를 탐색합니다." + }, + "encode-and-decode-strings": { + "difficulty": "Medium", + "categories": [ + "String" + ], + "intended_approach": "각 문자열 앞에 길이를 접두사로 붙이는 방식(예: '4#word')으로 구분자 충돌 없이 인코딩/디코딩합니다." + }, + "find-median-from-data-stream": { + "difficulty": "Hard", + "categories": [ + "Heap", + "Two Pointers" + ], + "intended_approach": "최대 힙(작은 절반)과 최소 힙(큰 절반)을 유지하며 중앙값을 O(log n)에 구합니다." + }, + "find-minimum-in-rotated-sorted-array": { + "difficulty": "Medium", + "categories": [ + "Array", + "Binary Search" + ], + "intended_approach": "이진 탐색으로 정렬된 절반을 판별해 O(log n)에 최솟값을 찾아야 합니다." + }, + "graph-valid-tree": { + "difficulty": "Medium", + "categories": [ + "Graph", + "Union-Find", + "DFS" + ], + "intended_approach": "Union-Find 또는 DFS로 사이클 여부를 확인하고, 모든 노드가 연결되어 있는지 검증합니다." + }, + "group-anagrams": { + "difficulty": "Medium", + "categories": [ + "Array", + "Hash Table", + "String" + ], + "intended_approach": "정렬된 문자열 또는 문자 카운팅 튜플을 HashMap의 키로 사용해 그룹핑합니다." + }, + "house-robber": { + "difficulty": "Medium", + "categories": [ + "Dynamic Programming" + ], + "intended_approach": "dp[i] = max(dp[i-1], dp[i-2] + nums[i]) 점화식으로 O(n), O(1) DP로 풀어야 합니다." + }, + "house-robber-ii": { + "difficulty": "Medium", + "categories": [ + "Dynamic Programming" + ], + "intended_approach": "원형 배열을 첫 집 포함/제외 두 경우로 분리해 house-robber를 두 번 실행합니다." + }, + "implement-trie-prefix-tree": { + "difficulty": "Medium", + "categories": [ + "Trie", + "Hash Table" + ], + "intended_approach": "각 노드가 자식 맵과 is_end 플래그를 갖는 Trie 자료구조를 직접 구현합니다." + }, + "insert-interval": { + "difficulty": "Medium", + "categories": [ + "Array" + ], + "intended_approach": "새 구간의 앞/겹치는/뒤 세 구역으로 나눠 선형 순회로 O(n)에 처리합니다." + }, + "invert-binary-tree": { + "difficulty": "Easy", + "categories": [ + "Tree", + "DFS", + "BFS" + ], + "intended_approach": "DFS 재귀 또는 BFS로 각 노드의 좌우 자식을 교환합니다." + }, + "jump-game": { + "difficulty": "Medium", + "categories": [ + "Array", + "Greedy" + ], + "intended_approach": "현재까지 도달 가능한 최대 인덱스를 추적하는 Greedy로 O(n)에 풀어야 합니다." + }, + "kth-smallest-element-in-a-bst": { + "difficulty": "Medium", + "categories": [ + "Tree", + "DFS" + ], + "intended_approach": "BST의 중위 순회(In-order traversal)는 오름차순이므로 k번째 원소가 정답입니다." + }, + "linked-list-cycle": { + "difficulty": "Easy", + "categories": [ + "Linked List", + "Two Pointers" + ], + "intended_approach": "플로이드 사이클 감지(빠른/느린 포인터)로 O(n), O(1)에 풀어야 합니다." + }, + "longest-common-subsequence": { + "difficulty": "Medium", + "categories": [ + "Dynamic Programming" + ], + "intended_approach": "2D DP 테이블 dp[i][j] = text1[:i]와 text2[:j]의 LCS 길이로 풀어야 합니다." + }, + "longest-consecutive-sequence": { + "difficulty": "Medium", + "categories": [ + "Array", + "Hash Table" + ], + "intended_approach": "HashSet에 모든 수를 넣고, 시퀀스 시작점(num-1이 없는 수)에서만 연속 길이를 셉니다. O(n)." + }, + "longest-increasing-subsequence": { + "difficulty": "Medium", + "categories": [ + "Dynamic Programming", + "Binary Search" + ], + "intended_approach": "O(n log n)은 이진 탐색으로 patience sorting, O(n2)은 기본 DP로 풀어야 합니다." + }, + "longest-palindromic-substring": { + "difficulty": "Medium", + "categories": [ + "String", + "Dynamic Programming" + ], + "intended_approach": "각 문자(및 문자 사이)를 중심으로 확장하는 중심 확장법으로 O(n2), O(1)에 풀어야 합니다." + }, + "longest-repeating-character-replacement": { + "difficulty": "Medium", + "categories": [ + "String", + "Sliding Window" + ], + "intended_approach": "슬라이딩 윈도우로 윈도우 내 최다 빈도 문자를 추적하고, (window 크기 - 최다 빈도) ≤ k 조건을 유지합니다." + }, + "longest-substring-without-repeating-characters": { + "difficulty": "Medium", + "categories": [ + "String", + "Sliding Window", + "Hash Table" + ], + "intended_approach": "슬라이딩 윈도우 + HashMap으로 중복 문자 발생 시 왼쪽 포인터를 이동합니다. O(n)." + }, + "lowest-common-ancestor-of-a-binary-search-tree": { + "difficulty": "Medium", + "categories": [ + "Tree", + "DFS" + ], + "intended_approach": "BST 속성(p, q가 모두 왼쪽/오른쪽이면 내려가고, 분기되면 현재 노드가 LCA)을 활용해 재귀합니다." + }, + "maximum-depth-of-binary-tree": { + "difficulty": "Easy", + "categories": [ + "Tree", + "DFS", + "BFS" + ], + "intended_approach": "DFS 재귀로 max(left, right) + 1을 반환하거나 BFS로 레벨을 셉니다." + }, + "maximum-product-subarray": { + "difficulty": "Medium", + "categories": [ + "Dynamic Programming" + ], + "intended_approach": "음수 곱셈을 고려해 현재 최댓값과 최솟값을 동시에 추적하는 DP로 풀어야 합니다." + }, + "maximum-subarray": { + "difficulty": "Medium", + "categories": [ + "Dynamic Programming" + ], + "intended_approach": "카데인 알고리즘: 현재 합이 음수가 되면 초기화하는 방식으로 O(n), O(1)에 풀어야 합니다." + }, + "meeting-rooms": { + "difficulty": "Easy", + "categories": [ + "Array", + "Sorting" + ], + "intended_approach": "시작 시간 기준으로 정렬 후, 인접한 회의의 겹침 여부를 확인합니다." + }, + "meeting-rooms-ii": { + "difficulty": "Medium", + "categories": [ + "Array", + "Heap", + "Sorting" + ], + "intended_approach": "최소 힙으로 진행 중인 회의의 종료 시간을 관리하고, 새 회의가 시작될 때 가장 빨리 끝나는 회의와 비교합니다." + }, + "merge-intervals": { + "difficulty": "Medium", + "categories": [ + "Array", + "Sorting" + ], + "intended_approach": "시작 시간으로 정렬 후 선형 순회하며 이전 구간과 겹치면 병합합니다." + }, + "merge-k-sorted-lists": { + "difficulty": "Hard", + "categories": [ + "Linked List", + "Heap", + "Divide and Conquer" + ], + "intended_approach": "최소 힙(Priority Queue)에 각 리스트의 헤드를 넣고 순서대로 추출합니다. O(n log k)." + }, + "merge-two-sorted-lists": { + "difficulty": "Easy", + "categories": [ + "Linked List", + "Two Pointers" + ], + "intended_approach": "두 포인터로 작은 쪽을 연결하는 반복 또는 재귀로 풀어야 합니다." + }, + "minimum-window-substring": { + "difficulty": "Hard", + "categories": [ + "String", + "Sliding Window", + "Hash Table" + ], + "intended_approach": "슬라이딩 윈도우 + 문자 카운팅 HashMap으로, 조건 충족 시 윈도우를 줄이며 최솟값을 갱신합니다." + }, + "missing-number": { + "difficulty": "Easy", + "categories": [ + "Array", + "Bit Manipulation", + "Math" + ], + "intended_approach": "XOR(모든 수 XOR 인덱스) 또는 가우스 공식(n*(n+1)/2 - 합)으로 O(n), O(1)에 풀어야 합니다." + }, + "non-overlapping-intervals": { + "difficulty": "Medium", + "categories": [ + "Array", + "Greedy", + "Sorting" + ], + "intended_approach": "종료 시간 기준으로 정렬 후, Greedy로 겹치는 구간 중 종료 시간이 긴 쪽을 제거합니다." + }, + "number-of-1-bits": { + "difficulty": "Easy", + "categories": [ + "Bit Manipulation" + ], + "intended_approach": "n & (n-1)로 가장 낮은 1 비트를 제거하는 방식으로 set bit 수를 셉니다." + }, + "number-of-connected-components-in-an-undirected-graph": { + "difficulty": "Medium", + "categories": [ + "Graph", + "Union-Find", + "DFS" + ], + "intended_approach": "Union-Find 또는 DFS/BFS로 연결 컴포넌트 수를 셉니다." + }, + "number-of-islands": { + "difficulty": "Medium", + "categories": [ + "Graph", + "DFS", + "BFS" + ], + "intended_approach": "육지 셀을 발견하면 DFS/BFS로 연결된 육지를 모두 방문 처리하고 카운트합니다." + }, + "pacific-atlantic-water-flow": { + "difficulty": "Medium", + "categories": [ + "Graph", + "DFS", + "BFS" + ], + "intended_approach": "역방향으로 태평양/대서양 경계에서 DFS/BFS를 시작해 도달 가능한 셀의 교집합을 구합니다." + }, + "palindromic-substrings": { + "difficulty": "Medium", + "categories": [ + "String", + "Dynamic Programming" + ], + "intended_approach": "각 문자와 문자 사이를 중심으로 확장하는 중심 확장법으로 O(n2)에 팰린드롬 수를 셉니다." + }, + "product-of-array-except-self": { + "difficulty": "Medium", + "categories": [ + "Array" + ], + "intended_approach": "나눗셈 없이 prefix 곱 배열과 suffix 곱을 활용해 O(n), O(1) 추가 공간으로 풀어야 합니다." + }, + "remove-nth-node-from-end-of-list": { + "difficulty": "Medium", + "categories": [ + "Linked List", + "Two Pointers" + ], + "intended_approach": "빠른 포인터를 n+1 앞서 출발시키는 투 포인터로 한 번의 순회에 처리합니다." + }, + "reorder-list": { + "difficulty": "Medium", + "categories": [ + "Linked List", + "Two Pointers" + ], + "intended_approach": "중간 찾기(느린/빠른 포인터) → 후반 역전 → 교차 병합 세 단계로 풀어야 합니다." + }, + "reverse-bits": { + "difficulty": "Easy", + "categories": [ + "Bit Manipulation" + ], + "intended_approach": "비트를 하나씩 추출해 결과에 왼쪽으로 추가하는 비트 시프트 연산으로 풀어야 합니다." + }, + "reverse-linked-list": { + "difficulty": "Easy", + "categories": [ + "Linked List" + ], + "intended_approach": "prev/curr 포인터로 방향을 뒤집는 반복(O(1) 공간) 또는 재귀로 풀어야 합니다." + }, + "rotate-image": { + "difficulty": "Medium", + "categories": [ + "Array", + "Math" + ], + "intended_approach": "전치(Transpose) 후 각 행을 좌우 반전하면 O(1) 추가 공간으로 90도 회전됩니다." + }, + "same-tree": { + "difficulty": "Easy", + "categories": [ + "Tree", + "DFS" + ], + "intended_approach": "두 트리를 동시에 DFS 재귀로 순회하며 값과 구조를 비교합니다." + }, + "search-in-rotated-sorted-array": { + "difficulty": "Medium", + "categories": [ + "Array", + "Binary Search" + ], + "intended_approach": "이진 탐색에서 mid를 기준으로 좌/우 절반 중 정렬된 쪽을 판별해 탐색 범위를 줄입니다." + }, + "serialize-and-deserialize-binary-tree": { + "difficulty": "Hard", + "categories": [ + "Tree", + "BFS", + "DFS" + ], + "intended_approach": "BFS(레벨 순서) 또는 DFS 전위 순회로 직렬화하고, null 마커로 구조를 복원합니다." + }, + "set-matrix-zeroes": { + "difficulty": "Medium", + "categories": [ + "Array" + ], + "intended_approach": "첫 행/열을 마커 행으로 활용해 O(1) 추가 공간으로 풀어야 합니다." + }, + "spiral-matrix": { + "difficulty": "Medium", + "categories": [ + "Array", + "Simulation" + ], + "intended_approach": "상/하/좌/우 경계를 좁혀가며 시뮬레이션으로 순회합니다." + }, + "subtree-of-another-tree": { + "difficulty": "Easy", + "categories": [ + "Tree", + "DFS" + ], + "intended_approach": "각 노드에서 same-tree 판별 함수를 호출하는 DFS로 풀어야 합니다." + }, + "sum-of-two-integers": { + "difficulty": "Medium", + "categories": [ + "Bit Manipulation" + ], + "intended_approach": "XOR로 합(올림 없는 덧셈), AND 후 왼쪽 시프트로 올림을 계산하고 올림이 0이 될 때까지 반복합니다." + }, + "top-k-frequent-elements": { + "difficulty": "Medium", + "categories": [ + "Array", + "Hash Table", + "Heap" + ], + "intended_approach": "버킷 정렬(빈도를 인덱스로 사용)로 O(n)에 풀거나, 최소 힙으로 O(n log k)에 풀어야 합니다." + }, + "two-sum": { + "difficulty": "Easy", + "categories": [ + "Array", + "Hash Table" + ], + "intended_approach": "HashMap으로 target - nums[i]를 조회하며 한 번의 순회로 O(n)에 풀어야 합니다." + }, + "unique-paths": { + "difficulty": "Medium", + "categories": [ + "Dynamic Programming", + "Math" + ], + "intended_approach": "dp[i][j] = dp[i-1][j] + dp[i][j-1]로 2D DP, 또는 조합 C(m+n-2, m-1)으로 수학적으로 풀 수 있습니다." + }, + "valid-anagram": { + "difficulty": "Easy", + "categories": [ + "String", + "Hash Table" + ], + "intended_approach": "문자 카운팅 배열(26) 또는 HashMap으로 두 문자열의 빈도를 비교합니다." + }, + "valid-palindrome": { + "difficulty": "Easy", + "categories": [ + "String", + "Two Pointers" + ], + "intended_approach": "양 끝에서 시작하는 투 포인터로 영숫자만 비교합니다. O(n), O(1)." + }, + "valid-parentheses": { + "difficulty": "Easy", + "categories": [ + "Stack", + "String" + ], + "intended_approach": "스택을 사용해 여는 괄호를 push하고, 닫는 괄호가 나오면 스택 top과 대응 여부를 확인합니다." + }, + "validate-binary-search-tree": { + "difficulty": "Medium", + "categories": [ + "Tree", + "DFS" + ], + "intended_approach": "DFS로 각 노드에 유효 범위(min, max)를 전달하며 BST 조건을 검증합니다." + }, + "word-break": { + "difficulty": "Medium", + "categories": [ + "Dynamic Programming" + ], + "intended_approach": "dp[i] = s[:i]가 wordDict로 분리 가능한지 여부로 정의하고, Bottom-up DP로 O(n2)에 풀어야 합니다." + }, + "word-search": { + "difficulty": "Medium", + "categories": [ + "Graph", + "Backtracking" + ], + "intended_approach": "각 셀에서 DFS 백트래킹으로 탐색하고, 방문한 셀을 임시 마킹해 중복 방문을 방지합니다." + }, + "word-search-ii": { + "difficulty": "Hard", + "categories": [ + "Trie", + "Backtracking" + ], + "intended_approach": "단어 목록으로 Trie를 구성하고, 그리드를 DFS 백트래킹으로 탐색하며 Trie 노드와 함께 매칭합니다." + } +} From a76fd5cfcf3c34f77edab37b060888ff2b060d71 Mon Sep 17 00:00:00 2001 From: soobing Date: Mon, 6 Apr 2026 21:47:12 +0900 Subject: [PATCH 270/526] =?UTF-8?q?fix(categories):=20leetcode=20topics=20?= =?UTF-8?q?=EC=B0=B8=EA=B3=A0=20=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-categories.json | 244 ++++++++++++++++++++++++++++------------ 1 file changed, 170 insertions(+), 74 deletions(-) diff --git a/problem-categories.json b/problem-categories.json index e34dab8d19..9ecff41ddb 100644 --- a/problem-categories.json +++ b/problem-categories.json @@ -11,7 +11,11 @@ "alien-dictionary": { "difficulty": "Hard", "categories": [ - "Graph", + "Array", + "String", + "Depth-First Search", + "Breadth-First Search", + "Graph Theory", "Topological Sort" ], "intended_approach": "인접한 단어 쌍에서 문자 순서 관계를 엣지로 추출하고, 위상 정렬(BFS/DFS)로 순서를 결정합니다." @@ -28,40 +32,46 @@ "difficulty": "Medium", "categories": [ "Tree", - "BFS" + "Breadth-First Search", + "Binary Tree" ], "intended_approach": "큐를 사용한 BFS로 레벨별로 노드를 처리합니다." }, "binary-tree-maximum-path-sum": { "difficulty": "Hard", "categories": [ + "Dynamic Programming", "Tree", - "DFS", - "Dynamic Programming" + "Depth-First Search", + "Binary Tree" ], "intended_approach": "DFS로 각 노드에서의 최대 gain을 계산하고, 좌우 자식을 포함한 경로 합을 전역 최댓값과 비교합니다." }, "climbing-stairs": { "difficulty": "Easy", "categories": [ - "Dynamic Programming" + "Math", + "Dynamic Programming", + "Memoization" ], "intended_approach": "dp[i] = dp[i-1] + dp[i-2] 피보나치 점화식으로 풀어야 합니다." }, "clone-graph": { "difficulty": "Medium", "categories": [ - "Graph", - "BFS", - "DFS", - "Hash Table" + "Hash Table", + "Depth-First Search", + "Breadth-First Search", + "Graph Theory" ], "intended_approach": "HashMap으로 원본 노드와 복제 노드를 매핑하면서 BFS 또는 DFS로 순회합니다." }, "coin-change": { "difficulty": "Medium", "categories": [ - "Dynamic Programming" + "Array", + "Dynamic Programming", + "Breadth-First Search" ], "intended_approach": "dp[i] = amount i를 만드는 최소 동전 수로 정의하고, Bottom-up DP로 풀어야 합니다." }, @@ -76,9 +86,11 @@ "construct-binary-tree-from-preorder-and-inorder-traversal": { "difficulty": "Medium", "categories": [ + "Array", + "Hash Table", + "Divide and Conquer", "Tree", - "DFS", - "Hash Table" + "Binary Tree" ], "intended_approach": "preorder의 첫 원소가 루트이고, inorder에서 루트 위치를 HashMap으로 O(1) 조회해 재귀적으로 트리를 구성합니다." }, @@ -95,7 +107,8 @@ "difficulty": "Easy", "categories": [ "Array", - "Hash Table" + "Hash Table", + "Sorting" ], "intended_approach": "HashSet에 원소를 추가하면서 이미 존재하는지 확인합니다. O(n), O(n)." }, @@ -110,15 +123,17 @@ "course-schedule": { "difficulty": "Medium", "categories": [ - "Graph", - "Topological Sort", - "DFS" + "Depth-First Search", + "Breadth-First Search", + "Graph Theory", + "Topological Sort" ], "intended_approach": "방향 그래프에서 사이클 존재 여부를 DFS(색칠 기법) 또는 BFS 위상 정렬로 감지합니다." }, "decode-ways": { "difficulty": "Medium", "categories": [ + "String", "Dynamic Programming" ], "intended_approach": "dp[i] = s[:i]를 디코딩하는 경우의 수로 정의하고, 1자리/2자리 해석 가능 여부에 따라 Bottom-up DP로 풀어야 합니다." @@ -126,23 +141,30 @@ "design-add-and-search-words-data-structure": { "difficulty": "Medium", "categories": [ - "Trie", - "DFS" + "String", + "Depth-First Search", + "Design", + "Trie" ], "intended_approach": "Trie를 구현하고, '.' 와일드카드 처리를 위해 DFS로 모든 자식 노드를 탐색합니다." }, "encode-and-decode-strings": { "difficulty": "Medium", "categories": [ - "String" + "Array", + "String", + "Design" ], "intended_approach": "각 문자열 앞에 길이를 접두사로 붙이는 방식(예: '4#word')으로 구분자 충돌 없이 인코딩/디코딩합니다." }, "find-median-from-data-stream": { "difficulty": "Hard", "categories": [ - "Heap", - "Two Pointers" + "Two Pointers", + "Design", + "Sorting", + "Heap (Priority Queue)", + "Data Stream" ], "intended_approach": "최대 힙(작은 절반)과 최소 힙(큰 절반)을 유지하며 중앙값을 O(log n)에 구합니다." }, @@ -157,9 +179,10 @@ "graph-valid-tree": { "difficulty": "Medium", "categories": [ - "Graph", + "Depth-First Search", + "Breadth-First Search", "Union-Find", - "DFS" + "Graph Theory" ], "intended_approach": "Union-Find 또는 DFS로 사이클 여부를 확인하고, 모든 노드가 연결되어 있는지 검증합니다." }, @@ -168,13 +191,15 @@ "categories": [ "Array", "Hash Table", - "String" + "String", + "Sorting" ], "intended_approach": "정렬된 문자열 또는 문자 카운팅 튜플을 HashMap의 키로 사용해 그룹핑합니다." }, "house-robber": { "difficulty": "Medium", "categories": [ + "Array", "Dynamic Programming" ], "intended_approach": "dp[i] = max(dp[i-1], dp[i-2] + nums[i]) 점화식으로 O(n), O(1) DP로 풀어야 합니다." @@ -182,6 +207,7 @@ "house-robber-ii": { "difficulty": "Medium", "categories": [ + "Array", "Dynamic Programming" ], "intended_approach": "원형 배열을 첫 집 포함/제외 두 경우로 분리해 house-robber를 두 번 실행합니다." @@ -189,8 +215,10 @@ "implement-trie-prefix-tree": { "difficulty": "Medium", "categories": [ - "Trie", - "Hash Table" + "Hash Table", + "String", + "Design", + "Trie" ], "intended_approach": "각 노드가 자식 맵과 is_end 플래그를 갖는 Trie 자료구조를 직접 구현합니다." }, @@ -205,8 +233,9 @@ "difficulty": "Easy", "categories": [ "Tree", - "DFS", - "BFS" + "Depth-First Search", + "Breadth-First Search", + "Binary Tree" ], "intended_approach": "DFS 재귀 또는 BFS로 각 노드의 좌우 자식을 교환합니다." }, @@ -214,6 +243,7 @@ "difficulty": "Medium", "categories": [ "Array", + "Dynamic Programming", "Greedy" ], "intended_approach": "현재까지 도달 가능한 최대 인덱스를 추적하는 Greedy로 O(n)에 풀어야 합니다." @@ -222,13 +252,16 @@ "difficulty": "Medium", "categories": [ "Tree", - "DFS" + "Depth-First Search", + "Binary Search Tree", + "Binary Tree" ], "intended_approach": "BST의 중위 순회(In-order traversal)는 오름차순이므로 k번째 원소가 정답입니다." }, "linked-list-cycle": { "difficulty": "Easy", "categories": [ + "Hash Table", "Linked List", "Two Pointers" ], @@ -237,6 +270,7 @@ "longest-common-subsequence": { "difficulty": "Medium", "categories": [ + "String", "Dynamic Programming" ], "intended_approach": "2D DP 테이블 dp[i][j] = text1[:i]와 text2[:j]의 LCS 길이로 풀어야 합니다." @@ -245,21 +279,24 @@ "difficulty": "Medium", "categories": [ "Array", - "Hash Table" + "Hash Table", + "Union-Find" ], "intended_approach": "HashSet에 모든 수를 넣고, 시퀀스 시작점(num-1이 없는 수)에서만 연속 길이를 셉니다. O(n)." }, "longest-increasing-subsequence": { "difficulty": "Medium", "categories": [ - "Dynamic Programming", - "Binary Search" + "Array", + "Binary Search", + "Dynamic Programming" ], "intended_approach": "O(n log n)은 이진 탐색으로 patience sorting, O(n2)은 기본 DP로 풀어야 합니다." }, "longest-palindromic-substring": { "difficulty": "Medium", "categories": [ + "Two Pointers", "String", "Dynamic Programming" ], @@ -268,6 +305,7 @@ "longest-repeating-character-replacement": { "difficulty": "Medium", "categories": [ + "Hash Table", "String", "Sliding Window" ], @@ -276,9 +314,9 @@ "longest-substring-without-repeating-characters": { "difficulty": "Medium", "categories": [ + "Hash Table", "String", - "Sliding Window", - "Hash Table" + "Sliding Window" ], "intended_approach": "슬라이딩 윈도우 + HashMap으로 중복 문자 발생 시 왼쪽 포인터를 이동합니다. O(n)." }, @@ -286,7 +324,9 @@ "difficulty": "Medium", "categories": [ "Tree", - "DFS" + "Depth-First Search", + "Binary Search Tree", + "Binary Tree" ], "intended_approach": "BST 속성(p, q가 모두 왼쪽/오른쪽이면 내려가고, 분기되면 현재 노드가 LCA)을 활용해 재귀합니다." }, @@ -294,14 +334,16 @@ "difficulty": "Easy", "categories": [ "Tree", - "DFS", - "BFS" + "Depth-First Search", + "Breadth-First Search", + "Binary Tree" ], "intended_approach": "DFS 재귀로 max(left, right) + 1을 반환하거나 BFS로 레벨을 셉니다." }, "maximum-product-subarray": { "difficulty": "Medium", "categories": [ + "Array", "Dynamic Programming" ], "intended_approach": "음수 곱셈을 고려해 현재 최댓값과 최솟값을 동시에 추적하는 DP로 풀어야 합니다." @@ -309,6 +351,8 @@ "maximum-subarray": { "difficulty": "Medium", "categories": [ + "Array", + "Divide and Conquer", "Dynamic Programming" ], "intended_approach": "카데인 알고리즘: 현재 합이 음수가 되면 초기화하는 방식으로 O(n), O(1)에 풀어야 합니다." @@ -325,8 +369,11 @@ "difficulty": "Medium", "categories": [ "Array", - "Heap", - "Sorting" + "Two Pointers", + "Greedy", + "Sorting", + "Heap (Priority Queue)", + "Prefix Sum" ], "intended_approach": "최소 힙으로 진행 중인 회의의 종료 시간을 관리하고, 새 회의가 시작될 때 가장 빨리 끝나는 회의와 비교합니다." }, @@ -342,8 +389,9 @@ "difficulty": "Hard", "categories": [ "Linked List", - "Heap", - "Divide and Conquer" + "Divide and Conquer", + "Heap (Priority Queue)", + "Merge Sort" ], "intended_approach": "최소 힙(Priority Queue)에 각 리스트의 헤드를 넣고 순서대로 추출합니다. O(n log k)." }, @@ -351,16 +399,16 @@ "difficulty": "Easy", "categories": [ "Linked List", - "Two Pointers" + "Recursion" ], "intended_approach": "두 포인터로 작은 쪽을 연결하는 반복 또는 재귀로 풀어야 합니다." }, "minimum-window-substring": { "difficulty": "Hard", "categories": [ + "Hash Table", "String", - "Sliding Window", - "Hash Table" + "Sliding Window" ], "intended_approach": "슬라이딩 윈도우 + 문자 카운팅 HashMap으로, 조건 충족 시 윈도우를 줄이며 최솟값을 갱신합니다." }, @@ -368,8 +416,11 @@ "difficulty": "Easy", "categories": [ "Array", + "Hash Table", + "Math", + "Binary Search", "Bit Manipulation", - "Math" + "Sorting" ], "intended_approach": "XOR(모든 수 XOR 인덱스) 또는 가우스 공식(n*(n+1)/2 - 합)으로 O(n), O(1)에 풀어야 합니다." }, @@ -377,6 +428,7 @@ "difficulty": "Medium", "categories": [ "Array", + "Dynamic Programming", "Greedy", "Sorting" ], @@ -385,6 +437,7 @@ "number-of-1-bits": { "difficulty": "Easy", "categories": [ + "Divide and Conquer", "Bit Manipulation" ], "intended_approach": "n & (n-1)로 가장 낮은 1 비트를 제거하는 방식으로 set bit 수를 셉니다." @@ -392,33 +445,38 @@ "number-of-connected-components-in-an-undirected-graph": { "difficulty": "Medium", "categories": [ - "Graph", + "Depth-First Search", + "Breadth-First Search", "Union-Find", - "DFS" + "Graph Theory" ], "intended_approach": "Union-Find 또는 DFS/BFS로 연결 컴포넌트 수를 셉니다." }, "number-of-islands": { "difficulty": "Medium", "categories": [ - "Graph", - "DFS", - "BFS" + "Array", + "Depth-First Search", + "Breadth-First Search", + "Union-Find", + "Matrix" ], "intended_approach": "육지 셀을 발견하면 DFS/BFS로 연결된 육지를 모두 방문 처리하고 카운트합니다." }, "pacific-atlantic-water-flow": { "difficulty": "Medium", "categories": [ - "Graph", - "DFS", - "BFS" + "Array", + "Depth-First Search", + "Breadth-First Search", + "Matrix" ], "intended_approach": "역방향으로 태평양/대서양 경계에서 DFS/BFS를 시작해 도달 가능한 셀의 교집합을 구합니다." }, "palindromic-substrings": { "difficulty": "Medium", "categories": [ + "Two Pointers", "String", "Dynamic Programming" ], @@ -427,7 +485,8 @@ "product-of-array-except-self": { "difficulty": "Medium", "categories": [ - "Array" + "Array", + "Prefix Sum" ], "intended_approach": "나눗셈 없이 prefix 곱 배열과 suffix 곱을 활용해 O(n), O(1) 추가 공간으로 풀어야 합니다." }, @@ -443,13 +502,16 @@ "difficulty": "Medium", "categories": [ "Linked List", - "Two Pointers" + "Two Pointers", + "Stack", + "Recursion" ], "intended_approach": "중간 찾기(느린/빠른 포인터) → 후반 역전 → 교차 병합 세 단계로 풀어야 합니다." }, "reverse-bits": { "difficulty": "Easy", "categories": [ + "Divide and Conquer", "Bit Manipulation" ], "intended_approach": "비트를 하나씩 추출해 결과에 왼쪽으로 추가하는 비트 시프트 연산으로 풀어야 합니다." @@ -457,7 +519,8 @@ "reverse-linked-list": { "difficulty": "Easy", "categories": [ - "Linked List" + "Linked List", + "Recursion" ], "intended_approach": "prev/curr 포인터로 방향을 뒤집는 반복(O(1) 공간) 또는 재귀로 풀어야 합니다." }, @@ -465,7 +528,8 @@ "difficulty": "Medium", "categories": [ "Array", - "Math" + "Math", + "Matrix" ], "intended_approach": "전치(Transpose) 후 각 행을 좌우 반전하면 O(1) 추가 공간으로 90도 회전됩니다." }, @@ -473,7 +537,9 @@ "difficulty": "Easy", "categories": [ "Tree", - "DFS" + "Depth-First Search", + "Breadth-First Search", + "Binary Tree" ], "intended_approach": "두 트리를 동시에 DFS 재귀로 순회하며 값과 구조를 비교합니다." }, @@ -488,16 +554,21 @@ "serialize-and-deserialize-binary-tree": { "difficulty": "Hard", "categories": [ + "String", "Tree", - "BFS", - "DFS" + "Depth-First Search", + "Breadth-First Search", + "Design", + "Binary Tree" ], "intended_approach": "BFS(레벨 순서) 또는 DFS 전위 순회로 직렬화하고, null 마커로 구조를 복원합니다." }, "set-matrix-zeroes": { "difficulty": "Medium", "categories": [ - "Array" + "Array", + "Hash Table", + "Matrix" ], "intended_approach": "첫 행/열을 마커 행으로 활용해 O(1) 추가 공간으로 풀어야 합니다." }, @@ -505,6 +576,7 @@ "difficulty": "Medium", "categories": [ "Array", + "Matrix", "Simulation" ], "intended_approach": "상/하/좌/우 경계를 좁혀가며 시뮬레이션으로 순회합니다." @@ -513,13 +585,17 @@ "difficulty": "Easy", "categories": [ "Tree", - "DFS" + "Depth-First Search", + "String Matching", + "Binary Tree", + "Hash Function" ], "intended_approach": "각 노드에서 same-tree 판별 함수를 호출하는 DFS로 풀어야 합니다." }, "sum-of-two-integers": { "difficulty": "Medium", "categories": [ + "Math", "Bit Manipulation" ], "intended_approach": "XOR로 합(올림 없는 덧셈), AND 후 왼쪽 시프트로 올림을 계산하고 올림이 0이 될 때까지 반복합니다." @@ -529,7 +605,12 @@ "categories": [ "Array", "Hash Table", - "Heap" + "Divide and Conquer", + "Sorting", + "Heap (Priority Queue)", + "Bucket Sort", + "Counting", + "Quickselect" ], "intended_approach": "버킷 정렬(빈도를 인덱스로 사용)로 O(n)에 풀거나, 최소 힙으로 O(n log k)에 풀어야 합니다." }, @@ -544,32 +625,34 @@ "unique-paths": { "difficulty": "Medium", "categories": [ + "Math", "Dynamic Programming", - "Math" + "Combinatorics" ], "intended_approach": "dp[i][j] = dp[i-1][j] + dp[i][j-1]로 2D DP, 또는 조합 C(m+n-2, m-1)으로 수학적으로 풀 수 있습니다." }, "valid-anagram": { "difficulty": "Easy", "categories": [ + "Hash Table", "String", - "Hash Table" + "Sorting" ], "intended_approach": "문자 카운팅 배열(26) 또는 HashMap으로 두 문자열의 빈도를 비교합니다." }, "valid-palindrome": { "difficulty": "Easy", "categories": [ - "String", - "Two Pointers" + "Two Pointers", + "String" ], "intended_approach": "양 끝에서 시작하는 투 포인터로 영숫자만 비교합니다. O(n), O(1)." }, "valid-parentheses": { "difficulty": "Easy", "categories": [ - "Stack", - "String" + "String", + "Stack" ], "intended_approach": "스택을 사용해 여는 괄호를 push하고, 닫는 괄호가 나오면 스택 top과 대응 여부를 확인합니다." }, @@ -577,30 +660,43 @@ "difficulty": "Medium", "categories": [ "Tree", - "DFS" + "Depth-First Search", + "Binary Search Tree", + "Binary Tree" ], "intended_approach": "DFS로 각 노드에 유효 범위(min, max)를 전달하며 BST 조건을 검증합니다." }, "word-break": { "difficulty": "Medium", "categories": [ - "Dynamic Programming" + "Array", + "Hash Table", + "String", + "Dynamic Programming", + "Trie", + "Memoization" ], "intended_approach": "dp[i] = s[:i]가 wordDict로 분리 가능한지 여부로 정의하고, Bottom-up DP로 O(n2)에 풀어야 합니다." }, "word-search": { "difficulty": "Medium", "categories": [ - "Graph", - "Backtracking" + "Array", + "String", + "Backtracking", + "Depth-First Search", + "Matrix" ], "intended_approach": "각 셀에서 DFS 백트래킹으로 탐색하고, 방문한 셀을 임시 마킹해 중복 방문을 방지합니다." }, "word-search-ii": { "difficulty": "Hard", "categories": [ + "Array", + "String", + "Backtracking", "Trie", - "Backtracking" + "Matrix" ], "intended_approach": "단어 목록으로 Trie를 구성하고, 그리드를 DFS 백트래킹으로 탐색하며 Trie 노드와 함께 매칭합니다." } From 23df2b7df955efdb93405f4f9817a158661df3ae Mon Sep 17 00:00:00 2001 From: soobing Date: Mon, 6 Apr 2026 22:04:05 +0900 Subject: [PATCH 271/526] fix: lint --- implement-trie-prefix-tree/soobing3.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/implement-trie-prefix-tree/soobing3.ts b/implement-trie-prefix-tree/soobing3.ts index 0343ccfbcb..d8cfd5d97c 100644 --- a/implement-trie-prefix-tree/soobing3.ts +++ b/implement-trie-prefix-tree/soobing3.ts @@ -50,3 +50,4 @@ class Trie { * var param_2 = obj.search(word) * var param_3 = obj.startsWith(prefix) */ + From 9a45a0dcd81037a9d97f13a21f4df3a1dcdc5f80 Mon Sep 17 00:00:00 2001 From: soobing Date: Mon, 6 Apr 2026 22:12:47 +0900 Subject: [PATCH 272/526] feat(soobing): move 3rd tried solutions to soobing.ts --- best-time-to-buy-and-sell-stock/soobing.ts | 24 ++++----- best-time-to-buy-and-sell-stock/soobing3.ts | 15 ------ encode-and-decode-strings/soobing.ts | 40 ++++++--------- encode-and-decode-strings/soobing3.ts | 25 ---------- group-anagrams/soobing.ts | 20 +++----- group-anagrams/soobing3.ts | 10 ---- implement-trie-prefix-tree/soobing.ts | 55 ++++++++++++--------- implement-trie-prefix-tree/soobing3.ts | 53 -------------------- word-break/soobing.ts | 23 ++++----- word-break/soobing3.ts | 15 ------ 10 files changed, 80 insertions(+), 200 deletions(-) delete mode 100644 best-time-to-buy-and-sell-stock/soobing3.ts delete mode 100644 encode-and-decode-strings/soobing3.ts delete mode 100644 group-anagrams/soobing3.ts delete mode 100644 implement-trie-prefix-tree/soobing3.ts delete mode 100644 word-break/soobing3.ts diff --git a/best-time-to-buy-and-sell-stock/soobing.ts b/best-time-to-buy-and-sell-stock/soobing.ts index b30c33976b..e83e6469f0 100644 --- a/best-time-to-buy-and-sell-stock/soobing.ts +++ b/best-time-to-buy-and-sell-stock/soobing.ts @@ -1,14 +1,16 @@ +// 3rd tried function maxProfit(prices: number[]): number { - let minPrice = Infinity; - let maxProfit = 0; - for (let i = 0; i < prices.length; i++) { - if (prices[i] < minPrice) { - minPrice = prices[i]; - } + let left = 0; + let right = 1; + let max = 0; - if (prices[i] - minPrice> maxProfit) { - maxProfit = prices[i] - minPrice; - } + while(left < right && right < prices.length) { + if(prices[right] - prices[left]> 0) { + max = Math.max(max, prices[right] - prices[left]) + } else { + left = right; + } + right++; } - return maxProfit; -} + return max; +}; diff --git a/best-time-to-buy-and-sell-stock/soobing3.ts b/best-time-to-buy-and-sell-stock/soobing3.ts deleted file mode 100644 index 373f8fec06..0000000000 --- a/best-time-to-buy-and-sell-stock/soobing3.ts +++ /dev/null @@ -1,15 +0,0 @@ -function maxProfit(prices: number[]): number { - let left = 0; - let right = 1; - let max = 0; - - while(left < right && right < prices.length) { - if(prices[right] - prices[left]> 0) { - max = Math.max(max, prices[right] - prices[left]) - } else { - left = right; - } - right++; - } - return max; -}; diff --git a/encode-and-decode-strings/soobing.ts b/encode-and-decode-strings/soobing.ts index e3b471b12b..89bb0811d6 100644 --- a/encode-and-decode-strings/soobing.ts +++ b/encode-and-decode-strings/soobing.ts @@ -1,34 +1,26 @@ +// 3rd tried class Solution { /** - * 문자열 배열을 하나의 문자열로 인코딩합니다. - * @param strs - 문자열 배열 - * @returns 인코딩된 하나의 문자열 + * @param {string[]} strs + * @returns {string} */ - encode(strs: string[]): string { - return strs.map((str) => str.length + "#" + str).join(""); + encode(strs) { + return strs.map((str) => `${str.length}#${str}`).join(''); } /** - * 인코딩된 문자열을 원래 문자열 배열로 디코딩합니다. - * @param str - 인코딩된 문자열 - * @returns 디코딩된 문자열 배열 + * @param {string} str + * @returns {string[]} */ - decode(str: string): string[] { - const result: string[] = []; - - let i = 0; - while (i < str.length) { - let j = i; - while (str[j] !== "#") { - j++; + decode(str) { + const result: string[] = []; + let i = 0; + while(i < str.length) { + const j = str.indexOf('#', i); + const length = Number(str.slice(i, j)); + result.push(str.slice(j + 1, j + 1 + length)); + i = j + 1 + length; } - - const length = parseInt(str.slice(i, j)); - const word = str.slice(j + 1, j + 1 + length); - result.push(word); - i = j + 1 + length; - } - - return result; + return result; } } diff --git a/encode-and-decode-strings/soobing3.ts b/encode-and-decode-strings/soobing3.ts deleted file mode 100644 index e1b8dc8d29..0000000000 --- a/encode-and-decode-strings/soobing3.ts +++ /dev/null @@ -1,25 +0,0 @@ -class Solution { - /** - * @param {string[]} strs - * @returns {string} - */ - encode(strs) { - return strs.map((str) => `${str.length}#${str}`).join(''); - } - - /** - * @param {string} str - * @returns {string[]} - */ - decode(str) { - const result: string[] = []; - let i = 0; - while(i < str.length) { - const j = str.indexOf('#', i); - const length = Number(str.slice(i, j)); - result.push(str.slice(j + 1, j + 1 + length)); - i = j + 1 + length; - } - return result; - } -} diff --git a/group-anagrams/soobing.ts b/group-anagrams/soobing.ts index c446e01609..ecad1e2a6e 100644 --- a/group-anagrams/soobing.ts +++ b/group-anagrams/soobing.ts @@ -1,15 +1,11 @@ -// idea: 배열에 담긴 모든 애들을 다 sorting하면서 sorting된 결과를 key로 바인딩하고 Record 에 맞게 매핑하여 values들만 리턴하면 될것 같음 +// 3rd tried function groupAnagrams(strs: string[]): string[][] { - const map = new Map(); + const map = new Map(); - for (let i = 0; i < strs.length; i++) { - const key = strs[i].split("").sort().join(""); - const group = map.get(key); - if (group) { - group.push(strs[i]); - } else { - map.set(key, [strs[i]]); - } + for(const str of strs) { + const key = str.split('').sort().join(''); + const value = map.get(key); + map.set(key, value ? [...value, str] : [str]) } - return [...map.values()]; -} + return Array.from(map.values()); +}; diff --git a/group-anagrams/soobing3.ts b/group-anagrams/soobing3.ts deleted file mode 100644 index 3763f3e452..0000000000 --- a/group-anagrams/soobing3.ts +++ /dev/null @@ -1,10 +0,0 @@ -function groupAnagrams(strs: string[]): string[][] { - const map = new Map(); - - for(const str of strs) { - const key = str.split('').sort().join(''); - const value = map.get(key); - map.set(key, value ? [...value, str] : [str]) - } - return Array.from(map.values()); -}; diff --git a/implement-trie-prefix-tree/soobing.ts b/implement-trie-prefix-tree/soobing.ts index d6a9e59359..6d0a72d12e 100644 --- a/implement-trie-prefix-tree/soobing.ts +++ b/implement-trie-prefix-tree/soobing.ts @@ -1,46 +1,53 @@ +// 3rd tried class TrieNode { children: Map; isEnd: boolean; - constructor() { - this.children = new Map(); - this.isEnd = false; + this.children = new Map(); + this.isEnd = false } } - class Trie { root: TrieNode; constructor() { - this.root = new TrieNode(); + this.root = new TrieNode(); } insert(word: string): void { - let node = this.root; - for (const char of word) { - if (!node.children.has(char)) { - node.children.set(char, new TrieNode()); + let node = this.root; + for(const ch of word) { + if(!node.children.has(ch)) { + node.children.set(ch, new TrieNode()); + } + node = node.children.get(ch)! } - node = node.children.get(char)!; - } - node.isEnd = true; + node.isEnd = true; } search(word: string): boolean { - const node = this._findNode(word); - return node !== null && node.isEnd; + let node = this.root; + for(const ch of word) { + if(!node.children.has(ch)) return false; + node = node.children.get(ch)!; + } + return node.isEnd; } startsWith(prefix: string): boolean { - return this._findNode(prefix) !== null; - } - - private _findNode(word: string): TrieNode | null { - let node = this.root; - for (const char of word) { - if (!node.children.has(char)) return null; - node = node.children.get(char)!; - } - return node; + let node = this.root; + for(const ch of prefix) { + if(!node.children.has(ch)) return false; + node = node.children.get(ch)!; + } + return true; } } + +/** +* Your Trie object will be instantiated and called as such: +* var obj = new Trie() +* obj.insert(word) +* var param_2 = obj.search(word) +* var param_3 = obj.startsWith(prefix) +*/ diff --git a/implement-trie-prefix-tree/soobing3.ts b/implement-trie-prefix-tree/soobing3.ts deleted file mode 100644 index d8cfd5d97c..0000000000 --- a/implement-trie-prefix-tree/soobing3.ts +++ /dev/null @@ -1,53 +0,0 @@ -class TrieNode { - children: Map; - isEnd: boolean; - constructor() { - this.children = new Map(); - this.isEnd = false - } -} -class Trie { - root: TrieNode; - - constructor() { - this.root = new TrieNode(); - } - - insert(word: string): void { - let node = this.root; - for(const ch of word) { - if(!node.children.has(ch)) { - node.children.set(ch, new TrieNode()); - } - node = node.children.get(ch)! - } - node.isEnd = true; - } - - search(word: string): boolean { - let node = this.root; - for(const ch of word) { - if(!node.children.has(ch)) return false; - node = node.children.get(ch)!; - } - return node.isEnd; - } - - startsWith(prefix: string): boolean { - let node = this.root; - for(const ch of prefix) { - if(!node.children.has(ch)) return false; - node = node.children.get(ch)!; - } - return true; - } -} - -/** -* Your Trie object will be instantiated and called as such: -* var obj = new Trie() -* obj.insert(word) -* var param_2 = obj.search(word) -* var param_3 = obj.startsWith(prefix) -*/ - diff --git a/word-break/soobing.ts b/word-break/soobing.ts index a6ed583068..f6925e063a 100644 --- a/word-break/soobing.ts +++ b/word-break/soobing.ts @@ -1,15 +1,16 @@ +// 3rd tried function wordBreak(s: string, wordDict: string[]): boolean { const dp = new Array(s.length + 1).fill(false); - dp[s.length] = true; + dp[0] = true; - for (let i = s.length - 1; i>= 0; i--) { - for (const word of wordDict) { - if (i + word.length <= s.length && s.slice(i, i + word.length) === word) { - dp[i] = dp[i + word.length]; - } - - if (dp[i]) break; + for (let i = 1; i <= s.length; i++) { + for (let j = 0; j < i; j++) { + if (dp[j] && wordDict.includes(s.slice(j, i))) { + dp[i] = true; + break; + } + } } - } - return dp[0]; -} + + return dp[s.length]; +}; diff --git a/word-break/soobing3.ts b/word-break/soobing3.ts deleted file mode 100644 index 42e3b0743f..0000000000 --- a/word-break/soobing3.ts +++ /dev/null @@ -1,15 +0,0 @@ -function wordBreak(s: string, wordDict: string[]): boolean { - const dp = new Array(s.length + 1).fill(false); - dp[0] = true; - - for (let i = 1; i <= s.length; i++) { - for (let j = 0; j < i; j++) { - if (dp[j] && wordDict.includes(s.slice(j, i))) { - dp[i] = true; - break; - } - } - } - - return dp[s.length]; -}; From 6e4f683919369ca4d4f9bf3f10e19fa7abbe56f4 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: Tue, 7 Apr 2026 09:55:49 +0900 Subject: [PATCH 273/526] solved design-add-and... --- design-add-and-search-words-data-structure/sangbeenmoon.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 design-add-and-search-words-data-structure/sangbeenmoon.java diff --git a/design-add-and-search-words-data-structure/sangbeenmoon.java b/design-add-and-search-words-data-structure/sangbeenmoon.java new file mode 100644 index 0000000000..e69de29bb2 From ad4b1cb5d88076b0a6cf3019250341bf2892fc1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: Tue, 7 Apr 2026 16:38:15 +0900 Subject: [PATCH 274/526] implement maxArea function to calculate maximum water container area --- container-with-most-water/gcount85.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 container-with-most-water/gcount85.py diff --git a/container-with-most-water/gcount85.py b/container-with-most-water/gcount85.py new file mode 100644 index 0000000000..efd66495f3 --- /dev/null +++ b/container-with-most-water/gcount85.py @@ -0,0 +1,24 @@ +""" +# Approach +투포인터로 양 끝에서 물의 양을 계산해나갑니다. +더 낮은 height인 쪽의 포인터를 줄여나가는데, 높이가 같은 경우에는 양쪽 모두 포인터를 움직입니다. + +# Complexity +height의 길이가 N일 때 +- Time complexity: O(N) +- Space complexity: O(1) +""" + + +class Solution: + def maxArea(self, height: list[int]) -> int: + n = len(height) + left, right = 0, n - 1 + best = 0 + while left < right: + best = max(best, (right - left) * min(height[left], height[right])) + if height[left]> height[right]: + right -= 1 + else: + left += 1 + return best From b2912ea8d804e16b89f1f878a36cd9411dd04789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: Tue, 7 Apr 2026 16:38:20 +0900 Subject: [PATCH 275/526] add lengthOfLIS function to calculate the length of the longest increasing subsequence --- longest-increasing-subsequence/gcount85.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 longest-increasing-subsequence/gcount85.py diff --git a/longest-increasing-subsequence/gcount85.py b/longest-increasing-subsequence/gcount85.py new file mode 100644 index 0000000000..56df84e87b --- /dev/null +++ b/longest-increasing-subsequence/gcount85.py @@ -0,0 +1,22 @@ +""" +# Approach +dp[n]은 nums[n] 위치까지 lis 길이입니다. + +# Complexity +nums의 길이를 n이라고 할 때, +- Time complexity: 이중 반복문 O(N^2) +- Space complexity: dp 배열 O(N) +""" + + +class Solution: + def lengthOfLIS(self, nums: list[int]) -> int: + n = len(nums) + dp = [1] * n + answer = 1 + for i in range(1, n): + for j in range(i): + if nums[j] < nums[i]: + dp[i] = max(dp[j] + 1, dp[i]) + answer = max(answer, dp[i]) + return answer From e34f9af099cada77bd1d3299d73deeaa1d7220e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: Tue, 7 Apr 2026 16:38:25 +0900 Subject: [PATCH 276/526] add spiralOrder function to return elements of a matrix in spiral order --- spiral-matrix/gcount85.py | 41 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 spiral-matrix/gcount85.py diff --git a/spiral-matrix/gcount85.py b/spiral-matrix/gcount85.py new file mode 100644 index 0000000000..556a5b1808 --- /dev/null +++ b/spiral-matrix/gcount85.py @@ -0,0 +1,41 @@ +""" +# Approach +상하좌우 경계값을 설정하고 matrix을 순회하며 경계값을 줄여나갑니다. + +# Complexity +matrix 크기의 가로를 M, 세로를 N이라고 할 때 +- Time complexity: O(M*N) +- Space complexity: O(M*N) +""" + + +class Solution: + def spiralOrder(self, matrix: list[list[int]]) -> list[int]: + start_row, start_col = 0, 0 + end_row, end_col = len(matrix) - 1, len(matrix[0]) - 1 + output = [] + + while start_row <= end_row and start_col <= end_col: + # 좌->우 + for col in range(start_col, end_col + 1): + output.append(matrix[start_row][col]) + start_row += 1 + + # 상->하 + for row in range(start_row, end_row + 1): + output.append(matrix[row][end_col]) + end_col -= 1 + + # 우->좌 + if start_row <= end_row: + for col in range(end_col, start_col - 1, -1): + output.append(matrix[end_row][col]) + end_row -= 1 + + # 하->상 + if start_col <= end_col: + for row in range(end_row, start_row - 1, -1): + output.append(matrix[row][start_col]) + start_col += 1 + + return output From c1627a0918a8e1774db6d9e46ad63d510d841920 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: Tue, 7 Apr 2026 16:38:35 +0900 Subject: [PATCH 277/526] add isValid function to validate parentheses using a stack --- valid-parentheses/gcount85.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 valid-parentheses/gcount85.py diff --git a/valid-parentheses/gcount85.py b/valid-parentheses/gcount85.py new file mode 100644 index 0000000000..e15095ca68 --- /dev/null +++ b/valid-parentheses/gcount85.py @@ -0,0 +1,25 @@ +""" +# Approach +스택을 이용하여 닫는 괄호가 나올 때 스택 top과 비교하여 짝이 맞으면 pop합니다. +짝이 맞지 않으면 invalid, 최종적으로 스택이 비어있지 않으면 invalid 합니다. + +# Complexity +s의 길이를 N이라고 할 때 +- Time complexity: O(N) +- Space complexity: O(N) +""" + + +class Solution: + def isValid(self, s: str) -> bool: + stack = [] + brackets = {"(": ")", "{": "}", "[": "]"} + for b in s: + if b in brackets: + stack.append(b) + continue + if not stack or brackets[stack.pop()] != b: + return False + if not stack: + return True + return False From 182e596026b8e839e432be8e9a9d0e2991b81d17 Mon Sep 17 00:00:00 2001 From: hyerijung Date: Tue, 7 Apr 2026 21:52:43 +0900 Subject: [PATCH 278/526] container-with-most-water --- container-with-most-water/hyeri0903.py | 32 ++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 container-with-most-water/hyeri0903.py diff --git a/container-with-most-water/hyeri0903.py b/container-with-most-water/hyeri0903.py new file mode 100644 index 0000000000..9375a08f8d --- /dev/null +++ b/container-with-most-water/hyeri0903.py @@ -0,0 +1,32 @@ +class Solution: + def maxArea(self, height: List[int]) -> int: + ''' + 1.문제: 가장 많은 양의 물을 저장할 수 있는 max value return + 2.조건 + - n: 높이를 의미, 최소 = 5, 최대 = 10^5 + - 원소값 최소 = 0, 최대 = 10^4 + 3.풀이 + - 높이는 height[i], height[j] 중에 작은 값, 가로는 abs(i-j) + - output = 높이 x 가로 + -> 2중 loop 는 O(n^2) 로 TLE 발생. + -> two pointer 로 O(n) 으로 해결! + ''' + + n = len(height) + maxArea = 0 + + left = 0 + right = n-1 + + while left < right: + curArea = abs(right-left) * min(height[left], height[right]) + maxArea = max(curArea, maxArea) + + #height 이 낮은쪽 pointer update + if height[left] < height[right]: + left += 1 + else: + right -= 1 + + return maxArea + \ No newline at end of file From b1f9499501671e7d4667e605eeb81952077f2c4b Mon Sep 17 00:00:00 2001 From: Dale Seo <5466341+daleseo@users.noreply.github.com> Date: Tue, 7 Apr 2026 21:00:41 -0400 Subject: [PATCH 279/526] container-with-most-water --- container-with-most-water/DaleSeo.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 container-with-most-water/DaleSeo.rs diff --git a/container-with-most-water/DaleSeo.rs b/container-with-most-water/DaleSeo.rs new file mode 100644 index 0000000000..1fbd2e4695 --- /dev/null +++ b/container-with-most-water/DaleSeo.rs @@ -0,0 +1,20 @@ +// TC: O(n) +// SC: O(1) +impl Solution { + pub fn max_area(height: Vec) -> i32 { + let mut max_area = 0; + let (mut left, mut right) = (0, height.len() - 1); + while left < right { + let width = (right - left) as i32; + let min_height = height[left].min(height[right]); + let area = width * min_height; + max_area = max_area.max(area); + if height[left] < height[right] { + left += 1; + } else { + right -= 1; + } + } + max_area + } +} From 3100a15a97a02432a1e21668e4ed30c42be4407a Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: Wed, 8 Apr 2026 11:19:43 +0900 Subject: [PATCH 280/526] sadie100: valid parentheses solution --- valid-parentheses/sadie100.ts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 valid-parentheses/sadie100.ts diff --git a/valid-parentheses/sadie100.ts b/valid-parentheses/sadie100.ts new file mode 100644 index 0000000000..182ab84776 --- /dev/null +++ b/valid-parentheses/sadie100.ts @@ -0,0 +1,33 @@ +/* +스택을 만들어 s를 탐색하며 집어넣고, 허용되지 않은 괄호가 오면 false를 리턴한다 +- 허용하는 괄호 : 열려있는 괄호 (, {, [ 혹은 마지막 원소의 짝이 되는 닫는괄호 + +시간복잡도 : O(N) - N은 s의 length +공간복잡도 : O(N) (괄호 배열 및 괄호 쌍) +*/ + +function isValid(s: string): boolean { + const stack = [] + const openBrackets = ['(', '{', '['] + const bracketMap = { + '(': ')', + '{': '}', + '[': ']', + } + + for (const char of s) { + if (openBrackets.includes(char)) { + stack.push(char) + continue + } + const last = stack.at(-1) + if (char === bracketMap[last]) { + stack.pop() + continue + } + + return false + } + + return stack.length === 0 +} From c8f83452830ca0cdd69649a764f095cd3b9d1306 Mon Sep 17 00:00:00 2001 From: Ted Date: Tue, 7 Apr 2026 23:55:47 -0400 Subject: [PATCH 281/526] add week 6 solutions --- container-with-most-water/tedkimdev.rs | 19 +++++++ .../tedkimdev.go | 56 +++++++++++++++++++ longest-increasing-subsequence/tedkimdev.go | 32 +++++++++++ spiral-matrix/tedkimdev.rs | 38 +++++++++++++ valid-parentheses/tedkimdev.rs | 33 +++++++++++ 5 files changed, 178 insertions(+) create mode 100644 container-with-most-water/tedkimdev.rs create mode 100644 design-add-and-search-words-data-structure/tedkimdev.go create mode 100644 longest-increasing-subsequence/tedkimdev.go create mode 100644 spiral-matrix/tedkimdev.rs create mode 100644 valid-parentheses/tedkimdev.rs diff --git a/container-with-most-water/tedkimdev.rs b/container-with-most-water/tedkimdev.rs new file mode 100644 index 0000000000..c1c2561311 --- /dev/null +++ b/container-with-most-water/tedkimdev.rs @@ -0,0 +1,19 @@ +// TC: O(n) +// SC: O(1) +impl Solution { + pub fn max_area(heights: Vec) -> i32 { + let (mut left, mut right) = (0, heights.len() - 1); + let mut res = 0i32; + while left <= right { + res = res.max(((right - left) as i32) * heights[left].min(heights[right])); + + if heights[right] < heights[left] { + right -= 1; + } else { + left += 1; + } + } + + res + } +} diff --git a/design-add-and-search-words-data-structure/tedkimdev.go b/design-add-and-search-words-data-structure/tedkimdev.go new file mode 100644 index 0000000000..bd3e7907e3 --- /dev/null +++ b/design-add-and-search-words-data-structure/tedkimdev.go @@ -0,0 +1,56 @@ +type WordDictionary struct { + root *TrieNode +} + +func Constructor() WordDictionary { + return WordDictionary{root: NewTrieNode()} +} + +// TC: O(n) +// SC: O(t + n) +// t = total number of TrieNodes created so far +func (this *WordDictionary) AddWord(word string) { + cur := this.root + for _, c := range word { + if cur.Children[c-'a'] == nil { + cur.Children[c-'a'] = NewTrieNode() + } + cur = cur.Children[c-'a'] + } + cur.IsWord = true +} + +// TC: O(n) +func (this *WordDictionary) Search(word string) bool { + return this.dfs(word, 0, this.root) +} + +func (this *WordDictionary) dfs(word string, index int, root *TrieNode) bool { + cur := root + for i := index; i < len(word); i++ { + c := word[i] + if c == '.' { + for _, child := range cur.Children { + if child != nil && this.dfs(word, i+1, child) { + return true + } + } + return false + } else { + if cur.Children[c-'a'] == nil { + return false + } + cur = cur.Children[c-'a'] + } + } + return cur.IsWord +} + +type TrieNode struct { + Children [26]*TrieNode + IsWord bool +} + +func NewTrieNode() *TrieNode { + return &TrieNode{} +} diff --git a/longest-increasing-subsequence/tedkimdev.go b/longest-increasing-subsequence/tedkimdev.go new file mode 100644 index 0000000000..ba5a577f37 --- /dev/null +++ b/longest-increasing-subsequence/tedkimdev.go @@ -0,0 +1,32 @@ +// TC: O(n ^ 2) +// SC: O(n) +func lengthOfLIS(nums []int) int { + dp := make([]int, len(nums)) + + for i := range dp { + dp[i] = 1 + } + + for i := len(nums) - 2; i>= 0; i-- { + for j := i + 1; j < len(nums); j++ { + if nums[i] < nums[j] { + if dp[i] < 1+dp[j] { + dp[i] = 1 + dp[j] + } + } + } + } + + maxLength := 1 + for _, length := range dp { + maxLength = max(maxLength, length) + } + return maxLength +} + +func max(a, b int) int { + if a> b { + return a + } + return b +} diff --git a/spiral-matrix/tedkimdev.rs b/spiral-matrix/tedkimdev.rs new file mode 100644 index 0000000000..7e77133ffb --- /dev/null +++ b/spiral-matrix/tedkimdev.rs @@ -0,0 +1,38 @@ +// TC: O(m * n) +// SC: O(m * n) +impl Solution { + pub fn spiral_order(matrix: Vec>) -> Vec { + let mut result: Vec = Vec::new(); + + let mut left = 0i32; + let mut right = matrix[0].len() as i32; + let mut top = 0i32; + let mut bottom = matrix.len() as i32; + + while left < right && top < bottom { + for i in left..right { + result.push(matrix[top as usize][i as usize]); + } + top += 1; + for i in top..bottom { + result.push(matrix[i as usize][(right - 1) as usize]); + } + right -= 1; + + if !(left < right && top < bottom) { + break; + } + + for i in (left..right).rev() { + result.push(matrix[(bottom - 1) as usize][i as usize]); + } + bottom -= 1; + for i in (top..bottom).rev() { + result.push(matrix[i as usize][left as usize]); + } + left += 1; + } + + result + } +} diff --git a/valid-parentheses/tedkimdev.rs b/valid-parentheses/tedkimdev.rs new file mode 100644 index 0000000000..13fd260cd1 --- /dev/null +++ b/valid-parentheses/tedkimdev.rs @@ -0,0 +1,33 @@ +// TC: O(n) +// SC: O(n) +impl Solution { + pub fn is_valid(s: String) -> bool { + let mut stack = Vec::new(); + + for c in s.chars() { + match c { + '{' | '(' | '[' => { + stack.push(c); + }, + '}' => { + if Some('{') != stack.pop() { + return false; + } + }, + ')' => { + if Some('(') != stack.pop() { + return false; + } + }, + ']' => { + if Some('[') != stack.pop() { + return false; + } + }, + _ => {}, + }; + } + + stack.is_empty() + } +} From fcf4286851c32150a4662cbd0a25fd4415061da1 Mon Sep 17 00:00:00 2001 From: hyejj19 Date: Wed, 8 Apr 2026 14:54:49 +0900 Subject: [PATCH 282/526] solve valid-parentheses --- valid-parentheses/hyejj19.ts | 56 ++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 valid-parentheses/hyejj19.ts diff --git a/valid-parentheses/hyejj19.ts b/valid-parentheses/hyejj19.ts new file mode 100644 index 0000000000..49a6f5f574 --- /dev/null +++ b/valid-parentheses/hyejj19.ts @@ -0,0 +1,56 @@ +function isValid(s: string): boolean { + const stack = []; + const open = '([{'; + for (const v of s) { + if (open.includes(v)) { + stack.push(v); + } else { + if ( + (v === ')' && stack.at(-1) === '(') || + (v === '}' && stack.at(-1) === '{') || + (v === ']' && stack.at(-1) === '[') + ) { + // 일치하는 닫는 괄호라면 pop + stack.pop(); + } else { + // 일치하지 않는 닫는 괄호라면 false + return false; + } + } + } + + return stack.length === 0 ? true : false; +} + +function isValid(s: string): boolean { + const pairs = new Map([ + [')', '('], + ['}', '{'], + [']', '['], + ]); + const stack = []; + + for (const v of s) { + // v 가 닫는 괄호이면 + if (pairs.has(v)) { + if (pairs.get(v) === stack.at(-1)) { + // 일치하는 닫는 괄호라면 pop + stack.pop(); + } else { + // 일치하지 않는 닫는 괄호라면 false + return false; + } + } else { + // 여는 괄호이면 + stack.push(v); + } + } + + return stack.length === 0; +} + +/* +1. 여는 괄호에 해당한다 -> 스택에 push +2. 닫는 괄호가 나왔다 -> 스택의 top과 일치하면 pop 아니라면 false +3. 스택이 비어있다 -> true + */ From bed992d1d5668921009db26102c66071b28a6813 Mon Sep 17 00:00:00 2001 From: hyejj19 Date: Wed, 8 Apr 2026 15:27:16 +0900 Subject: [PATCH 283/526] solve container-with-most-water --- container-with-most-water/hyejj19.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 container-with-most-water/hyejj19.ts diff --git a/container-with-most-water/hyejj19.ts b/container-with-most-water/hyejj19.ts new file mode 100644 index 0000000000..769c4e6710 --- /dev/null +++ b/container-with-most-water/hyejj19.ts @@ -0,0 +1,23 @@ +function maxArea(height: number[]): number { + let left = 0; + let right = height.length - 1; + let max = -1; + + while (right> left) { + const v = Math.min(height[left], height[right]) * (right - left); + max = Math.max(max, v); + if (height[left]>= height[right]) { + right--; + } else { + left++; + } + } + return max; +} + +/* +1. Math.min(height[left], height[right]) * (right - left); +2. left 와 right 를 양 끝에서 가리킴 +3. 너비를 계산해서 max 값을 갱신하고, 둘 중 더 짧은 쪽을 안쪽으로 이동 +4. left 와 right 가 만나면 종료 + */ From e60be984bd6d749140b1f23124e32215a9d3b243 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: Wed, 8 Apr 2026 22:03:26 +0900 Subject: [PATCH 284/526] tried LIS. --- .../sangbeenmoon.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 longest-increasing-subsequence/sangbeenmoon.py diff --git a/longest-increasing-subsequence/sangbeenmoon.py b/longest-increasing-subsequence/sangbeenmoon.py new file mode 100644 index 0000000000..f4305af6b5 --- /dev/null +++ b/longest-increasing-subsequence/sangbeenmoon.py @@ -0,0 +1,27 @@ +# hint 를 보고 해결. +# DP 로도 풀 수 있음. + +class Solution: + def lengthOfLIS(self, nums: List[int]) -> int: + seq = [] + + + for num in nums: + if len(seq) == 0: + seq.append(num) + continue + + i = 0 + + while seq[i] < num: + i = i + 1 + + if i> len(seq) - 1: + break + + if i> len(seq) - 1: + seq.append(num) + else: + seq[i] = num + + return len(seq) From 2bc42e617209a61311ce8264d49345b874f405da Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: Wed, 8 Apr 2026 23:43:48 +0900 Subject: [PATCH 285/526] add: validParentheses solution --- valid-parentheses/Cyjin-jani.js | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 valid-parentheses/Cyjin-jani.js diff --git a/valid-parentheses/Cyjin-jani.js b/valid-parentheses/Cyjin-jani.js new file mode 100644 index 0000000000..d522b58364 --- /dev/null +++ b/valid-parentheses/Cyjin-jani.js @@ -0,0 +1,34 @@ +// tc: O(n) +// sc: O(n) +const isValid = function (s) { + const bracketMap = { + '(': ')', + '{': '}', + '[': ']', + }; + + if (s.length % 2 !== 0 || isCloseBracket(s[0])) return false; + + const stack = []; + + for (let i = 0; i < s.length; i++) { + if (stack.length === 0) { + stack.push(s[i]); + continue; + } + + let topBracket = stack.pop(); + if (bracketMap[topBracket] !== s[i]) { + stack.push(topBracket); + stack.push(s[i]); + } + } + + return stack.length === 0; +}; + +function isCloseBracket(char) { + const closeBrackets = [')', '}', ']']; + + return closeBrackets.includes(char); +} From 6e422c0a3fb0b2a76167725bf177b7631669afbb Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: Thu, 9 Apr 2026 20:31:45 +0900 Subject: [PATCH 286/526] =?UTF-8?q?sadie100:=20container=20with=20most=20w?= =?UTF-8?q?ater=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- container-with-most-water/sadie100.ts | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 container-with-most-water/sadie100.ts diff --git a/container-with-most-water/sadie100.ts b/container-with-most-water/sadie100.ts new file mode 100644 index 0000000000..59d6e89b42 --- /dev/null +++ b/container-with-most-water/sadie100.ts @@ -0,0 +1,32 @@ +/* +시작인덱스 start와 끝인덱스 end를 지정하고 result 변수를 갱신, start와 end를 좁혀가며 최대 result를 찾는다 + - start와 end 중 더 작은 값을 옮겨가며 값을 비교. + - 둘이 겹쳐지면 리턴한다. + +result를 리턴 + +시간복잡도 : O(N), 공간복잡도 : O(1) +*/ + +function maxArea(height: number[]): number { + let start = 0 + let end = height.length - 1 + let result = 0 + + function getAmount(startIdx: number, endIdx: number): number { + return (endIdx - startIdx) * Math.min(height[endIdx], height[startIdx]) + } + + while (start < end) { + const area = getAmount(start, end) + result = Math.max(result, area) + + if (height[start] < height[end]) { + start += 1 + } else { + end -= 1 + } + } + + return result +} From 583ff1e0ef67c18f1ace8d73a04e241e4ab738b4 Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: Thu, 9 Apr 2026 21:02:36 +0900 Subject: [PATCH 287/526] valid parentheses solution --- valid-parentheses/robinyoon-dev.js | 58 ++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 10 deletions(-) diff --git a/valid-parentheses/robinyoon-dev.js b/valid-parentheses/robinyoon-dev.js index 5dc3b6754d..cf45473046 100644 --- a/valid-parentheses/robinyoon-dev.js +++ b/valid-parentheses/robinyoon-dev.js @@ -3,25 +3,63 @@ * @return {boolean} */ var isValid = function (s) { - - const tempArray = []; - const pairObject = { + const bracketsObj = { ')': '(', '}': '{', ']': '[' } + const stackArray = []; + + for (let i = 0; i < s.length; i++) { - for (const ch of s) { - if (ch === '(' || ch === '{' || ch === '[') { - tempArray.push(ch); + let currentBracket = s[i]; + let isRightBracket = currentBracket in bracketsObj; + + if (!isRightBracket) { + stackArray.push(currentBracket); + continue; + } + + let isPair = stackArray[stackArray.length - 1] == bracketsObj[currentBracket]; + + if (isPair) { + stackArray.pop(); } else { - if (tempArray.pop() !== pairObject[ch]) { - return false; - } + return false; } } - return tempArray.length === 0; + return stackArray.length === 0 + }; +// -----6기 활동 시의 풀이---- +// /** +// * @param {string} s +// * @return {boolean} +// */ +// var isValid = function (s) { + +// const tempArray = []; +// const pairObject = { +// ')': '(', +// '}': '{', +// ']': '[' +// } + +// for (const ch of s) { +// if (ch === '(' || ch === '{' || ch === '[') { +// tempArray.push(ch); +// } else { +// if (tempArray.pop() !== pairObject[ch]) { +// return false; +// } +// } +// } + +// return tempArray.length === 0; +// }; + + + From d2b5c4e384e1a121ba97146c031971fa59e83d8e Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: Thu, 9 Apr 2026 21:34:43 +0900 Subject: [PATCH 288/526] container with most water solution --- container-with-most-water/robinyoon-dev.js | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 container-with-most-water/robinyoon-dev.js diff --git a/container-with-most-water/robinyoon-dev.js b/container-with-most-water/robinyoon-dev.js new file mode 100644 index 0000000000..42a372f35f --- /dev/null +++ b/container-with-most-water/robinyoon-dev.js @@ -0,0 +1,32 @@ +/** + * @param {number[]} height + * @return {number} + */ +var maxArea = function (height) { + + // 투 포인터 + // 왼쪽 포인터, 오른쪽 포인터. lower 라인의 포인터를 움직여야함. + + let leftPointer = 0; + let rightPointer = height.length - 1; + let tempMax = 0; + + while (leftPointer !== rightPointer) { + let areaHeight = Math.min(height[leftPointer], height[rightPointer]); + + let areaWidth = rightPointer - leftPointer; + + let waterArea = areaHeight * areaWidth; + + tempMax = Math.max(tempMax, waterArea); + + if (height[leftPointer] < height[rightPointer]) { + leftPointer++; + } else { + rightPointer--; + } + } + + return tempMax; + +}; From a199b08a88f7a00de7bd25de222d60aa4653b730 Mon Sep 17 00:00:00 2001 From: jla670 Date: Thu, 9 Apr 2026 16:33:39 -0700 Subject: [PATCH 289/526] container with most water solution --- container-with-most-water/jylee2033.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 container-with-most-water/jylee2033.py diff --git a/container-with-most-water/jylee2033.py b/container-with-most-water/jylee2033.py new file mode 100644 index 0000000000..e39ec0677d --- /dev/null +++ b/container-with-most-water/jylee2033.py @@ -0,0 +1,19 @@ +class Solution: + def maxArea(self, height: List[int]) -> int: + left = 0 + right = len(height) - 1 + area = min(height[left], height[right]) * (right - left) + + while left < right: + if height[left] < height[right]: + left += 1 + else: + right -= 1 + + new_area = min(height[left], height[right]) * (right - left) + area = max(area, new_area) + + return area + +# Time Complexity: O(n) +# Space Complexity: O(1) From 128600aa6d98747a3200b71b30d744db37b3a95c Mon Sep 17 00:00:00 2001 From: juhui Date: 2026年4月10日 17:36:03 +0900 Subject: [PATCH 290/526] WEEK 06 Solutions --- valid-parentheses/juhui-jeong.java | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 valid-parentheses/juhui-jeong.java diff --git a/valid-parentheses/juhui-jeong.java b/valid-parentheses/juhui-jeong.java new file mode 100644 index 0000000000..1cf1d6a63d --- /dev/null +++ b/valid-parentheses/juhui-jeong.java @@ -0,0 +1,22 @@ +class Solution { + public boolean isValid(String s) { + Stack stack = new Stack(); + + for (char c: s.toCharArray()) { + if (c == '(' || c == '{' || c == '[') { + stack.push(c); + } else { + if (stack.isEmpty()) { + return false; + } + + char top = stack.pop(); + + if (c == ')' && top != '(') return false; + if (c == '}' && top != '{') return false; + if (c == ']' && top != '[') return false; + } + } + return stack.isEmpty(); + } +} From 416d65bdd7ca635eb8c3a1733ec22aacc56c6809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <54928040+gcount85@users.noreply.github.com> Date: 2026年4月10日 18:41:09 +0900 Subject: [PATCH 291/526] Update container-with-most-water/gcount85.py Co-authored-by: Dale Seo <5466341+daleseo@users.noreply.github.com> --- container-with-most-water/gcount85.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container-with-most-water/gcount85.py b/container-with-most-water/gcount85.py index efd66495f3..0e8e0322a1 100644 --- a/container-with-most-water/gcount85.py +++ b/container-with-most-water/gcount85.py @@ -1,7 +1,7 @@ """ # Approach 투포인터로 양 끝에서 물의 양을 계산해나갑니다. -더 낮은 height인 쪽의 포인터를 줄여나가는데, 높이가 같은 경우에는 양쪽 모두 포인터를 움직입니다. +더 낮은 height인 쪽의 포인터를 줄여나가는데, 높이가 같은 경우에는 왼쪽 포인터만 움직입니다. # Complexity height의 길이가 N일 때 From 177774ea021a9feda74ac2a566902ee4a1d145f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <54928040+gcount85@users.noreply.github.com> Date: 2026年4月10日 18:42:21 +0900 Subject: [PATCH 292/526] Update valid-parentheses/gcount85.py Co-authored-by: Dale Seo <5466341+daleseo@users.noreply.github.com> --- valid-parentheses/gcount85.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/valid-parentheses/gcount85.py b/valid-parentheses/gcount85.py index e15095ca68..d8fbd9ea5d 100644 --- a/valid-parentheses/gcount85.py +++ b/valid-parentheses/gcount85.py @@ -20,6 +20,4 @@ def isValid(self, s: str) -> bool: continue if not stack or brackets[stack.pop()] != b: return False - if not stack: - return True - return False + return not stack From 40c8746cb79e3e656688033d2c5c7d2cfe90c434 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月10日 19:32:33 +0900 Subject: [PATCH 293/526] [7th batch] week 6 - sprial matirx --- spiral-matrix/liza0525.py | 81 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 spiral-matrix/liza0525.py diff --git a/spiral-matrix/liza0525.py b/spiral-matrix/liza0525.py new file mode 100644 index 0000000000..5366788886 --- /dev/null +++ b/spiral-matrix/liza0525.py @@ -0,0 +1,81 @@ +# 7기 풀이 +# 풀이 1 +# 시간 복잡도: O(n * m) +# - matrix의 가로, 세로 길이의 곱에 비례하여 시간복잡도가 계산됨(모든 칸을 다 돌기 때문) +# 공간 복잡도: O(n * m) +# - matrix를 방문할 때마다 visited를 업데이트 해주고 있어, n * m의 길이 만큼 늘어남 +class Solution: + def spiralOrder(self, matrix: List[List[int]]) -> List[int]: + len_i = len(matrix) + len_j = len(matrix[0]) + visited = set() # 확인한 인덱스의 경우에는 tuple의 형태로 넣어주려고 함 + + dirs = ((0, 1), (1, 0), (0, -1), (-1, 0)) # 시계 방향을 나타내는 tuple(오른쪽, 아래쪽, 왼쪽, 위쪽 순서) + + curr_dir_idx = 0 # 현재 방향을 나타내는 dirs의 index(0이면 오른쪽을 의미) + curr_i, curr_j = 0, 0 # 처음 시작점인 (0, 0) 인덱스를 지정 + + result = [] + + while len(visited) < len_i * len_j: # 모든 인덱스에 방문할 때까지 루프 돌기 + result.append(matrix[curr_i][curr_j]) # result에 값을 먼저 넣어주고 + visited.add((curr_i, curr_j)) # visited에 방문했다는 것을 표시 + + dir_i, dir_j = dirs[curr_dir_idx] # 현재의 진행 방향 가져오기 + + if ( + (curr_i + dir_i, curr_j + dir_j) in visited # 다음 방문할 곳이 이미 방문했던 했거나 + or not (0 <= curr_i + dir_i < len_i) # i 인덱스 범위를 벗어나거나 + or not (0 <= curr_j + dir_j < len_j) # j 인덱스 범위를 벗어나면 + ): + curr_dir_idx = (curr_dir_idx + 1) % 4 # 방향 index를 하나 올려서 + dir_i, dir_j = dirs[curr_dir_idx] # 방향을 바꿔준다. + + # curr_i, curr_j를 업데이트 하여 다음 루프에서 탐방하게 한다. + curr_i, curr_j = curr_i + dir_i, curr_j + dir_j + + return result + + +# 풀이 2 +# 시간 복잡도: O(n * m) +# - matrix의 가로, 세로 길이의 곱에 비례하여 시간복잡도가 계산됨(모든 칸을 다 돌기 때문) +# 공간 복잡도: O(1) +# - 변수 몇 개만 사용했음(풀이 1과의 가장 큰 차이) +class Solution: + def spiralOrder(self, matrix: List[List[int]]) -> List[int]: + # 각각에 대한 경계를 지정하여 계산하는 방법이다. + # 위, 아래, 왼쪽, 오른쪽에 대한 최초 경계 설정 + top, bottom, left, right = 0, len(matrix) - 1, 0, len(matrix[0]) - 1 + + # 처음 방향 설정(오른쪽으로 가기) + dir_i, dir_j = 0, 1 + + # 처음 방문 인덱스 설정 + curr_i, curr_j = 0, 0 + + result = [] + + # top은 bottom보다 커지면 안되고 + # left는 right보다 커지면 안된다. + # 이에 따라 top <= bottom and left <= right 조건으로 루프 돌기 + while top <= bottom and left <= right: + result.append(matrix[curr_i][curr_j]) # 해당 인덱스에 있는 값을 result에 넣기 + + if curr_i + dir_i < top: # 1. 다음 인덱스가 top 경계를 넘어가려고 할 때 + dir_i, dir_j = 0, 1 # 방향을 오른쪽으로 변경해주고 + left += 1 # 지나온 인덱스들이 새로운 왼쪽 경계가 되므로, left을 하나 올려준다. + elif curr_i + dir_i> bottom: # 2. 다음 인덱스가 bottom의 경계를 넘어가려고 할 때 + dir_i, dir_j = 0, -1 # 방향을 왼쪽으로 변경해주고 + right -= 1 # 지나온 인덱스들이 새로운 오른쪽 경계가 되므로, right를 하나 내려준다. + elif curr_j + dir_j < left: # 3. 다음 인덱스가 left 경계를 넘어가려고 할 때 + dir_i, dir_j = -1, 0 # 방향을 위쪽으로 변경해주고 + bottom -= 1 # 지나온 인덱스들이 새로운 아랫쪽 경계가 되므로, bottom을 하나 내려준다. + elif curr_j + dir_j> right: # 4. 다음 인덱스가 right 경계를 넘어가려고 할 떄 + dir_i, dir_j = 1, 0 # 방향을 아랫쪽으로 변경해주고 + top += 1 # 지나온 인덱스들이 새로운 윗쪽 경계가 되므로, top을 하나 올려준다. + + # curr_i, curr_j를 업데이트 하여 다음 루프에서 탐방하게 한다. + curr_i, curr_j = curr_i + dir_i, curr_j + dir_j + + return result From 716fd2a7b797504edb7c9de662b21fbe739b43db Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年4月10日 20:35:57 +0900 Subject: [PATCH 294/526] solved design-add-and... --- .../sangbeenmoon.java | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/design-add-and-search-words-data-structure/sangbeenmoon.java b/design-add-and-search-words-data-structure/sangbeenmoon.java index e69de29bb2..026c10b257 100644 --- a/design-add-and-search-words-data-structure/sangbeenmoon.java +++ b/design-add-and-search-words-data-structure/sangbeenmoon.java @@ -0,0 +1,63 @@ +import java.util.HashMap; +import java.util.Map; + +class WordDictionary { + + + Map map; + boolean isEnd = false; + + public WordDictionary() { + map = new HashMap(); + } + + public void addWord(String word) { + char ch = word.charAt(0); + WordDictionary node; + if (map.containsKey(ch)) { + node = map.get(ch); + } else { + node = new WordDictionary(); + } + + map.put(ch, node); + + if (word.length() == 1) { + node.isEnd = true; + return; + } + + node.addWord(word.substring(1)); + } + + public boolean search(String word) { + if (word.length() == 0) { + return isEnd; + } + + char ch = word.charAt(0); + WordDictionary node; + + if (ch == '.') { + for (Map.Entry entry : map.entrySet()) { + if (entry.getValue().search(word.substring(1))){ + return true; + } + } + } + + if (map.containsKey(ch)) { + node = map.get(ch); + return node.search(word.substring(1)); + } + + return false; + } +} + +/** + * Your WordDictionary object will be instantiated and called as such: + * WordDictionary obj = new WordDictionary(); + * obj.addWord(word); + * boolean param_2 = obj.search(word); + */ From e7657c59010bc76a09952cb7a0d4582c812cdcd1 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月10日 20:53:25 +0900 Subject: [PATCH 295/526] [7th batch] week 6 - longest increasing subsequence --- longest-increasing-subsequence/liza0525.py | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 longest-increasing-subsequence/liza0525.py diff --git a/longest-increasing-subsequence/liza0525.py b/longest-increasing-subsequence/liza0525.py new file mode 100644 index 0000000000..2404fbe01b --- /dev/null +++ b/longest-increasing-subsequence/liza0525.py @@ -0,0 +1,25 @@ +# 7기 풀이 +# 시간 복잡도: O(n^2) +# - 각 원소마다 이전 인덱스들을 모두 확인하므로 이중 for문을 돌아야 함 +# 공간 복잡도: O(n) +# - dp 계산을 위한 리스트는 nums의 길이에 의존 +class Solution: + def lengthOfLIS(self, nums: List[int]) -> int: + # 각 인덱스에서의 최대 길이를 저장하는 dp 리스트 + dp = [1 for _ in range(len(nums))] + + for i in range(1, len(nums)): + # i 인덱스까지의 최대 길이를 계산 하기 위해 + # 이전 인덱스들 중 가장 긴 길이를 찾아내어 저장하는 장식이다. + max_lis = 1 + for j in range(0, i): + # j 인덱스의 의미는 i보다 이전 인덱스 탐방하기 위함 + if nums[j] < nums[i]: # 이전 인덱스(j 인덱스)에 있는 값이 i 인덱스의 값보다 작다면 + # 기존의 max_lis와 j 인덱스까지의 최대 길이 값 + 1(i 인덱스 포함한 길이)를 비교하여 + # 더 큰 수를 max_list에 업데이트 해준다. + max_lis = max(max_lis, dp[j] + 1) + + # 계산된 max_lis를 dp[i]에 업데이트 + dp[i] = max_lis + + return max(dp) From 334b8f0d7743c2d59650956fd6ac6f116c51f001 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月10日 21:13:53 +0900 Subject: [PATCH 296/526] [7th batch] week 6 - design add and search words data structure --- .../liza0525.py | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 design-add-and-search-words-data-structure/liza0525.py diff --git a/design-add-and-search-words-data-structure/liza0525.py b/design-add-and-search-words-data-structure/liza0525.py new file mode 100644 index 0000000000..a0f33c6b6b --- /dev/null +++ b/design-add-and-search-words-data-structure/liza0525.py @@ -0,0 +1,80 @@ +# 7기 풀이 + +# 클래스 공간 복잡도: O(W * L) +# - W는 word의 개수, L는 word의 평균 길이. + +# addWord 메서드 +# 시간 복잡도: O(L) +# - L는 word의 길이. word의 길이만큼 탐색하며 insert함 +# 공간 복잡도: O(L) +# - L는 word의 길이. 길이만큼 재귀 스택이 쌓임 + +# search 메서드 +# 시간 복잡도: O(W * L) +# - W는 이미 삽입된 단어의 개수, L는 word의 평균 길이. +# - 최악인 조건은 word의 모든 문자들이 '.'일 때 +# 공간 복잡도: O(L) +# - L는 word의 길이. 길이만큼 재귀 스택이 쌓임 + + +DELIMITER = "$" # 끝맺음을 나타내는 DELIMITER로 "$"를 사용 + + +class WordDictionary: + def __init__(self): + self.word_dict = {} + + def addWord(self, word: str) -> None: + # 재귀를 이용해 단어를 각 문자별로 insert + def _add_word(curr_dict, word): + if not word: + # 끝맺음을 나타내는 DELIMITER로 "$"를 사용 + curr_dict[DELIMITER] = {} + return + + s = word[0] # word의 첫번째 문자 + if s not in curr_dict: # curr에 없는 경우에는 새로 key를 만든다. + curr_dict[s] = {} + + # 다음 문자를 저장하기 위한 dictionary와 + # 해당 depth에서 확인한 문자를 제외한 나머지 문자열을 가지고 다음 작업 수행 + _add_word(curr_dict[s], word[1:]) + + _add_word(self.word_dict, word) + + + def search(self, word: str) -> bool: + # 재귀를 이용해 단어를 각 문자별로 뎁스를 타고 내려가 search + def _search(curr_dict, word): + if not word: + # 더이상 검색할 문자열이 없을 땐 + # DELIMITER의 존재 여부를 보고 return + return DELIMITER in curr_dict + + s = word[0] + if s != '.' and s not in curr_dict: + # 와일드 카드 문자가 아니면서, 찾으려는 문자가 dictionary에 없으면 + # insert가 된 적이 없는 단어이므로 False로 early return + return False + elif s == '.': + # 와일드 카드 문자이면 curr_dict에 있는 모든 문자열을 가지고 다음 depth를 확인한다. + for k in curr_dict.keys(): + is_valid = _search(curr_dict[k], word[1:]) + if is_valid: + # 하나라도 True라면 search 결과가 유효하기 때문에 + # True로 early return + return True + # 모든 문자열을 탐색하고도 결과가 없다면 False return + return False + else: + # 그 외의 경우는 일반 문자열 탐색을 해야 하므로 + # 자식 문자열이 있는 curr_dict[s]와 + # 해당 depth에서 확인한 문자를 제외한 나머지 문자열을 가지고 다음 작업 수행 + return _search(curr_dict[s], word[1:]) + + return _search(self.word_dict, word) + +# Your WordDictionary object will be instantiated and called as such: +# obj = WordDictionary() +# obj.addWord(word) +# param_2 = obj.search(word) \ No newline at end of file From 714782a0cceb13db8928bbf2bbf00c51f96a1a88 Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年4月10日 21:20:47 +0900 Subject: [PATCH 297/526] week6: valid-parentheses --- valid-parentheses/reeseo3o.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 valid-parentheses/reeseo3o.js diff --git a/valid-parentheses/reeseo3o.js b/valid-parentheses/reeseo3o.js new file mode 100644 index 0000000000..2177874951 --- /dev/null +++ b/valid-parentheses/reeseo3o.js @@ -0,0 +1,20 @@ +const isValid = (s) => { + const stack = []; + const map = { + "(": ")", + "[": "]", + "{": "}" + }; + + for (const char of s) { + if (map[char]) { + console.log(char); + stack.push(char); + } else { + if (stack.length === 0 || map[stack.pop()] !== char) { + return false; + } + } + } + return stack.length === 0; +} From 1686e6364109d919e7f6358e9591c36d4bbeed15 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月10日 21:30:50 +0900 Subject: [PATCH 298/526] [7th batch] week 6 - container with most water --- container-with-most-water/liza0525.py | 33 +++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/container-with-most-water/liza0525.py b/container-with-most-water/liza0525.py index c81280a514..de5de33a8f 100644 --- a/container-with-most-water/liza0525.py +++ b/container-with-most-water/liza0525.py @@ -29,3 +29,36 @@ def maxArea(self, height: List[int]) -> int: ) return result_area + + +# 7기 풀이 +# 시간 복잡도: O(n) +# - two point 알고리즘을 이용하기 때문에 heights 변수의 길이인 n에 시간복잡도가 정해짐 +# 공간 복잡도: O(1) +# - 몇 개의 변수만 사용함 +class Solution: + def maxArea(self, height: List[int]) -> int: + # 양 끝 포인터 지정 + start, end = 0, len(height) - 1 + + # max_area는 현재 포인터들을 이용했을 때의 넓이 계산 + # 이때 높이는 작은 쪽으로 선택하여 계산해야 함 + max_area = min(height[start], height[end]) * (end - start) + + # start가 end보다 작을 때 루프 돌기 + while start < end: + # 문제의 핵심 아이디어는, 높이가 큰 쪽을 움직이면 얻을 수 있는 최선이 현재보다 클 수 없다. + # 이는, start의 높이와 end의 높이 중 큰 쪽의 포인터를 고정하여 움직여야 한다는 것 + # (물의 높이는 작은 쪽에 의해 정해지는데, 큰 쪽 포인터를 움직이면 x 길이만 짧아지게 되어 오히려 넓이이 줄어듦) + if height[start] < height[end]: + # start 쪽의 높이가 낮으면 start를 움직임 + start += 1 + else: + # end 쪽의 높이가 낮으면 end를 움직임 + end -= 1 + + # 포인터를 옮기고 난 후의 넓이를 계산하여, 기존의 max_area와 비교하여 큰 쪽으로 업데이트 + curr_area = min(height[start], height[end]) * (end - start) + max_area = max(max_area, curr_area) + + return max_area \ No newline at end of file From aa6d6a929667a16ff75d96f06171a4885ada5409 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月10日 21:31:19 +0900 Subject: [PATCH 299/526] [7th batch] week 6 - valid parentheses --- valid-parentheses/liza0525.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/valid-parentheses/liza0525.py b/valid-parentheses/liza0525.py index 2edcd060a4..df1bd6c5e2 100644 --- a/valid-parentheses/liza0525.py +++ b/valid-parentheses/liza0525.py @@ -61,3 +61,37 @@ def isValid(self, s: str) -> bool: if stack: return False return True + + + +# 7기 풀이 +# 시간 복잡도: O(n) +# - s의 길이 n에 시간복잡도가 정해짐 +# 공간 복잡도: O(n) +# - 왼쪽 괄호를 저장할 stacks(list) 변수의 길이는 s의 길이에 의해 정해짐 +# - stack의 최대 길이는 s가 모두 왼쪽 괄호로 되어 있을 때 +class Solution: + def isValid(self, s: str) -> bool: + # 오른쪽 괄호가 들어올 때의 쌍을 쉽게 찾기 위해 만든 dictionary + brackets = {")": "(", "}": "{", "]": "["} + + # 왼쪽 괄호를 저장할 list + stacks = [] + + for ss in s: + if stacks and ss in brackets.keys(): + # stacks에 괄호가 저장되어 있으면서, ss로 오른쪽 괄호가 들어오면 + # 쌍을 비교 + if stacks[-1] != brackets[ss]: + # stacks의 마지막 문자(가장 늦게 들어온 왼쪽 괄호)와 현재 들어온 오른쪽 괄호의 쌍이 같지 않으면 + # 괄호의 쌍이 맞지 않으므로 False를 early return + return False + else: + # 쌍이 맞는다면 stacks에 있는 마지막 왼쪽 괄호는 더이상 비교할 필요가 없으므로 pop + stacks.pop() + else: + # ss가 왼쪽 괄호인 경우엔 stacks에 쌓아준다 + stacks.append(ss) + + # 모든 쌍비교를 하고 stacks에 괄호가 남아있는 지 여부를 return + return not stacks From 95d2080838b769f0d0885d38a1fdac18f6f74863 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月10日 21:36:49 +0900 Subject: [PATCH 300/526] add lines --- container-with-most-water/liza0525.py | 2 +- design-add-and-search-words-data-structure/liza0525.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/container-with-most-water/liza0525.py b/container-with-most-water/liza0525.py index de5de33a8f..032b648f9b 100644 --- a/container-with-most-water/liza0525.py +++ b/container-with-most-water/liza0525.py @@ -61,4 +61,4 @@ def maxArea(self, height: List[int]) -> int: curr_area = min(height[start], height[end]) * (end - start) max_area = max(max_area, curr_area) - return max_area \ No newline at end of file + return max_area diff --git a/design-add-and-search-words-data-structure/liza0525.py b/design-add-and-search-words-data-structure/liza0525.py index a0f33c6b6b..dbeed69721 100644 --- a/design-add-and-search-words-data-structure/liza0525.py +++ b/design-add-and-search-words-data-structure/liza0525.py @@ -77,4 +77,4 @@ def _search(curr_dict, word): # Your WordDictionary object will be instantiated and called as such: # obj = WordDictionary() # obj.addWord(word) -# param_2 = obj.search(word) \ No newline at end of file +# param_2 = obj.search(word) From f2469906842cbae647392a0b93c9a1a8447e2032 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年4月10日 21:52:47 +0900 Subject: [PATCH 301/526] solved spiral-matrix. --- spiral-matrix/sangbeenmoon.py | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 spiral-matrix/sangbeenmoon.py diff --git a/spiral-matrix/sangbeenmoon.py b/spiral-matrix/sangbeenmoon.py new file mode 100644 index 0000000000..90cce34edb --- /dev/null +++ b/spiral-matrix/sangbeenmoon.py @@ -0,0 +1,40 @@ +# 우 -> 하 -> 좌 -> 상 + +class Solution: + def spiralOrder(self, matrix: List[List[int]]) -> List[int]: + dx = [1, 0, -1, 0] + dy = [0, 1, 0, -1] + + rows, cols = len(matrix), len(matrix[0]) + + visited = [[False] * cols for _ in range(rows)] + + answer = [] + + def dfs(xx: int, yy:int, d:int): + + i = d + cnt = 0 + while cnt <= 5: + nx = xx + dx[i] + ny = yy + dy[i] + + if 0 <= nx and nx < cols and 0 <= ny and ny < rows: + if not visited[ny][nx]: + visited[ny][nx] = True + answer.append(matrix[ny][nx]) + dfs(nx,ny,i) + return + if i == 3: + i = 0 + else: + i = i + 1 + cnt = cnt + 1 + + + + visited[0][0] = True + answer.append(matrix[0][0]) + dfs(0,0,0) + + return answer From 66bba7266035f7d9c0efe32b43ea3a13f57298af Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年4月11日 00:41:27 +0900 Subject: [PATCH 302/526] week6: container-with-most-water --- container-with-most-water/reeseo3o.js | 36 +++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 container-with-most-water/reeseo3o.js diff --git a/container-with-most-water/reeseo3o.js b/container-with-most-water/reeseo3o.js new file mode 100644 index 0000000000..48774049c2 --- /dev/null +++ b/container-with-most-water/reeseo3o.js @@ -0,0 +1,36 @@ +// Brute Force +// Time Complexity: O(n^2) +// Space Complexity: O(1) +const maxAreaBrute = (height) => { + let maxWater = 0; + for (let i = 0; i < height.length; i++) { + for (let j = i + 1; j < height.length; j++) { + const area = Math.min(height[i], height[j]) * (j - i); + maxWater = Math.max(maxWater, area); + } + } + return maxWater; +}; + +// Two Pointer +// Time Complexity: O(n) +// Space Complexity: O(1) +const maxArea = (height) => { + let left = 0; + let right = height.length - 1; + let maxWater = 0; + + while (left < right) { + const area = Math.min(height[left], height[right]) * (right - left); + + maxWater = Math.max(maxWater, area); + + if (height[left] < height[right]) { + left++; + } else { + right--; + } + } + + return maxWater; +}; From 95b8c702385cc04f15343b98061ec945b0ba4c70 Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年4月10日 14:34:52 -0700 Subject: [PATCH 303/526] design add and search words data structure solution --- .../jylee2033.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 design-add-and-search-words-data-structure/jylee2033.py diff --git a/design-add-and-search-words-data-structure/jylee2033.py b/design-add-and-search-words-data-structure/jylee2033.py new file mode 100644 index 0000000000..77b6492678 --- /dev/null +++ b/design-add-and-search-words-data-structure/jylee2033.py @@ -0,0 +1,41 @@ +class WordDictionary: + + def __init__(self): + self.children = {} # key: character, value: WordDictionary node + self.is_end = False + + # Time Complexity: O(n), n - length of the word + # Space Complexity: O(N * n), N - number of words, n - length of the word + def addWord(self, word: str) -> None: + cur = self + + for char in word: + if char not in cur.children: + cur.children[char] = WordDictionary() + cur = cur.children[char] + + cur.is_end = True + + # Time Complexity: O(26^n), n - length of the word + # Space Complexity: O(n^2), n - length of the word + def search(self, word: str) -> bool: + cur = self + + for i, char in enumerate(word): + if char == ".": + for child in cur.children.values(): + if child.search(word[i + 1:]): + return True + return False + + elif char not in cur.children: + return False + + cur = cur.children[char] + + return cur.is_end + +# Your WordDictionary object will be instantiated and called as such: +# obj = WordDictionary() +# obj.addWord(word) +# param_2 = obj.search(word) From 714420c42145e84fe5f160c21a571f74c57bbd21 Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年4月10日 17:41:12 -0700 Subject: [PATCH 304/526] add hello --- container-with-most-water/jylee2033.py | 1 + 1 file changed, 1 insertion(+) diff --git a/container-with-most-water/jylee2033.py b/container-with-most-water/jylee2033.py index e39ec0677d..a068fdf2c6 100644 --- a/container-with-most-water/jylee2033.py +++ b/container-with-most-water/jylee2033.py @@ -17,3 +17,4 @@ def maxArea(self, height: List[int]) -> int: # Time Complexity: O(n) # Space Complexity: O(1) +# Hello From e187b7f40de57b528ce0faa6c984a3a3230fa2aa Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年4月10日 18:59:19 -0700 Subject: [PATCH 305/526] remove hello --- container-with-most-water/jylee2033.py | 1 - 1 file changed, 1 deletion(-) diff --git a/container-with-most-water/jylee2033.py b/container-with-most-water/jylee2033.py index a068fdf2c6..e39ec0677d 100644 --- a/container-with-most-water/jylee2033.py +++ b/container-with-most-water/jylee2033.py @@ -17,4 +17,3 @@ def maxArea(self, height: List[int]) -> int: # Time Complexity: O(n) # Space Complexity: O(1) -# Hello From 41b9640974f97a9fd4a57bf07f54db187b243a8c Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年4月11日 12:54:28 +0900 Subject: [PATCH 306/526] add: containerWithMostWater solution --- container-with-most-water/Cyjin-jani.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 container-with-most-water/Cyjin-jani.js diff --git a/container-with-most-water/Cyjin-jani.js b/container-with-most-water/Cyjin-jani.js new file mode 100644 index 0000000000..f179de04af --- /dev/null +++ b/container-with-most-water/Cyjin-jani.js @@ -0,0 +1,22 @@ +// tc: O(n); +// sc: O(1); +const maxArea = function (height) { + let max = 0; + let leftIdx = 0; + let rightIdx = height.length - 1; + + while (leftIdx < rightIdx) { + const width = rightIdx - leftIdx; + const minHeight = Math.min(height[leftIdx], height[rightIdx]); + const area = width * minHeight; + max = Math.max(max, area); + + if (height[leftIdx]> height[rightIdx]) { + rightIdx -= 1; + } else { + leftIdx += 1; + } + } + + return max; +}; From b942db6ddf52d0829184666819e9ca85f9d37356 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月11日 13:16:14 +0900 Subject: [PATCH 307/526] spiral-matrix solution --- spiral-matrix/hyeri0903.py | 43 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 spiral-matrix/hyeri0903.py diff --git a/spiral-matrix/hyeri0903.py b/spiral-matrix/hyeri0903.py new file mode 100644 index 0000000000..1503af8473 --- /dev/null +++ b/spiral-matrix/hyeri0903.py @@ -0,0 +1,43 @@ +class Solution: + def spiralOrder(self, matrix: List[List[int]]) -> List[int]: + ''' + 1.문제: 나선형으로 numbers return + 2.조건 + - m, n 길이 최소 = 1. 최대 = 10 + - 원소 값 최소 = -100, 최대 = 100 + 3.풀이 + - 마지막 컬럼에 오면 index j change + ''' + + if len(matrix) == 1 and len(matrix[0]) == 1: + return [matrix[0][0]] + + left = 0 + right = len(matrix[0]) - 1 + top = 0 + bottom = len(matrix) - 1 + result = [] + + while top <= bottom and left <= right: + #left -> right + for i in range(left, right + 1): + result.append(matrix[top][i]) + top += 1 + + #top -> bottom + for i in range(top, bottom + 1): + result.append(matrix[i][right]) + right -= 1 + + #right -> left + if top <= bottom: + for i in range(right, left - 1, -1): + result.append(matrix[bottom][i]) + bottom -= 1 + + #bottom -> top + if left <= right: + for i in range(bottom, top - 1, -1): + result.append(matrix[i][left]) + left += 1 + return result From e75b852b3b7b60db7d6d4840e7ab484b4664f19d Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月11日 13:37:22 +0900 Subject: [PATCH 308/526] design-add-and-search-words-data-structure solution --- .../hyeri0903.py | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 design-add-and-search-words-data-structure/hyeri0903.py diff --git a/design-add-and-search-words-data-structure/hyeri0903.py b/design-add-and-search-words-data-structure/hyeri0903.py new file mode 100644 index 0000000000..9bc10f73bd --- /dev/null +++ b/design-add-and-search-words-data-structure/hyeri0903.py @@ -0,0 +1,47 @@ +class TrieNode: + def __init__(self): + self.children = {} + self.is_end = False + +class WordDictionary: + ''' 너무 어려워숴 풀이 봤어요..ᅲᅲ''' + + def __init__(self): + self.root = TrieNode() + + def addWord(self, word: str) -> None: + node = self.root + + for ch in word: + #node 에 존재하지 않으면 TrieNode 생성 + if ch not in node.children: + node.children[ch] = TrieNode() + #node 에 children 저장 + node = node.children[ch] + node.is_end = True + + def dfs(self, node, word, i): + if i == len(word): + return node.is_end + + #일반 문자일 경우 + ch = word[i] + if ch != '.': + if ch not in node.children: + return False + return self.dfs(node.children[ch], word, i + 1) + #.이 포함된 경우 -> 모든 경우 탐색 + for child in node.children.values(): + if self.dfs(child, word, i + 1): + return True + return False + + def search(self, word: str) -> bool: + return self.dfs(self.root, word, 0) + + + +# Your WordDictionary object will be instantiated and called as such: +# obj = WordDictionary() +# obj.addWord(word) +# param_2 = obj.search(word) From 3aac77a9fa60d5672717c36d3a02f3c7eee37695 Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年4月11日 13:44:56 +0900 Subject: [PATCH 309/526] add: 257 solution --- .../Cyjin-jani.js | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 design-add-and-search-words-data-structure/Cyjin-jani.js diff --git a/design-add-and-search-words-data-structure/Cyjin-jani.js b/design-add-and-search-words-data-structure/Cyjin-jani.js new file mode 100644 index 0000000000..c009063992 --- /dev/null +++ b/design-add-and-search-words-data-structure/Cyjin-jani.js @@ -0,0 +1,47 @@ +var WordDictionary = function () { + this.dictionary = new Set(); +}; + +/** + * @param {string} word + * @return {void} + */ +WordDictionary.prototype.addWord = function (word) { + this.dictionary.add(word); +}; + +/** + * @param {string} word + * @return {boolean} + */ + +// tc: O(n * k), n: dictionary size, k: word length => O(n) in worst case +// sc: O(1) +WordDictionary.prototype.search = function (word) { + if (!word.includes('.')) { + return this.dictionary.has(word); + } + + for (const stored of this.dictionary) { + if (stored.length !== word.length) continue; + + let isMatch = true; + for (let i = 0; i < word.length; i++) { + if (word[i] === '.') continue; + if (word[i] !== stored[i]) { + isMatch = false; + break; + } + } + if (isMatch) return true; + } + + return false; +}; + +/** + * Your WordDictionary object will be instantiated and called as such: + * var obj = new WordDictionary() + * obj.addWord(word) + * var param_2 = obj.search(word) + */ From e461ea151097f75403e2382b9fb7b4b26cb25c69 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年4月11日 17:24:34 +0900 Subject: [PATCH 310/526] =?UTF-8?q?6=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=205=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- container-with-most-water/hwi-middle.cpp | 30 ++++++++ .../hwi-middle.cpp | 71 +++++++++++++++++++ longest-increasing-subsequence/hwi-middle.cpp | 23 ++++++ spiral-matrix/hwi-middle.cpp | 54 ++++++++++++++ valid-parentheses/hwi-middle.cpp | 50 +++++++++++++ 5 files changed, 228 insertions(+) create mode 100644 container-with-most-water/hwi-middle.cpp create mode 100644 design-add-and-search-words-data-structure/hwi-middle.cpp create mode 100644 longest-increasing-subsequence/hwi-middle.cpp create mode 100644 spiral-matrix/hwi-middle.cpp create mode 100644 valid-parentheses/hwi-middle.cpp diff --git a/container-with-most-water/hwi-middle.cpp b/container-with-most-water/hwi-middle.cpp new file mode 100644 index 0000000000..78e1b261de --- /dev/null +++ b/container-with-most-water/hwi-middle.cpp @@ -0,0 +1,30 @@ +class Solution { +public: + int maxArea(vector& height) { + int l = 0; + int r = height.size() - 1; + + int area = 0; + + // 투 포인터로 접근 + while (l < r) + { + // 너비(물 저장량)를 구하고 최댓값 업데이트 + area = max(area, (r - l) * min(height[r], height[l])); + + // 높이가 낮은 쪽의 커서를 이동 + // -> 높은 쪽의 커서를 움직이면 무조건 손해 + // -> 너비는 줄어들고 높이까지 줄어드니까 + if (height[l] < height[r]) + { + l++; + } + else + { + r--; + } + } + + return area; + } +}; diff --git a/design-add-and-search-words-data-structure/hwi-middle.cpp b/design-add-and-search-words-data-structure/hwi-middle.cpp new file mode 100644 index 0000000000..a81b65a42f --- /dev/null +++ b/design-add-and-search-words-data-structure/hwi-middle.cpp @@ -0,0 +1,71 @@ +// 풀이 접근: Trie로 해결 + +class WordDictionary { +public: + WordDictionary() { + mRoot = make_unique(); // RAII를 위해 스마트 포인터 사용 + } + + void addWord(string word) { + Node* curNode = mRoot.get(); + for (char c : word) + { + auto& child = curNode->children[c - 'a']; + if (child == nullptr) + { + child = make_unique(); + } + + curNode = child.get(); + } + + curNode->isWord = true; + } + + bool search(string word) { + return search_impl(word, mRoot.get()); + } + +private: + struct Node + { + bool isWord = false; + unique_ptr children[26]; + }; + + unique_ptr mRoot; + + // 복사 없는 substr을 위해 std::string_view 활용 + bool search_impl(string_view word, Node* root) + { + Node* curNode = root; + for (int i = 0; i < word.size(); ++i) + { + char c = word[i]; + if (c == '.') // '.'은 와일드 카드이므로 자식 노드를 모두 순회하며 시도 + { + for (auto& p : curNode->children) + { + if (p != nullptr && search_impl(word.substr(i + 1), p.get())) + { + return true; + } + } + + return false; + } + else + { + auto& child = curNode->children[c - 'a']; + if (child == nullptr) + { + return false; + } + + curNode = child.get(); + } + } + + return curNode->isWord; + } +}; diff --git a/longest-increasing-subsequence/hwi-middle.cpp b/longest-increasing-subsequence/hwi-middle.cpp new file mode 100644 index 0000000000..213a044af6 --- /dev/null +++ b/longest-increasing-subsequence/hwi-middle.cpp @@ -0,0 +1,23 @@ +class Solution { +public: + int lengthOfLIS(vector& nums) { + int n = nums.size(); + vector d(n); // 점화식: d[i] = a[i]를 마지막으로 하는 LIS 길이 + + for (int i = 0; i < n; ++i) + { + d[i] = 1; // 최솟값은 1 + for (int j = 0; j < i; ++j) + { + // 증가하는 부분수열이고, 기존에 구한 길이보다 길면 업데이트 + if (nums[j] < nums[i] && d[j] + 1> d[i]) + { + d[i] = d[j] + 1; + } + } + } + + // d의 최댓값 반환 + return *max_element(d.begin(), d.end()); + } +}; diff --git a/spiral-matrix/hwi-middle.cpp b/spiral-matrix/hwi-middle.cpp new file mode 100644 index 0000000000..65c55dc583 --- /dev/null +++ b/spiral-matrix/hwi-middle.cpp @@ -0,0 +1,54 @@ +class Solution { +public: + vector spiralOrder(vector>& matrix) { + int m = matrix.size(); + int n = matrix[0].size(); + + int top = 0; + int bottom = m - 1; + int left = 0; + int right = n - 1; + + vector v; + v.reserve(m * n); + + while(top <= bottom && left <= right) + { + // 오른쪽으로 이동 + for (int i = left; i <= right; ++i) + { + v.push_back(matrix[top][i]); + } + top++; + + // 아래쪽으로 이동 + for (int i = top; i <= bottom; ++i) + { + v.push_back(matrix[i][right]); + } + right--; + + // 왼쪽으로 이동 + if (top <= bottom) + { + for (int i = right; i>= left; --i) + { + v.push_back(matrix[bottom][i]); + } + bottom--; + } + + // 위쪽으로 이동 + if (left <= right) + { + for (int i = bottom; i>= top; --i) + { + v.push_back(matrix[i][left]); + } + left++; + } + } + + return v; + } +}; diff --git a/valid-parentheses/hwi-middle.cpp b/valid-parentheses/hwi-middle.cpp new file mode 100644 index 0000000000..67423bb1bb --- /dev/null +++ b/valid-parentheses/hwi-middle.cpp @@ -0,0 +1,50 @@ +class Solution { +public: + bool isValid(string s) { + stack st; // 여는 괄호를 저장할 스택 + + for (char ch : s) + { + if (isOpening(ch)) // 여는 괄호라면 스택에 push + { + st.push(ch); + continue; + } + + if (st.empty()) // 스택이 비었는데 닫는 괄호면 invalid + { + return false; + } + + char t = st.top(); + st.pop(); + + // 괄호 쌍이 맞으면 계속 진행 + if ((ch == ')' && t == '(') + || (ch == ']' && t == '[') + || (ch == '}' && t == '{')) + { + continue; + } + + // 괄호 쌍이 맞지 않으면 invalid + return false; + } + + return st.empty(); + } + +private: + bool isOpening(char c) + { + switch(c) + { + case '(': + case '[': + case '{': + return true; + } + + return false; + } +}; From dd2cee8742c27b24322cfb71981ae0d6cbc6d098 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年4月11日 18:09:09 +0900 Subject: [PATCH 311/526] =?UTF-8?q?=EC=8B=9C=EA=B0=84=EB=B3=B5=EC=9E=A1?= =?UTF-8?q?=EB=8F=84=EB=A5=BC=20=EA=B0=9C=EC=84=A0=ED=95=9C=20=ED=92=80?= =?UTF-8?q?=EC=9D=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Longest Increasing Subsequence --- longest-increasing-subsequence/hwi-middle.cpp | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/longest-increasing-subsequence/hwi-middle.cpp b/longest-increasing-subsequence/hwi-middle.cpp index 213a044af6..4427cb0eca 100644 --- a/longest-increasing-subsequence/hwi-middle.cpp +++ b/longest-increasing-subsequence/hwi-middle.cpp @@ -1,3 +1,4 @@ +// O(n^2) 풀이 class Solution { public: int lengthOfLIS(vector& nums) { @@ -21,3 +22,27 @@ class Solution { return *max_element(d.begin(), d.end()); } }; + +// O(n log n) 풀이 +class Solution { +public: + int lengthOfLIS(vector& nums) { + int n = nums.size(); + vector d; // d[i] = 길이가 i + 1인 LIS의 가장 작은 마지막 값 + + for (int i = 0; i < n; ++i) + { + auto it = lower_bound(d.begin(), d.end(), nums[i]); + if (it == d.end()) // nums[i]가 d의 모든 원소보다 큰 경우 + { + d.push_back(nums[i]); + } + else // nums[i]의 자리를 찾은 경우 + { + *it = nums[i]; // 그냥 대체하는게 이득임 -> 길이는 유지됐고, 더 이어붙일 수 있는 수의 범위는 늘어나므로 + } + } + + return d.size(); + } +}; From 5054a1f79722911d24ffc7ef8ca2ab6e645e8ca0 Mon Sep 17 00:00:00 2001 From: robin Date: 2026年4月11日 20:49:07 +0900 Subject: [PATCH 312/526] week 6 solution --- container-with-most-water/nowrobin.js | 21 ++++++++++++++++++++ longest-increasing-subsequence/nowrobin.js | 17 ++++++++++++++++ valid-parentheses/nowrobin.js | 23 ++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 container-with-most-water/nowrobin.js create mode 100644 longest-increasing-subsequence/nowrobin.js create mode 100644 valid-parentheses/nowrobin.js diff --git a/container-with-most-water/nowrobin.js b/container-with-most-water/nowrobin.js new file mode 100644 index 0000000000..7211c54f0b --- /dev/null +++ b/container-with-most-water/nowrobin.js @@ -0,0 +1,21 @@ +/** + * @param {number[]} height + * @return {number} + */ +var maxArea = function(height) { + let maxArea = 0; + let left = 0; + let right = height.length - 1; + + while (left < right) { + maxArea = Math.max(maxArea, (right - left) * Math.min(height[left], height[right])); + + if (height[left] < height[right]) { + left++; + } else { + right--; + } + } + + return maxArea; +}; diff --git a/longest-increasing-subsequence/nowrobin.js b/longest-increasing-subsequence/nowrobin.js new file mode 100644 index 0000000000..6127d91381 --- /dev/null +++ b/longest-increasing-subsequence/nowrobin.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} nums + * @return {number} + */ +var lengthOfLIS = function(nums) { + const dp = new Array(nums.length).fill(1); + + for (let i = 0; i < nums.length; i++) { + for (let j = 0; j < i; j++) { + if (nums[j] < nums[i]) { + dp[i] = Math.max(dp[i], dp[j] + 1); + } + } + } + + return Math.max(...dp); +}; diff --git a/valid-parentheses/nowrobin.js b/valid-parentheses/nowrobin.js new file mode 100644 index 0000000000..d38d555460 --- /dev/null +++ b/valid-parentheses/nowrobin.js @@ -0,0 +1,23 @@ +/** + * @param {string} s + * @return {boolean} + */ +var isValid = function(s) { + const a = [...s] + const stack =[] + const mapping = {} + mapping[')'] = '(' + mapping[']'] = '[' + mapping['}'] = '{' + + for(let i of a){ + if(Object.values(mapping).includes(i)){ + stack.push(i) + }else if (mapping.hasOwnProperty(i)){ + if(!stack.length || mapping[i] !== stack.pop()){ + return false + } + } + } + return stack.length === 0 +}; From aa060336bb03e9e6b355d24d84a8d19e480745de Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年4月11日 23:17:28 +0900 Subject: [PATCH 313/526] =?UTF-8?q?feat:=20=EC=96=91=EC=AA=BD=EC=9D=98=20?= =?UTF-8?q?=ED=8F=AC=EC=9D=B8=ED=84=B0=EB=A5=BC=20=EC=9D=B4=EB=8F=99?= =?UTF-8?q?=EC=8B=9C=ED=82=A4=EB=8A=94=20=EB=B0=A9=EB=B2=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- container-with-most-water/gyeo-ri.py | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 container-with-most-water/gyeo-ri.py diff --git a/container-with-most-water/gyeo-ri.py b/container-with-most-water/gyeo-ri.py new file mode 100644 index 0000000000..0ba8444e51 --- /dev/null +++ b/container-with-most-water/gyeo-ri.py @@ -0,0 +1,41 @@ +class Solution: + def maxArea(self, height: list[int]) -> int: + max_area = 0 + left_idx = 0 + right_idx = len(height) - 1 + + while left_idx < right_idx: + left_h = height[left_idx] + right_h = height[right_idx] + + max_area = max(max_area, (right_idx - left_idx) * min(left_h, right_h)) + + if left_h < right_h: + left_idx += 1 + else: + right_idx -= 1 + + return max_area + + +if __name__ == "__main__": + test_cases = [ + ([1, 1], 1), + ([1, 2, 1], 2), + ([4, 3, 2, 1, 4], 16), + ([1, 8, 6, 2, 5, 4, 8, 3, 7], 49), + ([1, 2, 4, 3], 4), + ([2, 3, 10, 5, 7, 8, 9], 36), + ([1, 3, 2, 5, 25, 24, 5], 24), + ([5, 5, 5, 5, 5], 20), + ([1, 1000, 1, 1000, 1], 2000), + ([1, 2, 3, 4, 5, 6], 9), + ] + + solution = Solution() + for idx, case_ in enumerate(test_cases): + height, answer = case_ + result = solution.maxArea(height) + assert ( + answer == result + ), f"Test Case {idx + 1} Failed: Expected {answer}, Got {result}" From c1637f6fca28a151edf07fb863049a440432b4fc Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年4月11日 23:24:58 +0900 Subject: [PATCH 314/526] =?UTF-8?q?fix:=20=EC=95=8C=EA=B3=A0=EB=A6=AC?= =?UTF-8?q?=EC=A6=98=EC=9D=80=20=EA=B7=B8=EB=8C=80=EB=A1=9C=20=EC=9C=A0?= =?UTF-8?q?=EC=A7=80=ED=95=98=EB=90=98=20=EA=B0=80=EB=8F=85=EC=84=B1?= =?UTF-8?q?=EC=9D=84=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- container-with-most-water/gyeo-ri.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/container-with-most-water/gyeo-ri.py b/container-with-most-water/gyeo-ri.py index 0ba8444e51..6dc8e3702e 100644 --- a/container-with-most-water/gyeo-ri.py +++ b/container-with-most-water/gyeo-ri.py @@ -1,19 +1,20 @@ class Solution: def maxArea(self, height: list[int]) -> int: + left, right = 0, len(height) - 1 max_area = 0 - left_idx = 0 - right_idx = len(height) - 1 - while left_idx < right_idx: - left_h = height[left_idx] - right_h = height[right_idx] + while left < right: + left_height, right_height = height[left], height[right] + min_height = min(left_height, right_height) + width = right - left - max_area = max(max_area, (right_idx - left_idx) * min(left_h, right_h)) + current_area = width * min_height + max_area = max(max_area, current_area) - if left_h < right_h: - left_idx += 1 + if left_height < right_height: + left += 1 else: - right_idx -= 1 + right -= 1 return max_area From 3771ae247b91f0f4405c770241146b56142c8098 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年4月11日 23:27:33 +0900 Subject: [PATCH 315/526] =?UTF-8?q?feat:=20=EA=B2=B0=EA=B3=BC=20=EC=9A=94?= =?UTF-8?q?=EC=95=BD=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- container-with-most-water/gyeo-ri.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/container-with-most-water/gyeo-ri.py b/container-with-most-water/gyeo-ri.py index 6dc8e3702e..1a72646f15 100644 --- a/container-with-most-water/gyeo-ri.py +++ b/container-with-most-water/gyeo-ri.py @@ -1,3 +1,12 @@ +""" +[결과 요약] +# 시도한 로직 수: 3 + 1. 모든 결과룰 순회하면서 시간복잡도 O(n^2)을 시도 -> LeetCode에서 Time Limit Exceed 발생 + 2. 리스트 양쪽 끝에서 포인터를 이동하는 알고리즘: 시간/공간 모두 O(n) + 3. (2)의 로직은 유지한 채로 코드 가독성을 개선(알고리즘의 흐름을 쉽게 이해할 수 있도록) +""" + + class Solution: def maxArea(self, height: list[int]) -> int: left, right = 0, len(height) - 1 From 892a5b15d885166bde6a5485e3442d58abdaceff Mon Sep 17 00:00:00 2001 From: Dia Date: 2026年4月12日 00:08:23 +0900 Subject: [PATCH 316/526] feat: implement function to validate bracket pairs in a string --- valid-parentheses/kangdaia.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 valid-parentheses/kangdaia.py diff --git a/valid-parentheses/kangdaia.py b/valid-parentheses/kangdaia.py new file mode 100644 index 0000000000..75f9e0d525 --- /dev/null +++ b/valid-parentheses/kangdaia.py @@ -0,0 +1,23 @@ +class Solution: + def isValid(self, s: str) -> bool: + """s에 있는 bracket들의 쌍이 맞는지 확인하는 함수 + 시간 복잡도: O(n), 공간 복잡도: O(n) + + Args: + s (str): bracket {}, [], ()로 이루어진 문자열 + + Returns: + bool: bracket들의 쌍이 맞는지 여부 + """ + stack = [] + pair = {"{": "}", "[": "]", "(": ")"} + for ch in s: + if ch in pair: + stack.append(ch) + elif len(stack) == 0: + return False + else: + last = stack.pop() + if pair[last] != ch: + return False + return True if len(stack) == 0 else False From 4b8828d77aef823295a50e70a7dfe88aa1b9034a Mon Sep 17 00:00:00 2001 From: Dia Date: 2026年4月12日 00:17:51 +0900 Subject: [PATCH 317/526] feat: implement maxArea function to calculate the maximum water container area --- container-with-most-water/kangdaia.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 container-with-most-water/kangdaia.py diff --git a/container-with-most-water/kangdaia.py b/container-with-most-water/kangdaia.py new file mode 100644 index 0000000000..13489c2b20 --- /dev/null +++ b/container-with-most-water/kangdaia.py @@ -0,0 +1,15 @@ +class Solution: + def maxArea(self, height: list[int]) -> int: + # 가장 멀리 떨어져 있으면서 높이가 비슷한 막대기? + max_area = 0 + i, j = 0, len(height) - 1 + while i < j: + left, right = height[i], height[j] + area = min(left, right) * (j - i) + if area> max_area: + max_area = area + if left < right: + i += 1 + else: + j -= 1 + return max_area From b41a68953e58bdfcee9d7e3f213b50015972966f Mon Sep 17 00:00:00 2001 From: Dia Date: 2026年4月12日 00:34:43 +0900 Subject: [PATCH 318/526] feat: implement spiralOrder function to return elements of a 2D matrix in spiral order --- spiral-matrix/kangdaia.py | 46 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 spiral-matrix/kangdaia.py diff --git a/spiral-matrix/kangdaia.py b/spiral-matrix/kangdaia.py new file mode 100644 index 0000000000..1862da80e4 --- /dev/null +++ b/spiral-matrix/kangdaia.py @@ -0,0 +1,46 @@ +class Solution: + def spiralOrder(self, matrix: list[list[int]]) -> list[int]: + """ + 주어진 2D 행렬을 나선형으로 순회하여 요소들을 반환하는 함수 + + 방법: + 1. transpose 행렬을 만들어 열을 쉽게 접근할 수 있도록 함 + 2. while 루프를 사용하여 나선형으로 순회 + 3. 각 단계에서 top row, right column, bottom row, left column을 순서대로 추가 + 4. 각 단계가 끝날 때마다 row와 col을 증가시켜 다음 레이어로 이동 + + 시간복잡도 O(m*n), 공간복잡도 O(m*n) + + Args: + matrix (list[list[int]]): 2D 행렬 + + Returns: + list[int]: 나선형으로 순회한 요소들의 리스트 + """ + row, col = 0, 0 + m, n = len(matrix), len(matrix[0]) + t_matrix = list(zip(*matrix)) + spiral = [] + while row < m and col < n: + top, left = row, col + bottom, right = m - row - 1, n - col - 1 + if top> bottom or left> right: + break + # first row: left -> right + first_row = matrix[top][left : right + 1] + spiral += first_row + # last col: top+1 -> bottom + last_col = list(t_matrix[right][top + 1 : bottom + 1]) + spiral += last_col + # last row: right-1 -> left (역순) + if top < bottom: + last_row = matrix[bottom][left:right][::-1] + spiral += last_row + # first col: bottom-1 -> top+1 (역순) + if left < right: + first_col = list(t_matrix[left][top + 1 : bottom][::-1]) + spiral += first_col + # add + row += 1 + col += 1 + return spiral From 6b7b61982f18ffae7702f33d78ce51190c93ed51 Mon Sep 17 00:00:00 2001 From: yihyun-kim1 Date: 2026年4月12日 23:25:10 +0900 Subject: [PATCH 319/526] add solution: longest-increasing-subsequence --- longest-increasing-subsequence/yihyun-kim1.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 longest-increasing-subsequence/yihyun-kim1.js diff --git a/longest-increasing-subsequence/yihyun-kim1.js b/longest-increasing-subsequence/yihyun-kim1.js new file mode 100644 index 0000000000..7ddbdf18d0 --- /dev/null +++ b/longest-increasing-subsequence/yihyun-kim1.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const lengthOfLIS = (nums) => { + const dp = new Array(nums.length).fill(1); + + for (let i = 1; i < nums.length; i++) { + for (let j = 0; j < i; j++) { + if (nums[j] < nums[i]) { + dp[i] = Math.max(dp[i], dp[j] + 1); + } + } + } + + return Math.max(...dp); +}; From 1e89b4b095c1fd14d09971aa28e029423c48a47a Mon Sep 17 00:00:00 2001 From: yihyun-kim1 Date: 2026年4月12日 23:25:23 +0900 Subject: [PATCH 320/526] add solution: valid-parentheses --- valid-parentheses/yihyun-kim1.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 valid-parentheses/yihyun-kim1.js diff --git a/valid-parentheses/yihyun-kim1.js b/valid-parentheses/yihyun-kim1.js new file mode 100644 index 0000000000..d073ed4d9f --- /dev/null +++ b/valid-parentheses/yihyun-kim1.js @@ -0,0 +1,18 @@ +/** + * @param {string} s + * @return {boolean} + */ +const isValid = (s) => { + const stack = []; + const map = { ")": "(", "}": "{", "]": "[" }; + + for (const char of s) { + if (char === "(" || char === "{" || char === "[") { + stack.push(char); + } else { + if (stack.pop() !== map[char]) return false; + } + } + + return stack.length === 0; +}; From cbb5cadc04d16a910c77f86cc7eb5af805b68bfd Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: 2026年4月14日 13:23:37 +0900 Subject: [PATCH 321/526] sadie100: 1 solution --- .../sadie100.ts | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 design-add-and-search-words-data-structure/sadie100.ts diff --git a/design-add-and-search-words-data-structure/sadie100.ts b/design-add-and-search-words-data-structure/sadie100.ts new file mode 100644 index 0000000000..106390b0d5 --- /dev/null +++ b/design-add-and-search-words-data-structure/sadie100.ts @@ -0,0 +1,72 @@ +/* +words를 맵형태로 저장, 각 스펠링과 다음에 나오는 문자열을 key-value로 하는 맵으로 저장 +.의 경우 모든 경우를 탐색한다 + +시간복잡도 : + addWord : O(L) (L은 words의 길이) + search : 일반적으로 O(L), .이 많으면 O(26^k) (k는 .의 개수) + +*/ +class TrieNode { + children: Map + isEnd: boolean + + constructor() { + this.children = new Map() + this.isEnd = false + } +} + +class WordDictionary { + words = new TrieNode() + constructor() {} + + addWord(word: string): void { + let curWords = this.words + + for (let i = 0; i < word.length; i++) { + const char = word[i] + + if (!curWords.children.has(char)) { + curWords.children.set(char, new TrieNode()) + } + + curWords = curWords.children.get(char) + } + curWords.isEnd = true + } + + search(word: string): boolean { + return this.searchRecursively(word, this.words) + } + + searchRecursively(word: string, area: TrieNode) { + for (let i = 0; i < word.length; i++) { + if (!area) return false + const char = word[i] + + if (char === '.') { + const values = [...area.children.values()] + + for (let newArea of values) { + const result = this.searchRecursively(word.slice(i + 1), newArea) + if (result) return true + } + return false + } else { + if (!area.children.has(char)) return false + area = area.children.get(char) + } + } + + if (area.isEnd) return true + return false + } +} + +/** + * Your WordDictionary object will be instantiated and called as such: + * var obj = new WordDictionary() + * obj.addWord(word) + * var param_2 = obj.search(word) + */ From 03c9cc374a0695aaf9472dd820a0421730770b00 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年4月15日 09:39:54 +0900 Subject: [PATCH 322/526] solved reverse-linked-list. --- number-of-islands/sangbeenmoon.py | 29 +++++++++++++++++++++++++++++ reverse-linked-list/sangbeenmoon.py | 20 ++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 number-of-islands/sangbeenmoon.py create mode 100644 reverse-linked-list/sangbeenmoon.py diff --git a/number-of-islands/sangbeenmoon.py b/number-of-islands/sangbeenmoon.py new file mode 100644 index 0000000000..34b50b9a82 --- /dev/null +++ b/number-of-islands/sangbeenmoon.py @@ -0,0 +1,29 @@ +class Solution: + def numIslands(self, grid: List[List[str]]) -> int: + + m,n = len(grid[0]), len(grid) + + visited = [[False] * m for _ in range(n)] + + dx = [0,0, -1, 1] + dy = [-1,1,0,0] + + def dfs(xx:int, yy:int): + + for d in range(4): + nx = xx + dx[d] + ny = yy + dy[d] + + if 0 <= nx and nx < m and 0 <= ny and ny < n and grid[ny][nx] == "1": + if not visited[ny][nx]: + visited[ny][nx] = True + dfs(nx, ny) + + answer = 0 + + for y in range(n): + for x in range(m): + if grid[y][x] == "1" and not visited[y][x]: + answer = answer + 1 + dfs(x,y) + return answer diff --git a/reverse-linked-list/sangbeenmoon.py b/reverse-linked-list/sangbeenmoon.py new file mode 100644 index 0000000000..66526e01b2 --- /dev/null +++ b/reverse-linked-list/sangbeenmoon.py @@ -0,0 +1,20 @@ +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +# 1 -> 2 -> 3 -> 4 -> 5 +# 5 -> 4 -> 3 -> 2 -> 1 + +class Solution: + def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: + + cur = head + p = None + while cur != None: + n = ListNode(cur.val, p) + p = n + cur = cur.next + return p + + \ No newline at end of file From 76ef6c2070e82124230d48c27ae272692845618d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年4月15日 13:33:11 +0900 Subject: [PATCH 323/526] add solution for uniquePaths --- unique-paths/gcount85.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 unique-paths/gcount85.py diff --git a/unique-paths/gcount85.py b/unique-paths/gcount85.py new file mode 100644 index 0000000000..feee38c30e --- /dev/null +++ b/unique-paths/gcount85.py @@ -0,0 +1,16 @@ +""" +# Approach +(0,0) -> (m-1, n-1)로 가기 위해서는 아래로는 m-1회, 우측으로 n-1회 이동해야 합니다. +도합 m+n-2회 이동해야 합니다. 그 이동 경로 중에서 방향 전환(우측 이동 혹은 아래쪽 이동)을 하는 경우의 수를 계산하여 unique path를 구합니다. + +# Complexity +- Time complexity: math.comb는 거의 상수 시간으로 취급하므로 O(1) +- Space complexity: O(1) +""" + +import math + + +class Solution: + def uniquePaths(self, m: int, n: int) -> int: + return math.comb(m + n - 2, m - 1) From 6c5cb3d6d0e8f746f9fa5230bd4ecd6f03facf35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年4月15日 13:58:44 +0900 Subject: [PATCH 324/526] add setZeroes --- set-matrix-zeroes/gcount85.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 set-matrix-zeroes/gcount85.py diff --git a/set-matrix-zeroes/gcount85.py b/set-matrix-zeroes/gcount85.py new file mode 100644 index 0000000000..f9f51d4c9d --- /dev/null +++ b/set-matrix-zeroes/gcount85.py @@ -0,0 +1,34 @@ +""" +# Approach +matrix를 순회하며 값이 0인 행과 열의 번호를 기록합니다. +기록한 것을 토대로 다시 matrix를 순회하며 0으로 채웁니다. + +# Complexity +matrix의 행 크기를 M, 열 크기를 N이라고 할 때 +- Time complexity: O(MN) +- Space complexity: O(M+N) +""" + + +class Solution: + def setZeroes(self, matrix: list[list[int]]) -> None: + """ + Do not return anything, modify matrix in-place instead. + """ + + rows, cols = len(matrix), len(matrix[0]) + zero_rows = set() + zero_cols = set() + for x, row in enumerate(matrix): + for y, value in enumerate(row): + if value == 0: + zero_rows.add(x) + zero_cols.add(y) + + for x in zero_rows: + for i in range(cols): + matrix[x][i] = 0 + + for y in zero_cols: + for i in range(rows): + matrix[i][y] = 0 From fe403cdbc89739e6ccca94eb605e50d4d836528b Mon Sep 17 00:00:00 2001 From: hyejj19 Date: 2026年4月15日 14:12:17 +0900 Subject: [PATCH 325/526] solve reversed-linked-list --- reverse-linked-list/hyejj19.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 reverse-linked-list/hyejj19.ts diff --git a/reverse-linked-list/hyejj19.ts b/reverse-linked-list/hyejj19.ts new file mode 100644 index 0000000000..f95d78ffdb --- /dev/null +++ b/reverse-linked-list/hyejj19.ts @@ -0,0 +1,18 @@ +/* +time complexity : O(n) +space complexity : O(1) +*/ +function reverseList(head: ListNode | null): ListNode | null { + let prev = null; + let cur = head; + let next = null; + + while (cur !== null) { + next = cur.next; + cur.next = prev; + prev = cur; + cur = next; + } + + return prev; +} From 737a90789f596a401bb29d39fcead4961d266cfe Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: 2026年4月15日 16:19:28 +0900 Subject: [PATCH 326/526] reverse linked list solution --- reverse-linked-list/robinyoon-dev.js | 141 +++++++++++++++------------ 1 file changed, 78 insertions(+), 63 deletions(-) diff --git a/reverse-linked-list/robinyoon-dev.js b/reverse-linked-list/robinyoon-dev.js index 9ea6e21d0a..7b9906a5e3 100644 --- a/reverse-linked-list/robinyoon-dev.js +++ b/reverse-linked-list/robinyoon-dev.js @@ -5,82 +5,97 @@ * this.next = (next===undefined ? null : next) * } */ - /** * @param {ListNode} head * @return {ListNode} */ var reverseList = function (head) { - /**정리 - ListNode { - val: number; - next: ListNode | null; // - } - */ - - /** - 설명에 나와 있는 head=[1, 2, 3, 4, 5]는 실제로 다음과 같음. - const head = - new ListNode( - 1, - new ListNode( - 2, - new ListNode( - 3, - new ListNode( - 4, - new ListNode(5, null) - ) - ) - ) - ); - */ - - /** - 계획 - 1. ListNode -> Array로 바꾸는 함수 생성 - 2. const headArray는 head를 Array로 바꾼 값 - 3. const reversedArray는 headArray를 reverse한 배열 - 4. const result는 reversedArray를 ListNode로 바꾼 값 - 5. return result - */ - - // ListNode를 Array로 바꿔주는 함수 - const getToArray = (listNode) => { - const tempArray = []; - let cur = listNode; // 객체 참조 복사! - - while (cur !== null) { - tempArray.push(cur.val); - cur = cur.next; - } - return tempArray; + let prev = null; // 이전 노드를 기억할 변수 (처음엔 이전 노드가 없으니 null) + + while (head!== null) { + let nextTemp = head.next; + head.next = prev; + prev = head; + head = nextTemp; } + return prev; + +}; - const getReversedArray = (arr) => { +// -------------6기 참여 때의 풀이----------------- +// var reverseList = function (head) { - const reversedArray = [...arr].reverse(); +// /**정리 +// ListNode { +// val: number; +// next: ListNode | null; // +// } +// */ - return reversedArray; - } +// /** +// 설명에 나와 있는 head=[1, 2, 3, 4, 5]는 실제로 다음과 같음. +// const head = +// new ListNode( +// 1, +// new ListNode( +// 2, +// new ListNode( +// 3, +// new ListNode( +// 4, +// new ListNode(5, null) +// ) +// ) +// ) +// ); +// */ - const getToListNode = (arr) => { - const dummy = new ListNode(undefined, undefined); - let tail = dummy; // 객체 참조 복사! 즉, dummy가 가리키는 객체를 tail도 가리키게 (참조 복사) 됨! +// /** +// 계획 +// 1. ListNode -> Array로 바꾸는 함수 생성 +// 2. const headArray는 head를 Array로 바꾼 값 +// 3. const reversedArray는 headArray를 reverse한 배열 +// 4. const result는 reversedArray를 ListNode로 바꾼 값 +// 5. return result +// */ - for (const item of arr) { - tail.next = new ListNode(item, null); - tail = tail.next; - } +// // ListNode를 Array로 바꿔주는 함수 +// const getToArray = (listNode) => { +// const tempArray = []; +// let cur = listNode; // 객체 참조 복사! - return dummy.next; - } +// while (cur !== null) { +// tempArray.push(cur.val); +// cur = cur.next; +// } +// return tempArray; +// } - const headArray = getToArray(head); - const reversedArray = getReversedArray(headArray); - const result = getToListNode(reversedArray); +// const getReversedArray = (arr) => { - return result; +// const reversedArray = [...arr].reverse(); + +// return reversedArray; +// } + +// const getToListNode = (arr) => { +// const dummy = new ListNode(undefined, undefined); +// let tail = dummy; // 객체 참조 복사! 즉, dummy가 가리키는 객체를 tail도 가리키게 (참조 복사) 됨! + +// for (const item of arr) { +// tail.next = new ListNode(item, null); +// tail = tail.next; +// } + +// return dummy.next; +// } + +// const headArray = getToArray(head); +// const reversedArray = getReversedArray(headArray); +// const result = getToListNode(reversedArray); + +// return result; + +// }; -}; From c498b668d680c3104695dced9e019c34cf0d0ab2 Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: 2026年4月15日 20:06:02 +0900 Subject: [PATCH 327/526] longest substring without repeating characters solution --- .../robinyoon-dev.js | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 longest-substring-without-repeating-characters/robinyoon-dev.js diff --git a/longest-substring-without-repeating-characters/robinyoon-dev.js b/longest-substring-without-repeating-characters/robinyoon-dev.js new file mode 100644 index 0000000000..d4fcb315a6 --- /dev/null +++ b/longest-substring-without-repeating-characters/robinyoon-dev.js @@ -0,0 +1,29 @@ +/** + * @param {string} s + * @return {number} + */ +var lengthOfLongestSubstring = function (s) { + + let maxLength = 0; + let startIndex = 0; + let endIndex = 0; + + let charSet = new Set(); + + // 슬라이딩 윈도우 + while (endIndex < s.length) { + let currentChar = s[endIndex]; + if (charSet.has(currentChar)) { + charSet.delete(s[startIndex]); + startIndex++; + } else { + charSet.add(currentChar); + maxLength = Math.max(maxLength, charSet.size); + endIndex++; + } + } + return maxLength; +}; + + + From 697101dc55d55b083c2c5196b32792414bf68a6b Mon Sep 17 00:00:00 2001 From: Ted Date: 2026年4月15日 16:26:35 -0400 Subject: [PATCH 328/526] add week 7 solutions --- .../tedkimdev.go | 19 +++++++++ number-of-islands/tedkimdev.go | 31 ++++++++++++++ reverse-linked-list/tedkimdev.go | 22 ++++++++++ set-matrix-zeroes/tedkimdev.go | 40 +++++++++++++++++++ unique-paths/tedkimdev.go | 17 ++++++++ 5 files changed, 129 insertions(+) create mode 100644 longest-substring-without-repeating-characters/tedkimdev.go create mode 100644 number-of-islands/tedkimdev.go create mode 100644 reverse-linked-list/tedkimdev.go create mode 100644 set-matrix-zeroes/tedkimdev.go create mode 100644 unique-paths/tedkimdev.go diff --git a/longest-substring-without-repeating-characters/tedkimdev.go b/longest-substring-without-repeating-characters/tedkimdev.go new file mode 100644 index 0000000000..9bcaccb9ba --- /dev/null +++ b/longest-substring-without-repeating-characters/tedkimdev.go @@ -0,0 +1,19 @@ +// TC: O(n) +// SC: O(m) +func lengthOfLongestSubstring(s string) int { + charIndex := map[byte]int{} + + maxLen := 0 + left := 0 + for right := 0; right < len(s); right++ { + if idx, ok := charIndex[s[right]]; ok && idx>= left { + left = idx + 1 + } + charIndex[s[right]] = right + if right-left+1> maxLen { + maxLen = right - left + 1 + } + } + + return maxLen +} diff --git a/number-of-islands/tedkimdev.go b/number-of-islands/tedkimdev.go new file mode 100644 index 0000000000..5402d94bb5 --- /dev/null +++ b/number-of-islands/tedkimdev.go @@ -0,0 +1,31 @@ +// TC: O(m * n) +// SC: O(m * n) +func numIslands(grid [][]byte) int { + rows, cols := len(grid), len(grid[0]) + islands := 0 + + var dfs func(r, c int) + dfs = func(r, c int) { + if r < 0 || c < 0 || + r>= rows || c>= cols || + grid[r][c] == '0' { + return + } + grid[r][c] = '0' + dfs(r+1, c) + dfs(r-1, c) + dfs(r, c+1) + dfs(r, c-1) + } + + for r := 0; r < rows; r++ { + for c := 0; c < cols; c++ { + if grid[r][c] == '1' { + dfs(r, c) + islands++ + } + } + } + + return islands +} diff --git a/reverse-linked-list/tedkimdev.go b/reverse-linked-list/tedkimdev.go new file mode 100644 index 0000000000..e14d4ed6da --- /dev/null +++ b/reverse-linked-list/tedkimdev.go @@ -0,0 +1,22 @@ +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +// TC: O(n) +// SC: O(1) +func reverseList(head *ListNode) *ListNode { + var prev *ListNode + cur := head + + for cur != nil { + temp := cur.Next + cur.Next = prev + prev = cur + cur = temp + } + return prev +} diff --git a/set-matrix-zeroes/tedkimdev.go b/set-matrix-zeroes/tedkimdev.go new file mode 100644 index 0000000000..29b7c41927 --- /dev/null +++ b/set-matrix-zeroes/tedkimdev.go @@ -0,0 +1,40 @@ +// TC: O(m * n) +// SC: O(1) +func setZeroes(matrix [][]int) { + rowNum, colNum := len(matrix), len(matrix[0]) + + firstRowIsZero := false + + for r := 0; r < rowNum; r++ { + for c := 0; c < colNum; c++ { + if matrix[r][c] == 0 { + matrix[0][c] = 0 + if r> 0 { + matrix[r][0] = 0 + } else { + firstRowIsZero = true + } + } + } + } + + for r := 1; r < rowNum; r++ { + for c := 1; c < colNum; c++ { + if matrix[r][0] == 0 || matrix[0][c] == 0 { + matrix[r][c] = 0 + } + } + } + + if matrix[0][0] == 0 { // first column is zero + for r := 0; r < rowNum; r++ { + matrix[r][0] = 0 + } + } + + if firstRowIsZero { + for c := 0; c < colNum; c++ { + matrix[0][c] = 0 + } + } +} diff --git a/unique-paths/tedkimdev.go b/unique-paths/tedkimdev.go new file mode 100644 index 0000000000..541ea23739 --- /dev/null +++ b/unique-paths/tedkimdev.go @@ -0,0 +1,17 @@ +// TC: O(m * n) +// SC: O(m * n) +func uniquePaths(m int, n int) int { + dp := make([][]int, m+1) + for i := range dp { + dp[i] = make([]int, n+1) + } + dp[m-1][n-1] = 1 + + for i := m - 1; i>= 0; i-- { + for j := n - 1; j>= 0; j-- { + dp[i][j] += dp[i+1][j] + dp[i][j+1] + } + } + + return dp[0][0] +} From e003d65538bfc5e8b597e440a9eba14b96340ad6 Mon Sep 17 00:00:00 2001 From: Dale Seo <5466341+daleseo@users.noreply.github.com> Date: 2026年4月15日 19:11:06 -0400 Subject: [PATCH 329/526] longest-substring-without-repeating-characters --- .../DaleSeo.rs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 longest-substring-without-repeating-characters/DaleSeo.rs diff --git a/longest-substring-without-repeating-characters/DaleSeo.rs b/longest-substring-without-repeating-characters/DaleSeo.rs new file mode 100644 index 0000000000..fdf6644474 --- /dev/null +++ b/longest-substring-without-repeating-characters/DaleSeo.rs @@ -0,0 +1,23 @@ +// TC: O(n) +// SC: O(1) +use std::collections::HashMap; + +impl Solution { + pub fn length_of_longest_substring(s: String) -> i32 { + let mut max_len = 0; + let mut chars = HashMap::new(); + let mut start = 0; + + for (end, ch) in s.chars().enumerate() { + if let Some(&prev) = chars.get(&ch) { + if prev>= start { + start = prev + 1; + } + } + chars.insert(ch, end); + max_len = max_len.max(end - start + 1); + } + + max_len as i32 + } +} From c4805c190feadd90414af0b3cae00aa16b7832e7 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年4月16日 09:54:07 +0900 Subject: [PATCH 330/526] solved unique-paths. --- unique-paths/sangbeenmoon.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 unique-paths/sangbeenmoon.py diff --git a/unique-paths/sangbeenmoon.py b/unique-paths/sangbeenmoon.py new file mode 100644 index 0000000000..e1907713e5 --- /dev/null +++ b/unique-paths/sangbeenmoon.py @@ -0,0 +1,13 @@ +# dp[r][c] = dp[r-1][c] + dp[r][c-1] + +class Solution: + def uniquePaths(self, m: int, n: int) -> int: + dp = [[1] * n for _ in range(m)] + + for r in range(m): + for c in range(n): + if r == 0 or c == 0: + continue + dp[r][c] = dp[r-1][c] + dp[r][c-1] + + return dp[m-1][n-1] From eadef71928eb63d30cca47fc1f5c082b5d06e943 Mon Sep 17 00:00:00 2001 From: soobing Date: 2026年4月16日 10:47:58 +0900 Subject: [PATCH 331/526] feat(week7): reverseList --- reverse-linked-list/soobing.ts | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/reverse-linked-list/soobing.ts b/reverse-linked-list/soobing.ts index fbe1ae913f..888d1aa2e4 100644 --- a/reverse-linked-list/soobing.ts +++ b/reverse-linked-list/soobing.ts @@ -24,15 +24,28 @@ interface ListNode { next: ListNode | null; } +// function reverseList(head: ListNode | null): ListNode | null { +// let prev: ListNode | null = null; + +// while (head) { +// const next = head.next; +// head.next = prev; +// prev = head; +// head = next; +// } + +// return prev; +// } + +// 3rd tried function reverseList(head: ListNode | null): ListNode | null { let prev: ListNode | null = null; - - while (head) { - const next = head.next; - head.next = prev; - prev = head; - head = next; + let current = head; + while(current) { + const next = current?.next ?? null; + current.next = prev; + prev = current; + current = next; } - return prev; -} +}; From 448462fda70c14499f01052c2f5f3b1d3ddecf92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年4月16日 15:05:40 +0900 Subject: [PATCH 332/526] add reverseList function to reverse a linked list --- reverse-linked-list/gcount85.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 reverse-linked-list/gcount85.py diff --git a/reverse-linked-list/gcount85.py b/reverse-linked-list/gcount85.py new file mode 100644 index 0000000000..4059965740 --- /dev/null +++ b/reverse-linked-list/gcount85.py @@ -0,0 +1,22 @@ +""" +# Approach +이전 노드, 현재 노드, 다음 노드를 저장한 뒤, 현재 노드가 이전 노드를 가리키도록 방향을 바꾸고, +이전 노드와 현재 노드 포인터를 이동시킵니다. + +# Complexity +List의 길이를 N이라고 할 떄 +- Time complexity: O(N) +- Space complexity: O(1) +""" + + +class Solution: + def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: + prev = None + cur = head + while cur: + nxt = cur.next # 1. 다음 노드 저장 + cur.next = prev # 2. 방향 뒤집기 + prev = cur # 3. prev 이동 + cur = nxt # 4. cur 이동 + return prev From c52f8f2f8d954c0606e130ac481538afdf59485e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年4月16日 15:11:51 +0900 Subject: [PATCH 333/526] add numIslands function to count the number of islands in a grid --- number-of-islands/gcount85.py | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 number-of-islands/gcount85.py diff --git a/number-of-islands/gcount85.py b/number-of-islands/gcount85.py new file mode 100644 index 0000000000..83a90ca814 --- /dev/null +++ b/number-of-islands/gcount85.py @@ -0,0 +1,45 @@ +""" +# Approach +Grid의 원소에 일일이 dfs를 수행하되 값이 "1"(=육지)인 경우만 탐색을 수행합니다. +이때 방문한 노드는 값을 "-1"로 변경하여 방문 체크합니다. + +# Complexity +Grid의 rows = M, cols = N이라고 할 때, +- Time complexity: O(M*N) +- Space complexity: visited set 최대 O(M*N) +""" + + +class Solution: + def numIslands(self, grid: List[List[str]]) -> int: + answer = 0 + direction = [(0, 1), (0, -1), (1, 0), (-1, 0)] + row = len(grid) + col = len(grid[0]) + + def can_go(x, y, row, col): + if x < 0 or y < 0 or x>= row or y>= col: + return False + if grid[x][y] == "0": + return False + return True + + def dfs(x, y, row, col): + for dx, dy in direction: + nx, ny = x + dx, y + dy + if not can_go(nx, ny, row, col): + continue + if grid[nx][ny] == "-1": # 방문 확인 + continue + grid[nx][ny] = "-1" # 방문 처리 + dfs(nx, ny, row, col) + + for x, row_list in enumerate(grid): + for y, value in enumerate(row_list): + if value != "1": + continue + grid[x][y] = "-1" # 방문 확인 + dfs(x, y, row, col) + answer += 1 + + return answer From 37934ddc346496ab6b03b948171666882fe7208a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=9D=80=EB=AF=BC=20=28E=2EM=2E=20Jamie=20Lee=29?= <100mgml@gmail.com> Date: 2026年4月16日 15:16:22 +0900 Subject: [PATCH 334/526] add solution for longest substring without repeating characters problem --- .../gcount85.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 longest-substring-without-repeating-characters/gcount85.py diff --git a/longest-substring-without-repeating-characters/gcount85.py b/longest-substring-without-repeating-characters/gcount85.py new file mode 100644 index 0000000000..2701a819d3 --- /dev/null +++ b/longest-substring-without-repeating-characters/gcount85.py @@ -0,0 +1,33 @@ +""" +# Approach +슬라이딩 윈도우를 사용한다. +right 포인터를 하나씩 이동시키면서 문자열을 확장하고, +이미 등장한 문자를 만나면 해당 문자의 마지막 위치를 기준으로 left 포인터를 이동시켜 중복이 없는 구간을 유지한다. +각 단계에서 현재 윈도우의 길이를 계산하여 최대값을 갱신한다. + +# Complexity +문자열 길이를 N이라고 할 때, 문자 종류 수를 K라고 할 때 +- Time complexity: O(N) +- Space complexity: O(K) +""" + + +class Solution: + def lengthOfLongestSubstring(self, s: str) -> int: + last_seen = {} # 문자 -> 마지막으로 등장한 인덱스 + left = 0 # 현재 윈도우의 시작 위치 + answer = 0 # 최대 길이 저장 + + for right, ch in enumerate(s): + # 현재 문자가 이전에 등장했고, + # 그 위치가 현재 윈도우 안에 있다면 left 이동 + if ch in last_seen and last_seen[ch]>= left: + left = last_seen[ch] + 1 + + # 현재 문자의 마지막 위치 갱신 + last_seen[ch] = right + + # 현재 윈도우 길이 계산 및 최대값 갱신 + answer = max(answer, right - left + 1) + + return answer From 83a08dad38844f3418203450a554c33b849bc8ba Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: 2026年4月16日 17:50:47 +0900 Subject: [PATCH 335/526] sadie100: reverse linked list solution --- reverse-linked-list/sadie100.ts | 34 +++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 reverse-linked-list/sadie100.ts diff --git a/reverse-linked-list/sadie100.ts b/reverse-linked-list/sadie100.ts new file mode 100644 index 0000000000..4334a7dd16 --- /dev/null +++ b/reverse-linked-list/sadie100.ts @@ -0,0 +1,34 @@ +/** + * Definition for singly-linked list. + * class ListNode { + * val: number + * next: ListNode | null + * constructor(val?: number, next?: ListNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + * } + */ + +/* +직전 노드를 담는 변수 before과 다음 노드를 담는 변수 next, 순회중인 노드 head 변수와 함께 list를 순회 +head의 next에 before을 넣고, head를 next로 변환하며 head가 null이 아닐 때까지 반복한다 + +시간복잡도 : O(N) - 1번 순회 +공간복잡도 : O(1) - before, next 변수 + +*/ +function reverseList(head: ListNode | null): ListNode | null { + if (!head) return head + let originNext = head.next + let before = null + + while (head !== null) { + originNext = head.next + head.next = before + before = head + head = originNext + } + + return before +} From aba52c3c3c1cb0e1e866aba247574ca29b2ca274 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月16日 19:43:54 +0900 Subject: [PATCH 336/526] reverse-linked-list solution --- reverse-linked-list/hyeri0903.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 reverse-linked-list/hyeri0903.py diff --git a/reverse-linked-list/hyeri0903.py b/reverse-linked-list/hyeri0903.py new file mode 100644 index 0000000000..a4bdfebcdc --- /dev/null +++ b/reverse-linked-list/hyeri0903.py @@ -0,0 +1,31 @@ +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: + + if head is None: + return None + + st = [] + cur = head + + while cur: + st.append(cur.val) + cur = cur.next + + dummy = ListNode(0) + cur = dummy + + while st: + cur_value = st.pop() + cur.next = ListNode(cur_value) + cur = cur.next + + return dummy.next + + + + \ No newline at end of file From b5b3c4c86e051a5a40d88484b2dacfcdcbe09c93 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月16日 19:44:51 +0900 Subject: [PATCH 337/526] longest-substring-without-repeating-characters solution --- .../hyeri0903.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 longest-substring-without-repeating-characters/hyeri0903.py diff --git a/longest-substring-without-repeating-characters/hyeri0903.py b/longest-substring-without-repeating-characters/hyeri0903.py new file mode 100644 index 0000000000..ddd9b769d9 --- /dev/null +++ b/longest-substring-without-repeating-characters/hyeri0903.py @@ -0,0 +1,15 @@ +class Solution: + def lengthOfLongestSubstring(self, s: str) -> int: + left = 0 + max_len = 0 + visited = set() + + for i in range(len(s)): + while s[i] in visited: + visited.remove(s[left]) + left += 1 + + visited.add(s[i]) + max_len = max(max_len, i - left + 1) + + return max_len From 202b2dedd02a28141c71befbd89553932f312daf Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月16日 19:45:46 +0900 Subject: [PATCH 338/526] number of island solution --- number-of-islands/hyeri0903.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 number-of-islands/hyeri0903.py diff --git a/number-of-islands/hyeri0903.py b/number-of-islands/hyeri0903.py new file mode 100644 index 0000000000..efb89b7d7a --- /dev/null +++ b/number-of-islands/hyeri0903.py @@ -0,0 +1,33 @@ +class Solution: + def numIslands(self, grid: List[List[str]]) -> int: + ''' + m = 세로(열), n = 가로(행) + solution: dfs + ''' + m = len(grid) + n = len(grid[0]) + visited = [ [0] * n for _ in range(m)] + count = 0 + + def dfs(i, j): + #범위 벗어나면 return + if i < 0 or i>= m or j < 0 or j>= n or grid[i][j] == "0": + return + + if visited[i][j] == 1: + return + + visited[i][j] = 1 #방문표시 + + dfs(i+1, j) + dfs(i-1, j) + dfs(i, j+1) + dfs(i, j-1) + + for i in range(m): + for j in range(n): + if grid[i][j] == "1" and visited[i][j] == 0: + dfs(i,j) + count += 1 + return count + \ No newline at end of file From a25dc2f90a6db2e9b7e42cbb6c1cd66c838a3d0e Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月16日 23:17:01 +0900 Subject: [PATCH 339/526] edit: linelint --- encode-and-decode-strings/hyeri0903.py | 1 + 1 file changed, 1 insertion(+) diff --git a/encode-and-decode-strings/hyeri0903.py b/encode-and-decode-strings/hyeri0903.py index d2f0c43da7..16bcc81ac3 100644 --- a/encode-and-decode-strings/hyeri0903.py +++ b/encode-and-decode-strings/hyeri0903.py @@ -2,6 +2,7 @@ class Solution: """ @param: strs: a list of strings @return: encodes a list of strings to a single string. + 모르겠어서 해설의 힘을 빌렸어요..ᅲ """ def encode(self, strs: List[str]): text = "" From a1969312f09d2e683d048254c17c7e20691ed0cd Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月16日 23:21:45 +0900 Subject: [PATCH 340/526] fix: add missing newline at end of files --- container-with-most-water/hyeri0903.py | 2 +- longest-increasing-subsequence/hyeri0903.py | 2 +- number-of-islands/hyeri0903.py | 2 +- reverse-linked-list/hyeri0903.py | 2 +- valid-parentheses/hyeri0903.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/container-with-most-water/hyeri0903.py b/container-with-most-water/hyeri0903.py index 9375a08f8d..1b102f3be8 100644 --- a/container-with-most-water/hyeri0903.py +++ b/container-with-most-water/hyeri0903.py @@ -29,4 +29,4 @@ def maxArea(self, height: List[int]) -> int: right -= 1 return maxArea - \ No newline at end of file + diff --git a/longest-increasing-subsequence/hyeri0903.py b/longest-increasing-subsequence/hyeri0903.py index f87953236a..2854a0fe41 100644 --- a/longest-increasing-subsequence/hyeri0903.py +++ b/longest-increasing-subsequence/hyeri0903.py @@ -23,4 +23,4 @@ def lengthOfLIS(self, nums: List[int]) -> int: return max(dp) - \ No newline at end of file + diff --git a/number-of-islands/hyeri0903.py b/number-of-islands/hyeri0903.py index efb89b7d7a..be60281602 100644 --- a/number-of-islands/hyeri0903.py +++ b/number-of-islands/hyeri0903.py @@ -30,4 +30,4 @@ def dfs(i, j): dfs(i,j) count += 1 return count - \ No newline at end of file + diff --git a/reverse-linked-list/hyeri0903.py b/reverse-linked-list/hyeri0903.py index a4bdfebcdc..bab1173cef 100644 --- a/reverse-linked-list/hyeri0903.py +++ b/reverse-linked-list/hyeri0903.py @@ -28,4 +28,4 @@ def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: - \ No newline at end of file + diff --git a/valid-parentheses/hyeri0903.py b/valid-parentheses/hyeri0903.py index fd914442b9..614b8e8354 100644 --- a/valid-parentheses/hyeri0903.py +++ b/valid-parentheses/hyeri0903.py @@ -34,4 +34,4 @@ def isValid(self, s: str) -> bool: return False return True - \ No newline at end of file + From a4312007f624508e7fb97e81af4edae180f90545 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月16日 23:32:07 +0900 Subject: [PATCH 341/526] number of islands solution --- number-of-islands/hyeri0903.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/number-of-islands/hyeri0903.py b/number-of-islands/hyeri0903.py index be60281602..36a8bc34f2 100644 --- a/number-of-islands/hyeri0903.py +++ b/number-of-islands/hyeri0903.py @@ -6,7 +6,6 @@ def numIslands(self, grid: List[List[str]]) -> int: ''' m = len(grid) n = len(grid[0]) - visited = [ [0] * n for _ in range(m)] count = 0 def dfs(i, j): @@ -14,10 +13,10 @@ def dfs(i, j): if i < 0 or i>= m or j < 0 or j>= n or grid[i][j] == "0": return - if visited[i][j] == 1: + if grid[i][j] == "#": return - - visited[i][j] = 1 #방문표시 + #방문표시 + grid[i][j] = "#" dfs(i+1, j) dfs(i-1, j) @@ -26,7 +25,7 @@ def dfs(i, j): for i in range(m): for j in range(n): - if grid[i][j] == "1" and visited[i][j] == 0: + if grid[i][j] == "1" and grid[i][j] != "#": dfs(i,j) count += 1 return count From 3e704ff665820113852025fc441be97684268ce3 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月16日 23:43:03 +0900 Subject: [PATCH 342/526] reverse linked list solutions --- reverse-linked-list/hyeri0903.java | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 reverse-linked-list/hyeri0903.java diff --git a/reverse-linked-list/hyeri0903.java b/reverse-linked-list/hyeri0903.java new file mode 100644 index 0000000000..456b6ec8a7 --- /dev/null +++ b/reverse-linked-list/hyeri0903.java @@ -0,0 +1,36 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode reverseList(ListNode head) { + if(head == null) { + return null; + } + + Deque stack = new ArrayDeque(); + ListNode node = head; + + while(node != null) { + stack.push(node.val); + node = node.next; + } + + ListNode dummy = new ListNode(); + ListNode cur = dummy; + + while(stack.size()> 0) { + int val = stack.pop(); + cur.next = new ListNode(val); + cur = cur.next; + } + + return dummy.next; + } +} From 9cd063a7a5e2675abfe0e4af864e8c895d9598c4 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月16日 23:56:21 +0900 Subject: [PATCH 343/526] number of islands solution --- number-of-islands/hyeri0903.java | 43 ++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 number-of-islands/hyeri0903.java diff --git a/number-of-islands/hyeri0903.java b/number-of-islands/hyeri0903.java new file mode 100644 index 0000000000..bb24a3a98e --- /dev/null +++ b/number-of-islands/hyeri0903.java @@ -0,0 +1,43 @@ +class Solution { + + public int numIslands(char[][] grid) { + /** + 1.prob:섬 개수 구하기 + 2.constraints: + - 원소값 0 or 1 + - m,n 길이는 최소 = 1, 최대 = 300 + 3.solution: dfs + */ + + //m: 세로, n: 가로 길이 + int m = grid.length; + int n = grid[0].length; + int count = 0; + + for(int i = 0; i < m; i++) { + for(int j = 0; j < n; j++) { + if(grid[i][j] == '1' && grid[i][j] != '#') { + dfs(i, j, grid, m, n); + count += 1; + } + } + } + return count; + } + void dfs(int i, int j, char[][] grid, int m, int n) { + if(i < 0 || i>= m || j < 0 || j>= n || grid[i][j] == '0') { + return; + } + //이미 visited + if(grid[i][j] == '#') { + return; + } + //방문 체크 + grid[i][j] = '#'; + + dfs(i+1, j, grid, m, n); + dfs(i-1, j, grid, m, n); + dfs(i, j+1, grid, m, n); + dfs(i, j-1, grid, m, n); + } +} From f48c4b56d717ab778533682da6dd79b6ef307d0a Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月17日 00:13:13 +0900 Subject: [PATCH 344/526] lengthOfLongestSubstring solution --- .../hyeri0903.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 longest-substring-without-repeating-characters/hyeri0903.java diff --git a/longest-substring-without-repeating-characters/hyeri0903.java b/longest-substring-without-repeating-characters/hyeri0903.java new file mode 100644 index 0000000000..ecf404f823 --- /dev/null +++ b/longest-substring-without-repeating-characters/hyeri0903.java @@ -0,0 +1,28 @@ +class Solution { + public int lengthOfLongestSubstring(String s) { + /** + 1.prob: 중복없는 가장 긴 substring length return + 2.constraints: + - alphabet, digit, space 로 구성 + - s.length min = 0, max = 50,000 + 3.solution + - slding window, time: O(n), space: O(n) or O(1) + */ + + int maxLen = 0; + int left = 0; + Set visited = new HashSet(); + + for(int i = 0; i < s.length(); i++){ + char ch = s.charAt(i); + while(visited.contains(ch)) { + visited.remove(s.charAt(left)); + left += 1; + } + visited.add(ch); + maxLen = Math.max(maxLen, i - left + 1); + } + + return maxLen; + } +} From 1fbb2c86399cd3c8ff8f70c5e30a767722afea8f Mon Sep 17 00:00:00 2001 From: Dia Date: 2026年4月17日 02:36:26 +0900 Subject: [PATCH 345/526] feat: implement week 7 --- number-of-islands/kangdaia.py | 40 +++++++++++++++++++++++++++++++++ reverse-linked-list/kangdaia.py | 27 ++++++++++++++++++++++ set-matrix-zeroes/kangdaia.py | 25 +++++++++++++++++++++ unique-paths/kangdaia.py | 27 ++++++++++++++++++++++ 4 files changed, 119 insertions(+) create mode 100644 number-of-islands/kangdaia.py create mode 100644 reverse-linked-list/kangdaia.py create mode 100644 set-matrix-zeroes/kangdaia.py create mode 100644 unique-paths/kangdaia.py diff --git a/number-of-islands/kangdaia.py b/number-of-islands/kangdaia.py new file mode 100644 index 0000000000..6f3656399b --- /dev/null +++ b/number-of-islands/kangdaia.py @@ -0,0 +1,40 @@ +class Solution: + def numIslands(self, grid: list[list[str]]) -> int: + """1이 땅이고, 0이 바다로 표현한 2D리스트에서 연결되지 않은 땅 (섬)의 갯수를 구하는 함수 + + 방법: + 1. deque를 사용해 BFS로 풀이 + - 1이 땅인 경우, 섬 갯수 +1, 그리고 해당 땅과 연결된 땅을 모두 0으로 바꿔주며 탐색 + 2. deque 대신 stack을 사용해 DFS로 풀이 + 시간 복잡도: O(m*n) - 모든 땅을 탐색하는 경우 + 공간 복잡도: O(m*n) - 최악의 경우 모든 땅이 연결되어 있는 경우 + + Args: + grid (list[list[str]]): 1과 0으로 구성된 2d array 지도 + + Returns: + int: 총 땅 갯수 + """ + + if not grid or not grid[0]: + return 0 + + m, n = len(grid), len(grid[0]) + directions = ((1, 0), (-1, 0), (0, 1), (0, -1)) + islands = 0 + + for x in range(m): + for y in range(n): + if grid[x][y] != "1": + continue + islands += 1 + stack = [(x, y)] + grid[x][y] = "0" + while stack: + i_x, i_y = stack.pop() + for dx, dy in directions: + nx, ny = i_x + dx, i_y + dy + if 0 <= nx < m and 0 <= ny < n and grid[nx][ny] == "1": + grid[nx][ny] = "0" + stack.append((nx, ny)) + return islands diff --git a/reverse-linked-list/kangdaia.py b/reverse-linked-list/kangdaia.py new file mode 100644 index 0000000000..6bc1d7cf28 --- /dev/null +++ b/reverse-linked-list/kangdaia.py @@ -0,0 +1,27 @@ +from typing import Optional + + +# Definition for singly-linked list. +class ListNode: + def __init__(self, val=0, next=None): + self.val = val + self.next = next + + +class Solution: + def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: + """링크드 리스트를 뒤집어서 역순의 링크드 리스트를 만드는 함수 + + Args: + head (Optional[ListNode]): 주어진 링크드 리스트 + + Returns: + Optional[ListNode]: 뒤집어진 링크드 리스트 + """ + if head is None or head.next is None: + return head + curr = head.next + new_head = self.reverseList(head.next) + curr.next = head + head.next = None + return new_head diff --git a/set-matrix-zeroes/kangdaia.py b/set-matrix-zeroes/kangdaia.py new file mode 100644 index 0000000000..fa8b1233cc --- /dev/null +++ b/set-matrix-zeroes/kangdaia.py @@ -0,0 +1,25 @@ +class Solution: + def setZeroes(self, matrix: list[list[int]]) -> None: + """ + Hint 가이드에 따라 풀이 + + Do not return anything, modify matrix in-place instead. + """ + m, n = len(matrix), len(matrix[0]) + first_row = any(matrix[0][j] == 0 for j in range(n)) + first_col = any(matrix[i][0] == 0 for i in range(m)) + for i in range(1, m): + for j in range(1, n): + if matrix[i][j] == 0: + matrix[i][0] = 0 + matrix[0][j] = 0 + for i in range(1, m): + for j in range(1, n): + if matrix[i][0] == 0 or matrix[0][j] == 0: + matrix[i][j] = 0 + if first_col: + for i in range(m): + matrix[i][0] = 0 + if first_row: + for j in range(n): + matrix[0][j] = 0 diff --git a/unique-paths/kangdaia.py b/unique-paths/kangdaia.py new file mode 100644 index 0000000000..6468c5ca8d --- /dev/null +++ b/unique-paths/kangdaia.py @@ -0,0 +1,27 @@ +class Solution: + def uniquePaths(self, m: int, n: int) -> int: + """격자에서 (0, 0) 위치에서 시작해 (m-1, n-1) 위치에 도달하는 경로의 수를 구하는 함수 + + 방법: + 1. 최적의 경로 -> DP 문제! + - 각 위치에서는 오른쪽과 아래로만 가지 못함 + - 따라서, dp[i][j] = dp[i - 1][j] + dp[i][j - 1]로 표현 가능 + 시간 복잡도: O(m*n) - 모든 위치에 대해 계산하는 경우 + 공간 복잡도: O(m*n) - dp 테이블을 저장하는 경우 + + Args: + m (int): 격자의 행 갯수 + n (int): 격자의 열 갯수 + + Returns: + int: (m-1, n-1) 위치에 도달하는 경로의 수 + """ + dp = [[0] * n for _ in range(m)] + for i in range(m): + dp[i][0] = 1 + for j in range(n): + dp[0][j] = 1 + for i in range(1, m): + for j in range(1, n): + dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + return dp[m - 1][n - 1] From 858dab7dac64f69d45bd387d74318336a1c4544e Mon Sep 17 00:00:00 2001 From: jamiebase <100mgml@gmail.com> Date: 2026年4月17日 12:47:01 +0900 Subject: [PATCH 346/526] Update filenames --- .../{gcount85.py => jamiebase.py} | 0 number-of-islands/{gcount85.py => jamiebase.py} | 0 reverse-linked-list/{gcount85.py => jamiebase.py} | 0 set-matrix-zeroes/{gcount85.py => jamiebase.py} | 0 unique-paths/{gcount85.py => jamiebase.py} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename longest-substring-without-repeating-characters/{gcount85.py => jamiebase.py} (100%) rename number-of-islands/{gcount85.py => jamiebase.py} (100%) rename reverse-linked-list/{gcount85.py => jamiebase.py} (100%) rename set-matrix-zeroes/{gcount85.py => jamiebase.py} (100%) rename unique-paths/{gcount85.py => jamiebase.py} (100%) diff --git a/longest-substring-without-repeating-characters/gcount85.py b/longest-substring-without-repeating-characters/jamiebase.py similarity index 100% rename from longest-substring-without-repeating-characters/gcount85.py rename to longest-substring-without-repeating-characters/jamiebase.py diff --git a/number-of-islands/gcount85.py b/number-of-islands/jamiebase.py similarity index 100% rename from number-of-islands/gcount85.py rename to number-of-islands/jamiebase.py diff --git a/reverse-linked-list/gcount85.py b/reverse-linked-list/jamiebase.py similarity index 100% rename from reverse-linked-list/gcount85.py rename to reverse-linked-list/jamiebase.py diff --git a/set-matrix-zeroes/gcount85.py b/set-matrix-zeroes/jamiebase.py similarity index 100% rename from set-matrix-zeroes/gcount85.py rename to set-matrix-zeroes/jamiebase.py diff --git a/unique-paths/gcount85.py b/unique-paths/jamiebase.py similarity index 100% rename from unique-paths/gcount85.py rename to unique-paths/jamiebase.py From 8ae1b5ead7201231067d441fb3c9e39f84da3c7f Mon Sep 17 00:00:00 2001 From: jamiebase <100mgml@gmail.com> Date: 2026年4月17日 12:54:09 +0900 Subject: [PATCH 347/526] Update filenames to jamiebase.py --- 3sum/{gcount85.py => jamiebase.py} | 0 best-time-to-buy-and-sell-stock/{gcount85.py => jamiebase.py} | 0 climbing-stairs/{gcount85.py => jamiebase.py} | 0 coin-change/{gcount85.py => jamiebase.py} | 0 combination-sum/{gcount85.py => jamiebase.py} | 0 container-with-most-water/{gcount85.py => jamiebase.py} | 0 contains-duplicate/{gcount85.py => jamiebase.py} | 0 decode-ways/{gcount85.py => jamiebase.py} | 0 .../{gcount85.py => jamiebase.py} | 0 group-anagrams/{gcount85.py => jamiebase.py} | 0 house-robber/{gcount85.py => jamiebase.py} | 0 implement-trie-prefix-tree/{gcount85.py => jamiebase.py} | 0 longest-consecutive-sequence/{gcount85.py => jamiebase.py} | 0 longest-increasing-subsequence/{gcount85.py => jamiebase.py} | 0 maximum-depth-of-binary-tree/{gcount85.py => jamiebase.py} | 0 maximum-subarray/{gcount85.py => jamiebase.py} | 0 merge-two-sorted-lists/{gcount85.py => jamiebase.py} | 0 number-of-1-bits/{gcount85.py => jamiebase.py} | 0 product-of-array-except-self/{gcount85.py => jamiebase.py} | 0 spiral-matrix/{gcount85.py => jamiebase.py} | 0 top-k-frequent-elements/{gcount85.py => jamiebase.py} | 0 two-sum/{gcount85.py => jamiebase.py} | 0 valid-anagram/{gcount85.py => jamiebase.py} | 0 valid-palindrome/{gcount85.py => jamiebase.py} | 0 valid-parentheses/{gcount85.py => jamiebase.py} | 0 validate-binary-search-tree/{gcount85.py => jamiebase.py} | 0 word-break/{gcount85.py => jamiebase.py} | 0 word-search/{gcount85.py => jamiebase.py} | 0 28 files changed, 0 insertions(+), 0 deletions(-) rename 3sum/{gcount85.py => jamiebase.py} (100%) rename best-time-to-buy-and-sell-stock/{gcount85.py => jamiebase.py} (100%) rename climbing-stairs/{gcount85.py => jamiebase.py} (100%) rename coin-change/{gcount85.py => jamiebase.py} (100%) rename combination-sum/{gcount85.py => jamiebase.py} (100%) rename container-with-most-water/{gcount85.py => jamiebase.py} (100%) rename contains-duplicate/{gcount85.py => jamiebase.py} (100%) rename decode-ways/{gcount85.py => jamiebase.py} (100%) rename find-minimum-in-rotated-sorted-array/{gcount85.py => jamiebase.py} (100%) rename group-anagrams/{gcount85.py => jamiebase.py} (100%) rename house-robber/{gcount85.py => jamiebase.py} (100%) rename implement-trie-prefix-tree/{gcount85.py => jamiebase.py} (100%) rename longest-consecutive-sequence/{gcount85.py => jamiebase.py} (100%) rename longest-increasing-subsequence/{gcount85.py => jamiebase.py} (100%) rename maximum-depth-of-binary-tree/{gcount85.py => jamiebase.py} (100%) rename maximum-subarray/{gcount85.py => jamiebase.py} (100%) rename merge-two-sorted-lists/{gcount85.py => jamiebase.py} (100%) rename number-of-1-bits/{gcount85.py => jamiebase.py} (100%) rename product-of-array-except-self/{gcount85.py => jamiebase.py} (100%) rename spiral-matrix/{gcount85.py => jamiebase.py} (100%) rename top-k-frequent-elements/{gcount85.py => jamiebase.py} (100%) rename two-sum/{gcount85.py => jamiebase.py} (100%) rename valid-anagram/{gcount85.py => jamiebase.py} (100%) rename valid-palindrome/{gcount85.py => jamiebase.py} (100%) rename valid-parentheses/{gcount85.py => jamiebase.py} (100%) rename validate-binary-search-tree/{gcount85.py => jamiebase.py} (100%) rename word-break/{gcount85.py => jamiebase.py} (100%) rename word-search/{gcount85.py => jamiebase.py} (100%) diff --git a/3sum/gcount85.py b/3sum/jamiebase.py similarity index 100% rename from 3sum/gcount85.py rename to 3sum/jamiebase.py diff --git a/best-time-to-buy-and-sell-stock/gcount85.py b/best-time-to-buy-and-sell-stock/jamiebase.py similarity index 100% rename from best-time-to-buy-and-sell-stock/gcount85.py rename to best-time-to-buy-and-sell-stock/jamiebase.py diff --git a/climbing-stairs/gcount85.py b/climbing-stairs/jamiebase.py similarity index 100% rename from climbing-stairs/gcount85.py rename to climbing-stairs/jamiebase.py diff --git a/coin-change/gcount85.py b/coin-change/jamiebase.py similarity index 100% rename from coin-change/gcount85.py rename to coin-change/jamiebase.py diff --git a/combination-sum/gcount85.py b/combination-sum/jamiebase.py similarity index 100% rename from combination-sum/gcount85.py rename to combination-sum/jamiebase.py diff --git a/container-with-most-water/gcount85.py b/container-with-most-water/jamiebase.py similarity index 100% rename from container-with-most-water/gcount85.py rename to container-with-most-water/jamiebase.py diff --git a/contains-duplicate/gcount85.py b/contains-duplicate/jamiebase.py similarity index 100% rename from contains-duplicate/gcount85.py rename to contains-duplicate/jamiebase.py diff --git a/decode-ways/gcount85.py b/decode-ways/jamiebase.py similarity index 100% rename from decode-ways/gcount85.py rename to decode-ways/jamiebase.py diff --git a/find-minimum-in-rotated-sorted-array/gcount85.py b/find-minimum-in-rotated-sorted-array/jamiebase.py similarity index 100% rename from find-minimum-in-rotated-sorted-array/gcount85.py rename to find-minimum-in-rotated-sorted-array/jamiebase.py diff --git a/group-anagrams/gcount85.py b/group-anagrams/jamiebase.py similarity index 100% rename from group-anagrams/gcount85.py rename to group-anagrams/jamiebase.py diff --git a/house-robber/gcount85.py b/house-robber/jamiebase.py similarity index 100% rename from house-robber/gcount85.py rename to house-robber/jamiebase.py diff --git a/implement-trie-prefix-tree/gcount85.py b/implement-trie-prefix-tree/jamiebase.py similarity index 100% rename from implement-trie-prefix-tree/gcount85.py rename to implement-trie-prefix-tree/jamiebase.py diff --git a/longest-consecutive-sequence/gcount85.py b/longest-consecutive-sequence/jamiebase.py similarity index 100% rename from longest-consecutive-sequence/gcount85.py rename to longest-consecutive-sequence/jamiebase.py diff --git a/longest-increasing-subsequence/gcount85.py b/longest-increasing-subsequence/jamiebase.py similarity index 100% rename from longest-increasing-subsequence/gcount85.py rename to longest-increasing-subsequence/jamiebase.py diff --git a/maximum-depth-of-binary-tree/gcount85.py b/maximum-depth-of-binary-tree/jamiebase.py similarity index 100% rename from maximum-depth-of-binary-tree/gcount85.py rename to maximum-depth-of-binary-tree/jamiebase.py diff --git a/maximum-subarray/gcount85.py b/maximum-subarray/jamiebase.py similarity index 100% rename from maximum-subarray/gcount85.py rename to maximum-subarray/jamiebase.py diff --git a/merge-two-sorted-lists/gcount85.py b/merge-two-sorted-lists/jamiebase.py similarity index 100% rename from merge-two-sorted-lists/gcount85.py rename to merge-two-sorted-lists/jamiebase.py diff --git a/number-of-1-bits/gcount85.py b/number-of-1-bits/jamiebase.py similarity index 100% rename from number-of-1-bits/gcount85.py rename to number-of-1-bits/jamiebase.py diff --git a/product-of-array-except-self/gcount85.py b/product-of-array-except-self/jamiebase.py similarity index 100% rename from product-of-array-except-self/gcount85.py rename to product-of-array-except-self/jamiebase.py diff --git a/spiral-matrix/gcount85.py b/spiral-matrix/jamiebase.py similarity index 100% rename from spiral-matrix/gcount85.py rename to spiral-matrix/jamiebase.py diff --git a/top-k-frequent-elements/gcount85.py b/top-k-frequent-elements/jamiebase.py similarity index 100% rename from top-k-frequent-elements/gcount85.py rename to top-k-frequent-elements/jamiebase.py diff --git a/two-sum/gcount85.py b/two-sum/jamiebase.py similarity index 100% rename from two-sum/gcount85.py rename to two-sum/jamiebase.py diff --git a/valid-anagram/gcount85.py b/valid-anagram/jamiebase.py similarity index 100% rename from valid-anagram/gcount85.py rename to valid-anagram/jamiebase.py diff --git a/valid-palindrome/gcount85.py b/valid-palindrome/jamiebase.py similarity index 100% rename from valid-palindrome/gcount85.py rename to valid-palindrome/jamiebase.py diff --git a/valid-parentheses/gcount85.py b/valid-parentheses/jamiebase.py similarity index 100% rename from valid-parentheses/gcount85.py rename to valid-parentheses/jamiebase.py diff --git a/validate-binary-search-tree/gcount85.py b/validate-binary-search-tree/jamiebase.py similarity index 100% rename from validate-binary-search-tree/gcount85.py rename to validate-binary-search-tree/jamiebase.py diff --git a/word-break/gcount85.py b/word-break/jamiebase.py similarity index 100% rename from word-break/gcount85.py rename to word-break/jamiebase.py diff --git a/word-search/gcount85.py b/word-search/jamiebase.py similarity index 100% rename from word-search/gcount85.py rename to word-search/jamiebase.py From c6322760b79d8970a13ecad03a4460b78bbad5b8 Mon Sep 17 00:00:00 2001 From: hyejj19 Date: 2026年4月17日 14:45:27 +0900 Subject: [PATCH 348/526] solve logest-substring-without-repeating-characters --- .../hyejj19.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 longest-substring-without-repeating-characters/hyejj19.ts diff --git a/longest-substring-without-repeating-characters/hyejj19.ts b/longest-substring-without-repeating-characters/hyejj19.ts new file mode 100644 index 0000000000..e9d88103ca --- /dev/null +++ b/longest-substring-without-repeating-characters/hyejj19.ts @@ -0,0 +1,24 @@ +function lengthOfLongestSubstring(s: string): number { + if (s.length <= 1) return s.length; + + let left = 0; + let right = 0; + let maxLen = -1; + const sMap = new Map(); + while (right !== s.length) { + const curS = s[right]; + // Map에 존재하지 않는다 -> 중복 X -> right 전진 + if (!sMap.get(curS)) { + sMap.set(s[right], 1); + right++; + } else { + // Map에 존재 한다 -> 중복 O -> left 전진 + while (left <= right && sMap.get(curS)) { + sMap.set(s[left], sMap.get(s[left]) - 1); + left++; + } + } + maxLen = Math.max(maxLen, right - left); + } + return maxLen; +} From 7c741cb8083a3199b0efa7ac7fc3409839c6c9ec Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月15日 16:14:15 +0900 Subject: [PATCH 349/526] [7th batch] week 7 - reverse linked list --- reverse-linked-list/liza0525.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/reverse-linked-list/liza0525.py b/reverse-linked-list/liza0525.py index 22373de61c..a62bf3a2fc 100644 --- a/reverse-linked-list/liza0525.py +++ b/reverse-linked-list/liza0525.py @@ -6,3 +6,31 @@ def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: curr_node.next = pre_node pre_node, curr_node = curr_node, temp return pre_node + + +# 7기 풀이 +# 시간 복잡도: O(n) +# - 링크드 리스트의 길이만큼 탐색 +# 공간 복잡도: O(1) +# - 결과 변수 이외에는 curr_node 변수만 사용 +class Solution: + def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: + prev_node, curr_node = None, head + + while curr_node: + # next를 먼저 저장해두지 않으면 링크를 끊은 뒤 다음 노드를 잃어리므로 temp에 저장 + temp = curr_node.next + + # curr_node의 다음 노드로 prev_node를 저장 + curr_node.next = prev_node + + # prev_node와 curr_node에 각각 curr_node와 temp 노드를 저장하여 순서 바꾸기 + prev_node, curr_node = curr_node, temp + + return prev_node + +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next From 04c6c985059bffd356d5e288c04a221b0b95b6f6 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月15日 16:14:28 +0900 Subject: [PATCH 350/526] [7th batch] week 7 - number of islands --- number-of-islands/liza0525.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 number-of-islands/liza0525.py diff --git a/number-of-islands/liza0525.py b/number-of-islands/liza0525.py new file mode 100644 index 0000000000..db6a2b86f3 --- /dev/null +++ b/number-of-islands/liza0525.py @@ -0,0 +1,34 @@ +# 7기 풀이 +# 시간 복잡도: O(n * m) +# - grid의 크기 n * m 에 따라 시간 복잡도가 정해짐(최악은 모든 grid 인덱스를 다 돌 때) +# 공간 복잡도: O(n * m) +# - 재귀 호출 스택의 최대 크기는 grid 이차 배열의 크기와 동일 +class Solution: + def numIslands(self, grid: List[List[str]]) -> int: + len_i, len_j = len(grid), len(grid[0]) + directions = [(1, 0), (-1, 0), (0, -1), (0 , 1)] # 탐색 방향(위, 아래, 왼쪽, 오른쪽 순) + + res = 0 + + def dfs(i, j): + grid[i][j] = "0" # 방문을 했으면 grid의 값을 "0"으로 변경해 다음 탐색 시 다시 방문하지 않도록 함 + for dir_i, dir_j in directions: + next_i, next_j = i + dir_i, j + dir_j + + # 다음 탐색 인덱스가 배열 범위 내이면서 + # grid[next_i][next_j]가 "1"이어야 그 다음 방문을 할 수 있다. + if ( + 0 <= next_i < len_i + and 0 <= next_j < len_j + and grid[next_i][next_j] == "1" + ): + dfs(next_i, next_j) + + for i in range(len_i): + for j in range(len_j): + if grid[i][j] == "0": # grid가 "0"일 땐 섬이 아니므로 탐색하지 않는다. + continue + dfs(i, j) # 섬 찾기 + res += 1 # 섬을 다 찾은 후엔 res에 1을 추가한다. + + return res From bd9abe64916d522ca1cbe03cfeb321d14172f36c Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月17日 14:57:26 +0900 Subject: [PATCH 351/526] [7th batch] week 7 - longest substring without repeating characters --- .../liza0525.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 longest-substring-without-repeating-characters/liza0525.py diff --git a/longest-substring-without-repeating-characters/liza0525.py b/longest-substring-without-repeating-characters/liza0525.py new file mode 100644 index 0000000000..20c8cb8f08 --- /dev/null +++ b/longest-substring-without-repeating-characters/liza0525.py @@ -0,0 +1,22 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - 슬라이딩 윈도우 기법을 사용, s의 길이 n에 비례 +# 공간 복잡도: O(min(n, k)) +# - 중복 문자를 저장 및 체크할 char_set의 최대 크기인 k(s의 모든 문자가 중복하지 않을 때)와 s의 크기 n 중 작은 쪽 +class Solution: + def lengthOfLongestSubstring(self, s: str) -> int: + max_len = 0 + left = 0 # 왼쪽 포인터 지정 + char_set = set() # 중복 문자 체크를 위한 set 추가 + + # right를 하나씩 옮겨가며 문자열 길이를 체크, + for right in range(len(s)): + while s[right] in char_set: + # 중복 문자가 생길 경우 left를 움직이되, 중복된 문자 이전의 모든 문자를 제한다. + char_set.remove(s[left]) + left += 1 + + char_set.add(s[right]) # 현재의 문자인 s[right]를 char_set에 저장하여 다음 루프에 중복 체크를 하도록 한다. + max_len = max(max_len, right - left + 1) # 현재까지의 가장 긴 문자열을 계산하여 max_len 업데이트 + + return max_len From 95584fe6a2f09286049fae212b728383539de340 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月17日 14:57:40 +0900 Subject: [PATCH 352/526] [7th batch] week 7 - unique paths --- unique-paths/liza0525.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 unique-paths/liza0525.py diff --git a/unique-paths/liza0525.py b/unique-paths/liza0525.py new file mode 100644 index 0000000000..d04eb25a69 --- /dev/null +++ b/unique-paths/liza0525.py @@ -0,0 +1,16 @@ +# 7기 풀이 +# 시간 복잡도: O(m * n) +# - m과 n 만큼의 이중 루프를 돌게 됨 +# 공간 복잡도: O(m) +# - dp의 결과 값을 저장할 배열의 길이는 m의 길이에 좌우됨 +class Solution: + def uniquePaths(self, m: int, n: int) -> int: + # 이전 열의 값만 필요로 하기 때문에 1차원 배열을 사용하며 in-place 업데이트를 하면 된다. + dp = [1 for _ in range(m)] + + for _ in range(n - 1): + for i in range(1, m): + # 현재 칸 = 위에서 오는 경로 수(갱신 전 dp[i]) + 왼쪽에서 오는 경로 수(dp[i-1]) + dp[i] = dp[i] + dp[i - 1] + + return dp[m - 1] # 모든 루프를 돌고 나면 도착지 도달 가능 방법수가 저장이 되어 있다. From dbed84b07cc33d58935df72c1e148c0c99c79627 Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年4月18日 00:20:53 +0900 Subject: [PATCH 353/526] add: reverseLinkedList solution --- reverse-linked-list/Cyjin-jani.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 reverse-linked-list/Cyjin-jani.js diff --git a/reverse-linked-list/Cyjin-jani.js b/reverse-linked-list/Cyjin-jani.js new file mode 100644 index 0000000000..456981b15c --- /dev/null +++ b/reverse-linked-list/Cyjin-jani.js @@ -0,0 +1,19 @@ +/** + * @param {ListNode} head + * @return {ListNode} + */ +const reverseList = function (head) { + if (!head) return null; + + let curr = head; + let prev = null; + + while (curr !== null) { + const next = curr.next; + curr.next = prev; + prev = curr; + curr = next; + } + + return prev; +}; From 27dedf62da3a44cffc41f4e44b848b2bc8d0d4dd Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年4月17日 11:52:30 -0700 Subject: [PATCH 354/526] reverse linked list solution --- reverse-linked-list/jylee2033.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 reverse-linked-list/jylee2033.py diff --git a/reverse-linked-list/jylee2033.py b/reverse-linked-list/jylee2033.py new file mode 100644 index 0000000000..358900aa36 --- /dev/null +++ b/reverse-linked-list/jylee2033.py @@ -0,0 +1,24 @@ +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: + # Handle empty list + if head is None: + return head + + prev = None + cur = head # Start from the head node + + # Traverse until the last node + while cur.next is not None: + nxt = cur.next # Store next node + cur.next = prev # Reverse the link + prev = cur # Move prev forward + cur = nxt # Move cur forward + + # Handle the last node + cur.next = prev + return cur From e75cdd4b5fff3a81beb5183e526810c2b3fb1347 Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年4月17日 11:55:44 -0700 Subject: [PATCH 355/526] add complexity --- reverse-linked-list/jylee2033.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/reverse-linked-list/jylee2033.py b/reverse-linked-list/jylee2033.py index 358900aa36..2729d6e8ac 100644 --- a/reverse-linked-list/jylee2033.py +++ b/reverse-linked-list/jylee2033.py @@ -22,3 +22,6 @@ def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: # Handle the last node cur.next = prev return cur + +# Time Complexity: O(n) +# Space Complexity: O(1) From af7c5dc109643a9d8ff0b06624e181ca7d0b7e36 Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年4月18日 13:48:59 +0900 Subject: [PATCH 356/526] week7: reverse-linked-list --- reverse-linked-list/reeseo3o.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 reverse-linked-list/reeseo3o.js diff --git a/reverse-linked-list/reeseo3o.js b/reverse-linked-list/reeseo3o.js new file mode 100644 index 0000000000..4686b9fd54 --- /dev/null +++ b/reverse-linked-list/reeseo3o.js @@ -0,0 +1,28 @@ +// Time Complexity: O(n) - 노드를 한 번만 순회 +// Space Complexity: O(1) - 변수 3개(prev, current, next)만 사용 +const reverseList = (head) => { + let prev = null; + let current = head; + + while (current !== null) { + const next = current.next; + current.next = prev; + prev = current; + current = next; + } + + return prev; +}; + +// Time Complexity: O(n) - 노드 수만큼 재귀 호출 +// Space Complexity: O(n) - 콜 스택이 노드 수만큼 쌓임 +const reverseListRecursive = (head) => { + if (head === null || head.next === null) return head; + + const newHead = reverseListRecursive(head.next); + + head.next.next = head; + head.next = null; + + return newHead; +}; From a5cc0300ff2c6d95b35c2c8e29528fca645e3adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=A4=EC=99=95=ED=83=9D=5FT6102=28Wang-Taek=20Oh=29?= Date: 2026年4月18日 17:08:00 +0900 Subject: [PATCH 357/526] Solved longest substring without repeating characters --- .../ohkingtaek.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 longest-substring-without-repeating-characters/ohkingtaek.py diff --git a/longest-substring-without-repeating-characters/ohkingtaek.py b/longest-substring-without-repeating-characters/ohkingtaek.py new file mode 100644 index 0000000000..5e717419a6 --- /dev/null +++ b/longest-substring-without-repeating-characters/ohkingtaek.py @@ -0,0 +1,23 @@ +""" +Time Complexity: O(n^2) +Space Complexity: O(n) + +과정: +1. 문자열을 순회하면서 중복되지 않는 가장 긴 부분 문자열을 찾음 +2. 중복되지 않는 부분 문자열을 찾으면 그 길이를 최대 길이와 비교하여 최대 길이를 업데이트함 +3. 중복되는 부분 문자열을 찾으면 그 부분 문자열을 초기화함 +4. 중복되지 않는 부분 문자열을 찾으면 그 부분 문자열을 최대 길이와 비교하여 최대 길이를 업데이트함 +""" + + +class Solution: + def lengthOfLongestSubstring(self, s: str) -> int: + ans = 0 + for left in range(len(s)): + tmp = set() + for right in range(left, len(s)): + if s[right] in tmp: + break + tmp.add(s[right]) + ans = max(right - left + 1, ans) + return ans From d1adc7a11772ca6de10ab645fc2923f510419592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=A4=EC=99=95=ED=83=9D=5FT6102=28Wang-Taek=20Oh=29?= Date: 2026年4月18日 17:08:10 +0900 Subject: [PATCH 358/526] solve number of islands --- number-of-islands/ohkingtaek.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 number-of-islands/ohkingtaek.py diff --git a/number-of-islands/ohkingtaek.py b/number-of-islands/ohkingtaek.py new file mode 100644 index 0000000000..b05ff9c737 --- /dev/null +++ b/number-of-islands/ohkingtaek.py @@ -0,0 +1,32 @@ +""" +Time Complexity: O(m * n) +Space Complexity: O(m * n) + +과정: +1. 2차원 배열을 순회하면서 1을 만나면 섬의 개수를 증가시킴 +2. DFS를 통해 해당 섬을 탐색함 +3. 해당 섬을 탐색하면서 0을 만나면 탐색을 종료함 +""" + + +class Solution: + def numIslands(self, grid: List[List[str]]) -> int: + ans = 0 + m, n = len(grid[0]), len(grid) + visited = [[0] * m for _ in range(n)] + dx, dy = [-1, 0, 1, 0], [0, -1, 0, 1] + for y in range(n): + for x in range(m): + if int(grid[y][x]) == 1 and visited[y][x] == 0: + ans += 1 + dfs = [(x, y)] + visited[y][x] = 1 + while dfs: + cx, cy = dfs.pop(0) + for _dx, _dy in zip(dx, dy): + gy = cy + _dy + gx = cx + _dx + if gx>= 0 and gy>= 0 and gx < m and gy < n and int(grid[gy][gx]) == 1 and visited[gy][gx] == 0: + visited[gy][gx] = 1 + dfs.append((gx, gy)) + return ans From 254bd980e48e2871680d6c4160f91fb686b830fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=A4=EC=99=95=ED=83=9D=5FT6102=28Wang-Taek=20Oh=29?= Date: 2026年4月18日 17:08:20 +0900 Subject: [PATCH 359/526] solve reverse linkedlist --- reverse-linked-list/ohkingtaek.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 reverse-linked-list/ohkingtaek.py diff --git a/reverse-linked-list/ohkingtaek.py b/reverse-linked-list/ohkingtaek.py new file mode 100644 index 0000000000..a4b56482e2 --- /dev/null +++ b/reverse-linked-list/ohkingtaek.py @@ -0,0 +1,25 @@ +""" +Time Complexity: O(n) +Space Complexity: O(1) + +과정: +1. 두 개의 포인터를 사용하여 리스트를 순회하면서 뒤집음 +2. 첫 번째 포인터는 이전 노드를 가리키고, 두 번째 포인터는 현재 노드를 가리킴 +3. 현재 노드의 next를 이전 노드로 변경하고, 두 포인터를 한 칸씩 이동시킴 +4. 마지막 노드까지 반복하면 리스트가 뒤집어짐 +""" + + +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next +class Solution: + def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: + left, now = None, head + while now: + right = now.next + now.next = left + left, now = now, right + return left From 43916f442842c9edf71f548b5f66a3f436af4d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=98=A4=EC=99=95=ED=83=9D=5FT6102=28Wang-Taek=20Oh=29?= Date: 2026年4月18日 17:08:31 +0900 Subject: [PATCH 360/526] solve set matrix zeroes --- set-matrix-zeroes/ohkingtaek.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 set-matrix-zeroes/ohkingtaek.py diff --git a/set-matrix-zeroes/ohkingtaek.py b/set-matrix-zeroes/ohkingtaek.py new file mode 100644 index 0000000000..7d5c027b6a --- /dev/null +++ b/set-matrix-zeroes/ohkingtaek.py @@ -0,0 +1,31 @@ +""" +Time Complexity: O(m * n) +Space Complexity: O(m + n) + +과정: +1. 0이 있는 행과 열을 따로 집합에 기록해둠 +2. 만들어진 행과 열을 기반으로 0으로 바꿔줌 +""" + + +class Solution: + def setZeroes(self, matrix: List[List[int]]) -> None: + """ + Do not return anything, modify matrix in-place instead. + """ + m, n = len(matrix[0]), len(matrix) + array = [] + for x in range(m): + for y in range(n): + if matrix[y][x] == 0: + array.append((x, y)) + a, b = set(), set() + for x, y in array: + a.add(x) + b.add(y) + for x in range(m): + for i in b: + matrix[i][x] = 0 + for y in range(n): + for i in a: + matrix[y][i] = 0 From 4c7f657a8601ba8f976bae4135f3532da260c562 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月18日 18:27:37 +0900 Subject: [PATCH 361/526] unique-paths solution --- unique-paths/hyeri0903.java | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 unique-paths/hyeri0903.java diff --git a/unique-paths/hyeri0903.java b/unique-paths/hyeri0903.java new file mode 100644 index 0000000000..df0ecf942c --- /dev/null +++ b/unique-paths/hyeri0903.java @@ -0,0 +1,33 @@ +class Solution { + public int uniquePaths(int m, int n) { + /** + 1.문제: finish로 가는 unique path 수 + 2.constraints: + - m: 세로, n = 가로 + - m,n min = 1, max = 100 + - right, down 으로만 움직이기 가능 + 3.solution + - dfs ?? => x, 모든 경로 탐색하지 않음 + - dp => [i][j] = [i-1][j] + [i][j-1] + - time: O(mn), space: O(n) + */ + + int[][] dp = new int[m][n]; + + //첫행, 첫열 = 1 + for(int i =0; i Date: 2026年4月18日 18:40:44 +0900 Subject: [PATCH 362/526] set-matrix-zeroes solution --- set-matrix-zeroes/hyeri0903.java | 37 ++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 set-matrix-zeroes/hyeri0903.java diff --git a/set-matrix-zeroes/hyeri0903.java b/set-matrix-zeroes/hyeri0903.java new file mode 100644 index 0000000000..4a4697203e --- /dev/null +++ b/set-matrix-zeroes/hyeri0903.java @@ -0,0 +1,37 @@ +class Solution { + public void setZeroes(int[][] matrix) { + /** + 1.문제: 0이 존재하는 위치의 모든 row, column을 0으로 set + 2.constraints: + - m,n min = 1, max = 200 + - space: O(mn)으로 풀이하지말 것, + 3.solution + - 0의 위치를 확인 -> 0의 위치는 여러개일 수 있음 + - row, col 각각 0의 위치 저장 + - time: O(mn), space O(m+n) + */ + int m = matrix.length; + int n = matrix[0].length; + int[] row = new int[m]; //0이 존재하는 row 위치이면 1, 아니면 0 + int[] col = new int[n]; //0이 존재하는 col 위치이면 1, 아니면 0 + + int x = 0; int y = 0; //0의 위치 + + for(int i = 0; i < m; i++) { + for(int j = 0; j < n; j++) { + if(matrix[i][j] == 0) { + row[i] = 1; + col[j] = 1; + } + } + } + + for(int i = 0; i < m; i++) { + for(int j = 0; j < n; j++) { + if(row[i] == 1 || col[j] == 1) { + matrix[i][j] = 0; + } + } + } + } +} From 2161c1919b5ad63e766eb4e3f86dbc6529ff6976 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年4月18日 18:47:11 +0900 Subject: [PATCH 363/526] =?UTF-8?q?7=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=205=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hwi-middle.cpp | 22 ++++ number-of-islands/hwi-middle.cpp | 49 ++++++++ reverse-linked-list/hwi-middle.cpp | 28 +++++ set-matrix-zeroes/hwi-middle.cpp | 108 ++++++++++++++++++ unique-paths/hwi-middle.cpp | 20 ++++ 5 files changed, 227 insertions(+) create mode 100644 longest-substring-without-repeating-characters/hwi-middle.cpp create mode 100644 number-of-islands/hwi-middle.cpp create mode 100644 reverse-linked-list/hwi-middle.cpp create mode 100644 set-matrix-zeroes/hwi-middle.cpp create mode 100644 unique-paths/hwi-middle.cpp diff --git a/longest-substring-without-repeating-characters/hwi-middle.cpp b/longest-substring-without-repeating-characters/hwi-middle.cpp new file mode 100644 index 0000000000..3f1c4ad194 --- /dev/null +++ b/longest-substring-without-repeating-characters/hwi-middle.cpp @@ -0,0 +1,22 @@ +class Solution { +public: + int lengthOfLongestSubstring(string s) { + int n = s.size(); + unordered_map m; // 현재 윈도우 내에 있는 문자 - 인덱스 + int maxLen = 0; + int l = 0; + for (int r = 0; r < n; ++r) + { + if (m.contains(s[r])) // 중복된 문자를 찾은 경우 + { + l = max(m[s[r]] + 1, l); // 해당 문자가 l보다 뒤에 있다면 l을 거기로 옮김 + } + + m[s[r]] = r; // s[r]의 위치 업데이트 + + maxLen = max(maxLen, r - l + 1); + } + + return maxLen; + } +}; diff --git a/number-of-islands/hwi-middle.cpp b/number-of-islands/hwi-middle.cpp new file mode 100644 index 0000000000..f57a1dd132 --- /dev/null +++ b/number-of-islands/hwi-middle.cpp @@ -0,0 +1,49 @@ +class Solution { +public: + int numIslands(vector>& grid) { + // BFS 기반 풀이 + int r = grid.size(); + int c = grid[0].size(); + + int cnt = 0; + for (int i = 0; i < r; ++i) + { + for (int j = 0; j < c; ++j) + { + if (grid[i][j] == '0') + { + continue; + } + + cnt++; + queue> q; + q.push({i, j}); + grid[i][j] = '0'; // 방문 여부를 저장하기 위해 grid를 직접 수정 + + while (!q.empty()) + { + int x, y; + tie(x, y) = q.front(); + q.pop(); + + int dx[] = { 0, 1, 0, -1 }; + int dy[] = { 1, 0, -1, 0 }; + + for (int dir = 0; dir < 4; ++dir) + { + int nx = x + dx[dir]; + int ny = y + dy[dir]; + + if (nx < 0 || nx>= r || ny < 0 || ny>= c) continue; + if (grid[nx][ny] == '0') continue; + + grid[nx][ny] = '0'; + q.push({nx, ny}); + } + } + } + } + + return cnt; + } +}; diff --git a/reverse-linked-list/hwi-middle.cpp b/reverse-linked-list/hwi-middle.cpp new file mode 100644 index 0000000000..8b49692f26 --- /dev/null +++ b/reverse-linked-list/hwi-middle.cpp @@ -0,0 +1,28 @@ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* reverseList(ListNode* head) { + ListNode* prev = nullptr; + ListNode* cur = head; + + // next를 이전 노드로 설정해나가며 루프 + while (cur != nullptr) + { + ListNode* tmp = cur->next; + cur->next = prev; + prev = cur; + cur = tmp; + } + + return prev; + } +}; diff --git a/set-matrix-zeroes/hwi-middle.cpp b/set-matrix-zeroes/hwi-middle.cpp new file mode 100644 index 0000000000..f177b18d4d --- /dev/null +++ b/set-matrix-zeroes/hwi-middle.cpp @@ -0,0 +1,108 @@ +// 풀이 1 +class Solution { +public: + void setZeroes(vector>& matrix) { + int m = matrix.size(); + int n = matrix[0].size(); + vector> v; + v.reserve(m * n); + + // 0인 칸을 별도의 공간에 마킹 + for (int i = 0; i < m; ++i) + { + for (int j = 0; j < n; ++j) + { + if (matrix[i][j] == 0) + { + v.push_back({i, j}); + } + } + } + + // 마킹이 끝난 후 해당 칸들을 확인하며 행과 열을 채움 + for (auto coord : v) + { + int x = coord.first; + int y = coord.second; + + // 행 + for (int i = 0; i < n; ++i) + { + matrix[x][i] = 0; + } + + // 열 + for (int i = 0; i < m; ++i) + { + matrix[i][y] = 0; + } + } + } +}; + +// 풀이 2 +class Solution { +public: + void setZeroes(vector>& matrix) { + int r = matrix.size(); + int c = matrix[0].size(); + + // 핵심 아이디어 + // - 각 행과 열에는 반드시 첫 번째 요소는 존재한다. + // - 이를 활용하여 각 행과 열의 첫 번째 요소를 마킹용으로 사용한다. + // - matrix[i][0]: i번째 행 전체를 0으로 만들어야 한다는 의미 + // - matrix[0][j]: j번째 열 전체를 0으로 만들어야 한다는 의미 + + // 엣지 케이스 + // - matrix[0][0]: 0번째 행인지, 0번째 열인지 구분할 수 없음 + + // 해결 방법 + // - matrix[0][0]은 0번째 행을 의미하도록 약속 + // - 0번째 열은 별도의 플래그를 둠 + + bool isFirstColZero = false; + for (int i = 0; i < r; ++i) + { + if (matrix[i][0] == 0) + { + isFirstColZero = true; + } + + for (int j = 1; j < c; ++j) + { + if (matrix[i][j] == 0) + { + matrix[i][0] = 0; + matrix[0][j] = 0; + } + } + } + + for (int i = 1; i < r; ++i) + { + for (int j = 1; j < c; ++j) + { + if (matrix[i][0] == 0 || matrix[0][j] == 0) + { + matrix[i][j] = 0; + } + } + } + + if (matrix[0][0] == 0) + { + for (int j = 0; j < c; j++) + { + matrix[0][j] = 0; + } + } + + if (isFirstColZero) + { + for (int i = 0; i < r; i++) + { + matrix[i][0] = 0; + } + } + } +}; diff --git a/unique-paths/hwi-middle.cpp b/unique-paths/hwi-middle.cpp new file mode 100644 index 0000000000..1f83463e57 --- /dev/null +++ b/unique-paths/hwi-middle.cpp @@ -0,0 +1,20 @@ +class Solution { +public: + int uniquePaths(int m, int n) { + // 결과 구하기: C(m + n - 2, m - 1) + + int k = min(m - 1, n - 1); // C(n, k) = C(n, n - k) + return combination(m + n - 2, k); + } + + int combination(int n, int k) + { + long long res = 1; + for (int i = 1; i <= k; ++i) + { + res = res * (n - i + 1) / i; + } + + return res; + } +}; From 1eb45c41717eb42fd19238fb75b22b5f0c795b77 Mon Sep 17 00:00:00 2001 From: hyejj19 Date: 2026年4月18日 19:33:19 +0900 Subject: [PATCH 364/526] solve number of islands --- number-of-islands/hyejj19.ts | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 number-of-islands/hyejj19.ts diff --git a/number-of-islands/hyejj19.ts b/number-of-islands/hyejj19.ts new file mode 100644 index 0000000000..3409423e3f --- /dev/null +++ b/number-of-islands/hyejj19.ts @@ -0,0 +1,42 @@ +// sc : O(n*m) +// tc : O(n*m) +function numIslands(grid: string[][]): number { + let count = 0; + const visited = Array.from({length: grid.length}, () => + Array.from({length: grid[0].length}, () => false), + ); + const directions = [ + [-1, 0], + [1, 0], + [0, -1], + [0, 1], + ]; + + function explore(x, y) { + visited[x][y] = true; + for (let [dx, dy] of directions) { + const nx = dx + x; + const ny = dy + y; + if ( + nx < grid.length && + ny < grid[0].length && + nx>= 0 && + ny>= 0 && + !visited[nx][ny] && + grid[nx][ny] === '1' + ) { + explore(nx, ny); + } + } + } + + for (let x = 0; x < grid.length; x++) { + for (let y = 0; y < grid[x].length; y++) { + if (!visited[x][y] && grid[x][y] === '1') { + count++; + explore(x, y); + } + } + } + return count; +} From 868f0336446aeb18654b8e6029b7018b5c543c67 Mon Sep 17 00:00:00 2001 From: juhui Date: 2026年4月18日 20:20:48 +0900 Subject: [PATCH 365/526] WEEK 07 Solutions --- reverse-linked-list/juhui-jeong.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 reverse-linked-list/juhui-jeong.java diff --git a/reverse-linked-list/juhui-jeong.java b/reverse-linked-list/juhui-jeong.java new file mode 100644 index 0000000000..6aeb599382 --- /dev/null +++ b/reverse-linked-list/juhui-jeong.java @@ -0,0 +1,18 @@ +/** +시간복잡도: O(n) +공간복잡도: O(1) + */ +class Solution { + public ListNode reverseList(ListNode head) { + ListNode prev = null; + ListNode curr = head; + + while(curr != null) { + ListNode next = curr.next; + curr.next = prev; + prev = curr; + curr = next; + } + return prev; + } +} From 0b9dc572cccf73d96468661923877b928e6b56d6 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年4月18日 21:27:24 +0900 Subject: [PATCH 366/526] solved set-matrix-zeros, tried longest-substring-... --- .../sangbeenmoon.py | 16 ++++++++++++++ set-matrix-zeroes/sangbeenmoon.py | 22 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 longest-substring-without-repeating-characters/sangbeenmoon.py create mode 100644 set-matrix-zeroes/sangbeenmoon.py diff --git a/longest-substring-without-repeating-characters/sangbeenmoon.py b/longest-substring-without-repeating-characters/sangbeenmoon.py new file mode 100644 index 0000000000..eb2d80bd74 --- /dev/null +++ b/longest-substring-without-repeating-characters/sangbeenmoon.py @@ -0,0 +1,16 @@ +class Solution: + def lengthOfLongestSubstring(self, s: str) -> int: + + start = 0 + last_seen = {} + answer = 0 + + for i,ch in enumerate(s): + if ch in last_seen: + if start < last_seen[ch]: + start = last_seen[ch] + 1 + + last_seen[ch] = i + answer = max(answer, i - start + 1) + + return answer diff --git a/set-matrix-zeroes/sangbeenmoon.py b/set-matrix-zeroes/sangbeenmoon.py new file mode 100644 index 0000000000..b4e010c14b --- /dev/null +++ b/set-matrix-zeroes/sangbeenmoon.py @@ -0,0 +1,22 @@ +# SC : O(m+n) + +class Solution: + def setZeroes(self, matrix: List[List[int]]) -> None: + """ + Do not return anything, modify matrix in-place instead. + """ + m,n = len(matrix), len(matrix[0]) + + row_dict = {} + col_dict = {} + + for r in range(m): + for c in range(n): + if matrix[r][c] == 0: + row_dict[r] = True + col_dict[c] = True + + for r in range(m): + for c in range(n): + if r in row_dict or c in col_dict: + matrix[r][c] = 0 From 54e83c9d53d463f602b8c01aedd5cc3df74a1aab Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年4月18日 21:32:47 +0900 Subject: [PATCH 367/526] chore: EOL --- reverse-linked-list/sangbeenmoon.py | 1 - 1 file changed, 1 deletion(-) diff --git a/reverse-linked-list/sangbeenmoon.py b/reverse-linked-list/sangbeenmoon.py index 66526e01b2..25879ac4d5 100644 --- a/reverse-linked-list/sangbeenmoon.py +++ b/reverse-linked-list/sangbeenmoon.py @@ -17,4 +17,3 @@ def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: cur = cur.next return p - \ No newline at end of file From 65c7d88a3b74551cc1a9b40088cc12988fd3a749 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年4月18日 21:42:03 +0900 Subject: [PATCH 368/526] =?UTF-8?q?feat:=20=EB=B0=98=EB=B3=B5=EB=AC=B8?= =?UTF-8?q?=EC=9D=84=20=EC=9D=B4=EC=9A=A9=ED=95=9C=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reverse-linked-list/gyeo-ri.py | 47 ++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 reverse-linked-list/gyeo-ri.py diff --git a/reverse-linked-list/gyeo-ri.py b/reverse-linked-list/gyeo-ri.py new file mode 100644 index 0000000000..c64015f75e --- /dev/null +++ b/reverse-linked-list/gyeo-ri.py @@ -0,0 +1,47 @@ +# Definition for singly-linked list. +class ListNode: + def __init__(self, val=0, next=None): + self.val: int = val + self.next: ListNode | None = next + + +class Solution: + def reverseList(self, head: ListNode | None) -> ListNode | None: + reversed_node = None + + while head: + reversed_node = ListNode(head.val, next=reversed_node) + + if not head.next: + return reversed_node + + else: + head = head.next + + +if __name__ == "__main__": + test_cases = [ + ([1, 2, 3, 4, 5], [5, 4, 3, 2, 1]), + ([1, 2], [2, 1]), + ([], []), + ] + + solution = Solution() + + for idx, (inp, expected) in enumerate(test_cases, start=1): + head = None + for value in reversed(inp): + head = ListNode(value, head) + + result = solution.reverseList(head) + + result_list = [] + while result is not None: + result_list.append(result.val) + result = result.next + + assert ( + result_list == expected + ), f"Test Case {idx} Failed: Expected {expected}, Got {result_list}" + + print("All test cases passed.") From 1fa2f2a7f4f0b8db7d1d20468e96db0ef9b7c0cf Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年4月18日 22:08:11 +0900 Subject: [PATCH 369/526] =?UTF-8?q?fix:=20=EA=B8=B0=EC=A1=B4=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B0=80=EB=8F=85=EC=84=B1=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reverse-linked-list/gyeo-ri.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/reverse-linked-list/gyeo-ri.py b/reverse-linked-list/gyeo-ri.py index c64015f75e..46a711dd67 100644 --- a/reverse-linked-list/gyeo-ri.py +++ b/reverse-linked-list/gyeo-ri.py @@ -7,16 +7,16 @@ def __init__(self, val=0, next=None): class Solution: def reverseList(self, head: ListNode | None) -> ListNode | None: + current_node = head reversed_node = None - while head: - reversed_node = ListNode(head.val, next=reversed_node) + while current_node: + reversed_node = ListNode(current_node.val, next=reversed_node) - if not head.next: + if not current_node.next: return reversed_node - else: - head = head.next + current_node = current_node.next if __name__ == "__main__": From 705d43fc74fe6a12b57f8f9e73e5fbf5ff2b9172 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年4月18日 22:17:57 +0900 Subject: [PATCH 370/526] =?UTF-8?q?fix:=20=EB=A9=94=EB=AA=A8=EB=A6=AC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=EB=9F=89=20=EC=A0=88=EA=B0=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reverse-linked-list/gyeo-ri.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/reverse-linked-list/gyeo-ri.py b/reverse-linked-list/gyeo-ri.py index 46a711dd67..0119623f42 100644 --- a/reverse-linked-list/gyeo-ri.py +++ b/reverse-linked-list/gyeo-ri.py @@ -11,12 +11,14 @@ def reverseList(self, head: ListNode | None) -> ListNode | None: reversed_node = None while current_node: - reversed_node = ListNode(current_node.val, next=reversed_node) + next_node = current_node.next + current_node.next = reversed_node - if not current_node.next: - return reversed_node + if next_node is None: + return current_node - current_node = current_node.next + reversed_node = current_node + current_node = next_node if __name__ == "__main__": From 0b94abbc140583bb8f9e8e92f23b502c0603c324 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年4月18日 22:56:02 +0900 Subject: [PATCH 371/526] =?UTF-8?q?fix:=20=EC=9E=AC=EA=B7=80=EB=A5=BC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=9C=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reverse-linked-list/gyeo-ri.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/reverse-linked-list/gyeo-ri.py b/reverse-linked-list/gyeo-ri.py index 0119623f42..995599ca22 100644 --- a/reverse-linked-list/gyeo-ri.py +++ b/reverse-linked-list/gyeo-ri.py @@ -5,6 +5,29 @@ def __init__(self, val=0, next=None): self.next: ListNode | None = next +# 재귀를 사용한 최종 풀이 +class Solution: + def reverseList(self, head: ListNode | None) -> ListNode | None: + # 1. 리스트가 비었거나(head is None) 마지막 노드일 때(head.next is None)는 종료 + if head is None or head.next is None: + return head + + # 2. 현재 노드(=head)를 제외하고, 다음 노드(next_node)부터 끝까지를 재귀 호출(뒤쪽 리스트를 뒤집기) + next_node = head.next + reversed_node = self.reverseList(next_node) + + # 3. 현재 노드를 뒤집힌 이전 노드(reversed_node)의 뒤에 붙이기 + # reversed_node의 가장 끝은 head.next이므로, head를 next_node 뒤에 붙인 다음 마지막 노드로 표시(head.next = None) + next_node.next = head + head.next = None + + # 4. 최종 노드를 반환 + # 2의 reversed_node는 head(=마지막 노드)가 빠진 상태였지만 3에서 next_node -> head를 연결하면서 완성됨 + return reversed_node + + +""" +# 반복문을 사용한 풀이 class Solution: def reverseList(self, head: ListNode | None) -> ListNode | None: current_node = head @@ -19,6 +42,7 @@ def reverseList(self, head: ListNode | None) -> ListNode | None: reversed_node = current_node current_node = next_node +""" if __name__ == "__main__": From f3179cb5f1660918a739fd52164d21ff028053cb Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年4月18日 23:02:27 +0900 Subject: [PATCH 372/526] =?UTF-8?q?feat:=20=EA=B2=B0=EA=B3=BC=20=EC=9A=94?= =?UTF-8?q?=EC=95=BD=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reverse-linked-list/gyeo-ri.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/reverse-linked-list/gyeo-ri.py b/reverse-linked-list/gyeo-ri.py index 995599ca22..f00908d9a5 100644 --- a/reverse-linked-list/gyeo-ri.py +++ b/reverse-linked-list/gyeo-ri.py @@ -1,3 +1,16 @@ +""" +[결과 요약] +# 시도한 로직 수: 3 + 1. 반복문을 사용한 풀이: 코드는 짧고 성능은 좋지만 (새로운 노드 객체 정의를 위해) 불필요한 메모리 사용이 있어 (2)에서 개선함 + - 시간복잡도 O(n) / 공간복잡도 O(n) + 2. 반복문 풀이와 메모리 개선: 기존 노드(ListNode)의 연결 관계(next)를 직접 바꾸는 방식) + - 시간복잡도 O(n) / 공간복잡도 O(1) + 3. 재귀 풀이: 반복문과 시간복잡도는 동일하나 실제 실행 속도가 약간 느리고, 공간복잡도에서는 불리함 + - 재귀는 기본적으로 공간의 깊이에 비례하여 O(1)의 공간복잡도가 나오기는 어려움 + - 시간복잡도 O(n) / 공간복잡도 O(n) +""" + + # Definition for singly-linked list. class ListNode: def __init__(self, val=0, next=None): From 1c21f129047fdc638571efa31318b1c157f53c95 Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: 2026年4月19日 18:17:56 +0900 Subject: [PATCH 373/526] sadie100: longest substring solution --- .../sadie100.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 longest-substring-without-repeating-characters/sadie100.ts diff --git a/longest-substring-without-repeating-characters/sadie100.ts b/longest-substring-without-repeating-characters/sadie100.ts new file mode 100644 index 0000000000..367060cf94 --- /dev/null +++ b/longest-substring-without-repeating-characters/sadie100.ts @@ -0,0 +1,30 @@ +/* +투 포인터 start와 end 생성, end를 1씩 증가하며 s를 탐색한다 +각 문자열의 마지막 위치를 기록하는 locate Map을 생성한다 +end값이 locate에 이미 존재하는데 start가 해당값+1보다 작을 경우, start를 해당값+1로 변경하고 locate를 업데이트, 이어서 탐색한다 +매번 탐색마다 최대 길이 result를 갱신한다 + +시간복잡도 : O(N) - 단일 순회 +공간복잡도 : O(N) (locate Map) + + +*/ + +function lengthOfLongestSubstring(s: string): number { + let start = 0 + let end = 0 + const locate = new Map() + let result = 0 + + while (end < s.length) { + let char = s[end] + if (locate.has(char)) { + start = Math.max(start, locate.get(char) + 1) + } + locate.set(char, end) + result = Math.max(result, end - start + 1) + end += 1 + } + + return result +} From 12b4a1ecd6888eeee07e2868d0b2423e05c889bf Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: 2026年4月19日 19:22:06 +0900 Subject: [PATCH 374/526] sadie100: number of islands solution --- number-of-islands/sadie100.ts | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 number-of-islands/sadie100.ts diff --git a/number-of-islands/sadie100.ts b/number-of-islands/sadie100.ts new file mode 100644 index 0000000000..75ed061b4a --- /dev/null +++ b/number-of-islands/sadie100.ts @@ -0,0 +1,45 @@ +/* +m x n visited 이중배열을 만들고 grid를 탐색, +visited false면서 1값이 있는 타일이 있으면 dfs로 상하좌우를 탐색, visited true로 만든 뒤 result+=1한다 +탐색이 마치면 result를 리턴한다 + +시간복잡도 : O(M + N) +공간복잡도 : O(M + N) - visited +*/ + +const dx = [0, 1, -1, 0] +const dy = [1, 0, 0, -1] + +function numIslands(grid: string[][]): number { + const visited = Array.from({ length: grid.length }, () => + new Array(grid[0].length).fill(false), + ) + let result = 0 + + function search(row: number, col: number) { + visited[row][col] = true + + for (let i = 0; i < 4; i++) { + const newRow = row + dx[i] + const newCol = col + dy[i] + + if (newRow < 0 || newRow>= grid.length) continue + if (newCol < 0 || newCol>= grid[0].length) continue + + if (visited[newRow][newCol] === false && grid[newRow][newCol] === '1') { + search(newRow, newCol) + } + } + } + + for (let i = 0; i < grid.length; i++) { + for (let j = 0; j < grid[0].length; j++) { + if (visited[i][j] === false && grid[i][j] === '1') { + search(i, j) + result += 1 + } + } + } + + return result +} From 1a7ba4c7d6909f8df33b4220f16fa731550f12e7 Mon Sep 17 00:00:00 2001 From: yihyun-kim1 Date: 2026年4月19日 23:16:42 +0900 Subject: [PATCH 375/526] add solution: number-of-islands --- number-of-islands/yihyun-kim1.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 number-of-islands/yihyun-kim1.js diff --git a/number-of-islands/yihyun-kim1.js b/number-of-islands/yihyun-kim1.js new file mode 100644 index 0000000000..25a554f104 --- /dev/null +++ b/number-of-islands/yihyun-kim1.js @@ -0,0 +1,30 @@ +/** + * @param {character[][]} grid + * @return {number} + */ +var numIslands = function (grid) { + let count = 0; + + const dfs = (i, j) => { + if (i < 0 || i>= grid.length || j < 0 || j>= grid[0].length) return; + if (grid[i][j] !== "1") return; + + grid[i][j] = "0"; + + dfs(i + 1, j); + dfs(i - 1, j); + dfs(i, j + 1); + dfs(i, j - 1); + }; + + for (let i = 0; i < grid.length; i++) { + for (let j = 0; j < grid[0].length; j++) { + if (grid[i][j] === "1") { + dfs(i, j); + count++; + } + } + } + + return count; +}; From f08f1474a47bd3562d32e310b1029fb3244f8eea Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: 2026年4月19日 23:30:55 +0900 Subject: [PATCH 376/526] =?UTF-8?q?sadie100:=20unique=20paths=20=ED=92=80?= =?UTF-8?q?=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- unique-paths/sadie100.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 unique-paths/sadie100.ts diff --git a/unique-paths/sadie100.ts b/unique-paths/sadie100.ts new file mode 100644 index 0000000000..3c6003fc38 --- /dev/null +++ b/unique-paths/sadie100.ts @@ -0,0 +1,20 @@ +/* +dp 배열 생성, top-left에서 bottom-right로 이동하며 위 값, 왼쪽 값을 더하며 dp를 업데이트, 마지막 원소를 리턴한다 + +시간복잡도 : O(m * n) +*/ + +const dx = [0, 1] +const dy = [1, 0] + +function uniquePaths(m: number, n: number): number { + const dp = Array.from({ length: m }, () => new Array(n).fill(1)) + + for (let i = 1; i < m; i++) { + for (let j = 1; j < n; j++) { + dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + } + } + + return dp[m - 1][n - 1] +} From dde78d80257ceb29e9ec70ceab8cf053e4770140 Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年4月19日 13:35:11 -0700 Subject: [PATCH 377/526] update reverse linked list --- reverse-linked-list/jylee2033.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/reverse-linked-list/jylee2033.py b/reverse-linked-list/jylee2033.py index 2729d6e8ac..a890395eca 100644 --- a/reverse-linked-list/jylee2033.py +++ b/reverse-linked-list/jylee2033.py @@ -6,22 +6,22 @@ class Solution: def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: # Handle empty list - if head is None: - return head + # if head is None: + # return head prev = None cur = head # Start from the head node # Traverse until the last node - while cur.next is not None: + while cur is not None: nxt = cur.next # Store next node cur.next = prev # Reverse the link prev = cur # Move prev forward cur = nxt # Move cur forward # Handle the last node - cur.next = prev - return cur + # cur.next = prev + return prev # Time Complexity: O(n) # Space Complexity: O(1) From 0f9547715e40123de9f498f57294e8437e173f5e Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年4月19日 15:05:09 -0700 Subject: [PATCH 378/526] reverse bits solution --- reverse-bits/jylee2033.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 reverse-bits/jylee2033.py diff --git a/reverse-bits/jylee2033.py b/reverse-bits/jylee2033.py new file mode 100644 index 0000000000..f2ded7faef --- /dev/null +++ b/reverse-bits/jylee2033.py @@ -0,0 +1,14 @@ +class Solution: + def reverseBits(self, n: int) -> int: + # 0100 + + res = 0 + + for _ in range(32): + res = (res << 1) | (n & 1) + n>>= 1 + + return res + +# Time Complexity: O(1) +# Space Complexity: O(1) From 8a555200f3ece5986040dcd22c84239dc8e1f3f9 Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: 2026年4月20日 14:48:57 +0900 Subject: [PATCH 379/526] reverse bits solution --- reverse-bits/robinyoon-dev.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 reverse-bits/robinyoon-dev.js diff --git a/reverse-bits/robinyoon-dev.js b/reverse-bits/robinyoon-dev.js new file mode 100644 index 0000000000..13565d7afe --- /dev/null +++ b/reverse-bits/robinyoon-dev.js @@ -0,0 +1,13 @@ +/** + * @param {number} n + * @return {number} + */ +var reverseBits = function(n) { + let result = 0; + for(let i = 0; i < 32; i++){ + result = result << 1; + result = result | (n & 1); + n = n>>> 1; + } + return result; +}; From 75fe3680f98789d921f85c2e3dc2273063283c1c Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: 2026年4月20日 20:41:27 +0900 Subject: [PATCH 380/526] add solution for reverse-bits --- dalestudy.iml | 91 ++++++++++++++++++++++++++++++++++++++ reverse-bits/Hyeri1ee.java | 13 ++++++ 2 files changed, 104 insertions(+) create mode 100644 dalestudy.iml create mode 100644 reverse-bits/Hyeri1ee.java diff --git a/dalestudy.iml b/dalestudy.iml new file mode 100644 index 0000000000..b1f695d02f --- /dev/null +++ b/dalestudy.iml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/reverse-bits/Hyeri1ee.java b/reverse-bits/Hyeri1ee.java new file mode 100644 index 0000000000..f9ffc93ce6 --- /dev/null +++ b/reverse-bits/Hyeri1ee.java @@ -0,0 +1,13 @@ +class Solution { + public int reverseBits(int n) { + int result =0; + for(int i=0; i< 32;i++){ + result <<= 1; + result |= (n & 1); + n>>= 1; + } + + return result; + } +} + From e2838326a01134e8d4d611055b23753cc1376f8c Mon Sep 17 00:00:00 2001 From: soobing Date: 2026年4月20日 21:56:26 +0900 Subject: [PATCH 381/526] refactor(soobing): rename soobing3.ts to soobing.ts Co-Authored-By: Claude Opus 4.7 --- 3sum/{soobing3.ts => soobing.ts} | 0 climbing-stairs/soobing.ts | 42 +++------ climbing-stairs/soobing3.ts | 14 --- coin-change/{soobing3.ts => soobing.ts} | 0 combination-sum/{soobing3.ts => soobing.ts} | 0 contains-duplicate/soobing.ts | 15 +-- contains-duplicate/soobing3.ts | 11 --- decode-ways/{soobing3.ts => soobing.ts} | 0 .../{soobing3.ts => soobing.ts} | 0 house-robber/soobing.ts | 42 ++------- house-robber/soobing3.ts | 10 -- .../{soobing3.ts => soobing.ts} | 0 .../{soobing3.ts => soobing.ts} | 0 maximum-subarray/soobing.ts | 16 ++-- maximum-subarray/soobing3.ts | 11 --- .../{soobing3.ts => soobing.ts} | 0 number-of-islands/soobing.ts | 92 +------------------ number-of-islands/soobing3.ts | 9 -- product-of-array-except-self/soobing.ts | 23 ++--- product-of-array-except-self/soobing3.ts | 20 ---- .../{soobing3.ts => soobing.ts} | 0 two-sum/soobing.ts | 42 +++++---- two-sum/soobing3.ts | 29 ------ valid-anagram/soobing.ts | 58 +++--------- valid-anagram/soobing3.ts | 20 ---- valid-palindrome/{soobing3.ts => soobing.ts} | 0 validate-binary-search-tree/soobing.ts | 55 ++++------- validate-binary-search-tree/soobing3.ts | 24 ----- word-search/{soobing3.ts => soobing.ts} | 0 29 files changed, 109 insertions(+), 424 deletions(-) rename 3sum/{soobing3.ts => soobing.ts} (100%) delete mode 100644 climbing-stairs/soobing3.ts rename coin-change/{soobing3.ts => soobing.ts} (100%) rename combination-sum/{soobing3.ts => soobing.ts} (100%) delete mode 100644 contains-duplicate/soobing3.ts rename decode-ways/{soobing3.ts => soobing.ts} (100%) rename find-minimum-in-rotated-sorted-array/{soobing3.ts => soobing.ts} (100%) delete mode 100644 house-robber/soobing3.ts rename longest-consecutive-sequence/{soobing3.ts => soobing.ts} (100%) rename maximum-depth-of-binary-tree/{soobing3.ts => soobing.ts} (100%) delete mode 100644 maximum-subarray/soobing3.ts rename merge-two-sorted-lists/{soobing3.ts => soobing.ts} (100%) delete mode 100644 number-of-islands/soobing3.ts delete mode 100644 product-of-array-except-self/soobing3.ts rename top-k-frequent-elements/{soobing3.ts => soobing.ts} (100%) delete mode 100644 two-sum/soobing3.ts delete mode 100644 valid-anagram/soobing3.ts rename valid-palindrome/{soobing3.ts => soobing.ts} (100%) delete mode 100644 validate-binary-search-tree/soobing3.ts rename word-search/{soobing3.ts => soobing.ts} (100%) diff --git a/3sum/soobing3.ts b/3sum/soobing.ts similarity index 100% rename from 3sum/soobing3.ts rename to 3sum/soobing.ts diff --git a/climbing-stairs/soobing.ts b/climbing-stairs/soobing.ts index 3a95e3a0da..79efb4f201 100644 --- a/climbing-stairs/soobing.ts +++ b/climbing-stairs/soobing.ts @@ -1,34 +1,14 @@ -/** - * 문제 유형 - * - DP (피보나치) - * - * 문제 설명 - * - 계단을 올라가는 방법의 수를 구하기 - * - * 아이디어 - * 1) 피보나치 수열 활용 - * - climbStairs(n) = climbStairs(n-1) + climbStairs(n-2) - */ -function climbStairsBottomUp(n: number): number { - function fibonacci(n: number, memo = new Map()) { - if (n === 1) return 1; - if (n === 2) return 2; +function climbStairs(n: number): number { + const memo = new Map(); + + function dp (n: number): number { + if(n <= 1) return 1; + if(memo.has(n)) return memo.get(n)!; - if (memo.has(n)) return memo.get(n); - const result = fibonacci(n - 1, memo) + fibonacci(n - 2, memo); - memo.set(n, result); - return result; + const result = dp(n-1) + dp(n-2); + memo.set(n, result); + return result; } - return fibonacci(n); -} -function climbStairsTopDown(n: number): number { - const dp = new Array(n + 1).fill(0); - dp[1] = 1; - dp[2] = 2; - - for (let i = 3; i <= n; i++) { - dp[i] = dp[i - 1] + dp[i - 2]; - } - return dp[n]; -} + return dp(n); +}; diff --git a/climbing-stairs/soobing3.ts b/climbing-stairs/soobing3.ts deleted file mode 100644 index 79efb4f201..0000000000 --- a/climbing-stairs/soobing3.ts +++ /dev/null @@ -1,14 +0,0 @@ -function climbStairs(n: number): number { - const memo = new Map(); - - function dp (n: number): number { - if(n <= 1) return 1; - if(memo.has(n)) return memo.get(n)!; - - const result = dp(n-1) + dp(n-2); - memo.set(n, result); - return result; - } - - return dp(n); -}; diff --git a/coin-change/soobing3.ts b/coin-change/soobing.ts similarity index 100% rename from coin-change/soobing3.ts rename to coin-change/soobing.ts diff --git a/combination-sum/soobing3.ts b/combination-sum/soobing.ts similarity index 100% rename from combination-sum/soobing3.ts rename to combination-sum/soobing.ts diff --git a/contains-duplicate/soobing.ts b/contains-duplicate/soobing.ts index a8ce40ac0d..01d03961d4 100644 --- a/contains-duplicate/soobing.ts +++ b/contains-duplicate/soobing.ts @@ -1,10 +1,11 @@ function containsDuplicate(nums: number[]): boolean { - const map = new Map(); - for (let i = 0; i < nums.length; i++) { - if (map.get(nums[i])) { - return true; - } else map.set(nums[i], 1); + const checkMap = new Map(); + for(const n of nums) { + if(checkMap.has(n)) { + return true; + } else { + checkMap.set(n, 1); + } } - return false; -} +}; diff --git a/contains-duplicate/soobing3.ts b/contains-duplicate/soobing3.ts deleted file mode 100644 index 01d03961d4..0000000000 --- a/contains-duplicate/soobing3.ts +++ /dev/null @@ -1,11 +0,0 @@ -function containsDuplicate(nums: number[]): boolean { - const checkMap = new Map(); - for(const n of nums) { - if(checkMap.has(n)) { - return true; - } else { - checkMap.set(n, 1); - } - } - return false; -}; diff --git a/decode-ways/soobing3.ts b/decode-ways/soobing.ts similarity index 100% rename from decode-ways/soobing3.ts rename to decode-ways/soobing.ts diff --git a/find-minimum-in-rotated-sorted-array/soobing3.ts b/find-minimum-in-rotated-sorted-array/soobing.ts similarity index 100% rename from find-minimum-in-rotated-sorted-array/soobing3.ts rename to find-minimum-in-rotated-sorted-array/soobing.ts diff --git a/house-robber/soobing.ts b/house-robber/soobing.ts index ad17c73f30..32d0bed9e9 100644 --- a/house-robber/soobing.ts +++ b/house-robber/soobing.ts @@ -1,34 +1,10 @@ -/** - * 문제 설명 - * - 주어진 배열의 시작과 끝이 연결되어 있는 원형이라고 할 경우에, 이웃하는 집은 털 수 없고 최대로 털 수 있는 돈을 구하는 문제 - * - * 아이디어 - * 1) 동적 계획법(Dynamic Programming) 활용 - * - 원형 구조이므로 첫번째 집과 마지막집은 동시에 털 수 없음 - * - 따라서 두 가지 경우로 나누어 계산하고, 두 결과 중 더 큰 값을 반환 - * 2) 선형 배열에 대한 최대 금액 계산 - * - 매 순회마다 현재 집을 털 경우(prev2 + num)와 털지 않을 경우(prev1) 중 큰 값을 선택 - * - 최종적으로 prev1에 최대값이 저장 - */ -function robLinear(nums: number[]) { - let prev1 = 0; - let prev2 = 0; - - for (const num of nums) { - const temp = prev1; - prev1 = Math.max(prev2 + num, prev1); - prev2 = temp; - } - - return prev1; -} - function rob(nums: number[]): number { - if (nums.length === 1) return nums[0]; - if (nums.length === 2) return Math.max(nums[0], nums[1]); - - const temp1 = robLinear(nums.slice(0, nums.length - 1)); - const temp2 = robLinear(nums.slice(1)); - - return Math.max(temp1, temp2); -} + const dp = new Array(nums.length); + dp[0] = nums[0]; + dp[1] = Math.max(nums[0], nums[1]); + + for(let i = 2; i < nums.length; i++) { + dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i]); + } + return dp[nums.length - 1]; +}; diff --git a/house-robber/soobing3.ts b/house-robber/soobing3.ts deleted file mode 100644 index 32d0bed9e9..0000000000 --- a/house-robber/soobing3.ts +++ /dev/null @@ -1,10 +0,0 @@ -function rob(nums: number[]): number { - const dp = new Array(nums.length); - dp[0] = nums[0]; - dp[1] = Math.max(nums[0], nums[1]); - - for(let i = 2; i < nums.length; i++) { - dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i]); - } - return dp[nums.length - 1]; -}; diff --git a/longest-consecutive-sequence/soobing3.ts b/longest-consecutive-sequence/soobing.ts similarity index 100% rename from longest-consecutive-sequence/soobing3.ts rename to longest-consecutive-sequence/soobing.ts diff --git a/maximum-depth-of-binary-tree/soobing3.ts b/maximum-depth-of-binary-tree/soobing.ts similarity index 100% rename from maximum-depth-of-binary-tree/soobing3.ts rename to maximum-depth-of-binary-tree/soobing.ts diff --git a/maximum-subarray/soobing.ts b/maximum-subarray/soobing.ts index 5cd3d4be76..9cd0073ed8 100644 --- a/maximum-subarray/soobing.ts +++ b/maximum-subarray/soobing.ts @@ -1,9 +1,11 @@ function maxSubArray(nums: number[]): number { - let currentSum = nums[0]; - let maxSum = nums[0]; - for (let i = 1; i < nums.length; i++) { - currentSum = Math.max(nums[i], currentSum + nums[i]); - maxSum = Math.max(maxSum, currentSum); + let max = nums[0]; + const dp = new Array(nums.length).fill(0); + dp[0] = Math.max(0, nums[0]); + + for(let i = 1; i < nums.length; i++) { + dp[i] = Math.max(dp[i-1] + nums[i], nums[i]); + max = Math.max(dp[i], max); } - return maxSum; -} + return max; +}; diff --git a/maximum-subarray/soobing3.ts b/maximum-subarray/soobing3.ts deleted file mode 100644 index 9cd0073ed8..0000000000 --- a/maximum-subarray/soobing3.ts +++ /dev/null @@ -1,11 +0,0 @@ -function maxSubArray(nums: number[]): number { - let max = nums[0]; - const dp = new Array(nums.length).fill(0); - dp[0] = Math.max(0, nums[0]); - - for(let i = 1; i < nums.length; i++) { - dp[i] = Math.max(dp[i-1] + nums[i], nums[i]); - max = Math.max(dp[i], max); - } - return max; -}; diff --git a/merge-two-sorted-lists/soobing3.ts b/merge-two-sorted-lists/soobing.ts similarity index 100% rename from merge-two-sorted-lists/soobing3.ts rename to merge-two-sorted-lists/soobing.ts diff --git a/number-of-islands/soobing.ts b/number-of-islands/soobing.ts index 8fdc56d4a9..5d2a326d9b 100644 --- a/number-of-islands/soobing.ts +++ b/number-of-islands/soobing.ts @@ -1,91 +1,9 @@ -/** - * 문제 설명 - * - 2차원 그리드에서 섬의 갯수를 구하는 문제 - * - * 조건 - * - 가로, 세로가 1로 인접해있는 경우 같은 섬으로 간주 - * - * 아이디어 - * - 경로 탐색, 네트워크, 조합 유형이 나오면 '그래프 탐색 알고리즘'을 떠울린다. - * 1) DFS (재귀) - * 2) BFS (링크드리스트 or 큐) - * - */ - -function numIslands(grid: string[][]): number { - const rows = grid.length; - const cols = grid[0].length; +function hammingWeight(n: number): number { let count = 0; - function dfs(r: number, c: number) { - if (r < 0 || c < 0 || r>= rows || c>= cols || grid[r][c] === "0") return; - - grid[r][c] = "0"; - dfs(r - 1, c); - dfs(r + 1, c); - dfs(r, c - 1); - dfs(r, c + 1); - } - - for (let r = 0; r < rows; r++) { - for (let c = 0; c < cols; c++) { - if (grid[r][c] === "1") { - count++; - dfs(r, c); - } - } - } - return count; -} - -/** - * - * BFS version - -function numIslands(grid: string[][]): number { - const rows = grid.length; - const cols = grid[0].length; - let count = 0; - - const directions = [ - [0, 1], - [1, 0], - [0, -1], - [-1, 0], - ]; - function bfs(r: number, c: number) { - const queue = [[r, c]]; - grid[r][c] = "0"; - - while (queue.length) { - const [row, col] = queue.shift()!; - - for (const [dr, dc] of directions) { - const newRow = row + dr; - const newCol = col + dc; - - if ( - newRow>= 0 && - newRow < rows && - newCol>= 0 && - newCol < cols && - grid[newRow][newCol] === "1" - ) { - queue.push([newRow, newCol]); - grid[newRow][newCol] = "0"; - } - } - } - } - - for (let r = 0; r < rows; r++) { - for (let c = 0; c < cols; c++) { - if (grid[r][c] === "1") { - count++; - bfs(r, c); + for(let i = 31; i>= 0; i--) { + if((n>> i) & 1) { + count++; } - } } return count; -} - - */ +}; diff --git a/number-of-islands/soobing3.ts b/number-of-islands/soobing3.ts deleted file mode 100644 index 5d2a326d9b..0000000000 --- a/number-of-islands/soobing3.ts +++ /dev/null @@ -1,9 +0,0 @@ -function hammingWeight(n: number): number { - let count = 0; - for(let i = 31; i>= 0; i--) { - if((n>> i) & 1) { - count++; - } - } - return count; -}; diff --git a/product-of-array-except-self/soobing.ts b/product-of-array-except-self/soobing.ts index c1caa1a859..e72350b9f7 100644 --- a/product-of-array-except-self/soobing.ts +++ b/product-of-array-except-self/soobing.ts @@ -1,19 +1,20 @@ function productExceptSelf(nums: number[]): number[] { - const left = Array(nums.length).fill(1); - const right = Array(nums.length).fill(1); - const result = Array(nums.length); + const n = nums.length; + const left = new Array(n).fill(1); + const right = new Array(n).fill(1); + const result = new Array(n).fill(1); - for (let i = 1; i < nums.length; i++) { - left[i] = left[i - 1] * nums[i - 1]; + for (let i = 1; i < n; i++) { + left[i] = nums[i-1] * left[i - 1]; } - for (let i = nums.length - 2; i>= 0; i--) { - right[i] = right[i + 1] * nums[i + 1]; + for (let i = n - 2; i>= 0; i--) { + right[i] = nums[i+1] * right[i + 1]; } - for (let i = 0; i < nums.length; i++) { - result[i] = left[i] * right[i]; + for (let i = 0; i < n; i++) { + result[i] = left[i] * right[i]; } - + return result; -} +}; diff --git a/product-of-array-except-self/soobing3.ts b/product-of-array-except-self/soobing3.ts deleted file mode 100644 index e72350b9f7..0000000000 --- a/product-of-array-except-self/soobing3.ts +++ /dev/null @@ -1,20 +0,0 @@ -function productExceptSelf(nums: number[]): number[] { - const n = nums.length; - const left = new Array(n).fill(1); - const right = new Array(n).fill(1); - const result = new Array(n).fill(1); - - for (let i = 1; i < n; i++) { - left[i] = nums[i-1] * left[i - 1]; - } - - for (let i = n - 2; i>= 0; i--) { - right[i] = nums[i+1] * right[i + 1]; - } - - for (let i = 0; i < n; i++) { - result[i] = left[i] * right[i]; - } - - return result; -}; diff --git a/top-k-frequent-elements/soobing3.ts b/top-k-frequent-elements/soobing.ts similarity index 100% rename from top-k-frequent-elements/soobing3.ts rename to top-k-frequent-elements/soobing.ts diff --git a/two-sum/soobing.ts b/two-sum/soobing.ts index dc909c1a18..2d4f5996e2 100644 --- a/two-sum/soobing.ts +++ b/two-sum/soobing.ts @@ -1,27 +1,29 @@ -// 1. Brute force function twoSum(nums: number[], target: number): number[] { - for (let i = 0; i < nums.length - 1; i++) { - for (let j = i + 1; j < nums.length; j++) { - if (nums[i] + nums[j] === target) { - return [i, j]; + const map = new Map(); + for(let i = 0; i < nums.length; i++) { + const current = map.get(nums[i]); + if(current) { + current.push(i); + } else { + map.set(nums[i], [i]); } - } } - return []; -} -// 2. Hashmap -function twoSum(nums: number[], target: number): number[] { - const map = new Map(); - for (let i = 0; i < nums.length; i++) { - map.set(nums[i], i); - } + nums.sort((a, b) => a - b); + let left = 0; + let right = nums.length - 1; - for (let i = 0; i < nums.length; i++) { - const targetIndex = map.get(target - nums[i]); - if (targetIndex && targetIndex !== i) { - return [i, targetIndex]; - } + while(left < right) { + if(nums[left] + nums[right] === target) { + return [map.get(nums[left])?.pop() ?? 0, map.get(nums[right])?.pop() ?? 0]; + } + + if(nums[left] + nums[right]> target) { + right--; + } else { + left++; + } } + return []; -} +}; diff --git a/two-sum/soobing3.ts b/two-sum/soobing3.ts deleted file mode 100644 index 2d4f5996e2..0000000000 --- a/two-sum/soobing3.ts +++ /dev/null @@ -1,29 +0,0 @@ -function twoSum(nums: number[], target: number): number[] { - const map = new Map(); - for(let i = 0; i < nums.length; i++) { - const current = map.get(nums[i]); - if(current) { - current.push(i); - } else { - map.set(nums[i], [i]); - } - } - - nums.sort((a, b) => a - b); - let left = 0; - let right = nums.length - 1; - - while(left < right) { - if(nums[left] + nums[right] === target) { - return [map.get(nums[left])?.pop() ?? 0, map.get(nums[right])?.pop() ?? 0]; - } - - if(nums[left] + nums[right]> target) { - right--; - } else { - left++; - } - } - - return []; -}; diff --git a/valid-anagram/soobing.ts b/valid-anagram/soobing.ts index 17869f5d53..66e505f804 100644 --- a/valid-anagram/soobing.ts +++ b/valid-anagram/soobing.ts @@ -1,52 +1,20 @@ -/** - * 문제 유형 - * - String - * - * 문제 설명 - * - 두 문자열이 애너그램인지 확인하기 - * - * 아이디어 - * 1) 문자열을 맵으로 변환하고, 정렬 후 비교하기 - * 2) 문자열 정렬 없이 하나의 map으로 더하고 빼기하여 0인지 확인하기 - */ -function mapString(str: string) { - const map = new Map(); - for (let i = 0; i < str.length; i++) { - map.set(str[i], (map.get(str[i]) || 0) + 1); - } - return map; -} function isAnagram(s: string, t: string): boolean { - const sMap = mapString(s); - const tMap = mapString(t); - - const sKeys = [...sMap.keys()].sort().join(""); - const tKeys = [...tMap.keys()].sort().join(""); + if(s.length !== t.length) return false; + + const sMap = new Map(); + const tMap = new Map(); - if (sKeys !== tKeys) return false; - - for (let i = 0; i < sKeys.length; i++) { - const key = sKeys[i]; - if (sMap.get(key) !== tMap.get(key)) return false; + for(const s_char of s) { + sMap.set(s_char, (sMap.get(s_char) ?? 0) + 1); } - return true; -} - -// 아이디어 2 -function isAnagramDeveloped(s: string, t: string): boolean { - if (s.length !== t.length) return false; - - const count = new Map(); - - for (let i = 0; i < s.length; i++) { - count.set(s[i], (count.get(s[i]) || 0) + 1); - count.set(t[i], (count.get(t[i]) || 0) - 1); + for(const t_char of t) { + tMap.set(t_char, (tMap.get(t_char) ?? 0) + 1); } - for (const val of count.values()) { - if (val !== 0) return false; + if(sMap.size !== tMap.size) return false; + for(const [sKey, sValue] of sMap) { + if(sValue !== tMap.get(sKey)) return false; } - - return true; -} + return true +}; diff --git a/valid-anagram/soobing3.ts b/valid-anagram/soobing3.ts deleted file mode 100644 index 66e505f804..0000000000 --- a/valid-anagram/soobing3.ts +++ /dev/null @@ -1,20 +0,0 @@ -function isAnagram(s: string, t: string): boolean { - if(s.length !== t.length) return false; - - const sMap = new Map(); - const tMap = new Map(); - - for(const s_char of s) { - sMap.set(s_char, (sMap.get(s_char) ?? 0) + 1); - } - - for(const t_char of t) { - tMap.set(t_char, (tMap.get(t_char) ?? 0) + 1); - } - - if(sMap.size !== tMap.size) return false; - for(const [sKey, sValue] of sMap) { - if(sValue !== tMap.get(sKey)) return false; - } - return true -}; diff --git a/valid-palindrome/soobing3.ts b/valid-palindrome/soobing.ts similarity index 100% rename from valid-palindrome/soobing3.ts rename to valid-palindrome/soobing.ts diff --git a/validate-binary-search-tree/soobing.ts b/validate-binary-search-tree/soobing.ts index cae6c35b9d..0d77d8bdff 100644 --- a/validate-binary-search-tree/soobing.ts +++ b/validate-binary-search-tree/soobing.ts @@ -1,39 +1,24 @@ /** - * 문제 유형 - * - Tree - * - * 문제 설명 - * - 이진 탐색 트리가 맞는지 확인하기 - * - * 아이디어 - * 1) 중위 순회 후 정렬된 배열인지 확인 - * + * Definition for a binary tree node. + * class TreeNode { + * val: number + * left: TreeNode | null + * right: TreeNode | null + * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + * } */ -class TreeNode { - val: number; - left: TreeNode | null; - right: TreeNode | null; - constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { - this.val = val === undefined ? 0 : val; - this.left = left === undefined ? null : left; - this.right = right === undefined ? null : right; - } -} -function isSorted(arr: number[]) { - for (let i = 1; i < arr.length; i++) { - if (arr[i - 1]>= arr[i]) return false; - } - return true; -} -function inorder(node: TreeNode | null, arr: number[]) { - if (node === null) return; - inorder(node.left, arr); - arr.push(node.val); - inorder(node.right, arr); -} function isValidBST(root: TreeNode | null): boolean { - const sortedArray: number[] = []; - inorder(root, sortedArray); - return isSorted(sortedArray); -} + function validate(node: TreeNode | null, min: number, max: number){ + if(node === null) return true; + + if(node.val <= min || node.val>= max) return false; + + return validate(node.left, min, node.val) && validate(node.right, node.val, max) + } + return validate(root, -Infinity, Infinity); +}; diff --git a/validate-binary-search-tree/soobing3.ts b/validate-binary-search-tree/soobing3.ts deleted file mode 100644 index 0d77d8bdff..0000000000 --- a/validate-binary-search-tree/soobing3.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Definition for a binary tree node. - * class TreeNode { - * val: number - * left: TreeNode | null - * right: TreeNode | null - * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - * } - */ - -function isValidBST(root: TreeNode | null): boolean { - function validate(node: TreeNode | null, min: number, max: number){ - if(node === null) return true; - - if(node.val <= min || node.val>= max) return false; - - return validate(node.left, min, node.val) && validate(node.right, node.val, max) - } - return validate(root, -Infinity, Infinity); -}; diff --git a/word-search/soobing3.ts b/word-search/soobing.ts similarity index 100% rename from word-search/soobing3.ts rename to word-search/soobing.ts From 345c2d04d444f6bae96c2d5487df3d43deb8c154 Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: 2026年4月21日 14:56:21 +0900 Subject: [PATCH 382/526] add solution for Palindromic-substrings --- palindromic-substrings/Hyeri1ee.java | 49 ++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 palindromic-substrings/Hyeri1ee.java diff --git a/palindromic-substrings/Hyeri1ee.java b/palindromic-substrings/Hyeri1ee.java new file mode 100644 index 0000000000..3a57e10032 --- /dev/null +++ b/palindromic-substrings/Hyeri1ee.java @@ -0,0 +1,49 @@ +class Solution { + //길이 1~s.length()까지 palindrome 함수 시도 + int cnt=0; // + + + public int countSubstrings(String s) { + + for(int len=1; len <= s.length();len++){//1~3 + for(int idx =0; idx <= s.length()-len ; idx++){ + //idx인덱스부터 len길이만큼의 문자열이 palindrome인지 판별 + boolean result = isPalindrome(s, idx, idx+len-1); //start: 시작 인덱스 , end: 끝 인덱스 + + if (result){ + cnt++; + } + } + } + + return cnt; + + } + + private static boolean isPalindrome(String w, int start, int end){ + if (start == end) return true; + //start!= end + int s = start; + int e = end; + while(s<= e){ + if(e < start && s> end) return true; + + + //서로 값이 다른 경우 + if (w.charAt(s) != w.charAt(e)){ + return false; + } + + //서로 값이 같은 경우 continue; + s++; + e--; + } + + + return true; + } + + +} + + From bd4afe01f014ebd899cb73f466bf8e318b795fae Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: 2026年4月21日 14:57:08 +0900 Subject: [PATCH 383/526] add solution for clone-graph --- clone-graph/Hyeri1ee.java | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 clone-graph/Hyeri1ee.java diff --git a/clone-graph/Hyeri1ee.java b/clone-graph/Hyeri1ee.java new file mode 100644 index 0000000000..f12d13c46a --- /dev/null +++ b/clone-graph/Hyeri1ee.java @@ -0,0 +1,48 @@ +import java.util.*; +/* +class Node { + public int val; + public List neighbors; + public Node() { + val = 0; + neighbors = new ArrayList(); + } + public Node(int _val) { + val = _val; + neighbors = new ArrayList(); + } + public Node(int _val, ArrayList _neighbors) { + val = _val; + neighbors = _neighbors; + } +} +*/ + + +class Solution { + + + //기존 node, 복사한 node + Map visited = new HashMap(); + public Node cloneGraph(Node node) { + if (node==null) return null; + + if (visited.containsKey(node)){ + return visited.get(node); + } + + //없는 경우 + Node newClone= new Node(node.val); + visited.put(node, newClone); + + //이웃 복사 + for(Node target : node.neighbors){ + newClone.neighbors.add(cloneGraph(target)); + } + + return newClone; + + } +} + + From da776029c00b945e68c2ee5c4ca84b7efb1ee04c Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: 2026年4月21日 14:58:21 +0900 Subject: [PATCH 384/526] add solution for LCS --- longest-common-subsequence/Hyeri1ee.java | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 longest-common-subsequence/Hyeri1ee.java diff --git a/longest-common-subsequence/Hyeri1ee.java b/longest-common-subsequence/Hyeri1ee.java new file mode 100644 index 0000000000..75a7378aa6 --- /dev/null +++ b/longest-common-subsequence/Hyeri1ee.java @@ -0,0 +1,33 @@ +import java.util.*; +class Solution { + public int longestCommonSubsequence(String text1, String text2) { + + + //int longerlen= (text1.length()>= text2.length()) ? text1.length() : text2.length(); + //int lesslen= (text1.length() <= text2.length()) ? text1.length() : text2.length(); + int[][] dp = new int[text1.length()+1][text2.length()+1]; + + //String longer>= text2.length()) ? text1 : text2; + //String lesstext= (text1.length() <= text2.length()) ? text1 : text2; + + + + for (int i = 1; i <=text1.length(); i++) { + for (int j = 1; j <=text2.length(); j++) { + //문자가 같으면 + if (text1.charAt(i-1) == text2.charAt(j-1)){ + dp[i][j] = dp[i-1][j-1]+1; + //System.out.println("dp["+i+"]["+j+"]: "+ dp[i][j]); + }else{ + //문자가 다르면 + dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]); + //System.out.println("dp["+i+"]["+j+"]: "+ dp[i][j]); + } + } + } + + + return dp[text1.length()][text2.length()]; + }//end of method +} + From dd005fbaabc3451c063ab5b4b404c199a44043f7 Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: 2026年4月21日 15:07:49 +0900 Subject: [PATCH 385/526] fix for linelint error --- dalestudy.iml | 91 --------------------------------------------------- 1 file changed, 91 deletions(-) delete mode 100644 dalestudy.iml diff --git a/dalestudy.iml b/dalestudy.iml deleted file mode 100644 index b1f695d02f..0000000000 --- a/dalestudy.iml +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From fbbbae1914446fc1c743f49c3f274fd95351ff9a Mon Sep 17 00:00:00 2001 From: Hyeri1ee Date: 2026年4月21日 15:55:24 +0900 Subject: [PATCH 386/526] add solution for longest-repeating-character-replacement --- .../Hyeri1ee.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 longest-repeating-character-replacement/Hyeri1ee.java diff --git a/longest-repeating-character-replacement/Hyeri1ee.java b/longest-repeating-character-replacement/Hyeri1ee.java new file mode 100644 index 0000000000..301f1ad3e1 --- /dev/null +++ b/longest-repeating-character-replacement/Hyeri1ee.java @@ -0,0 +1,61 @@ +class Solution { + //left,right + + //right를 left에서부터 이동하면서 max (대체해야되는 alphabet 수) 갱신 + //(right - left+ 1) - 다수등장alphabet 개수 = 대체해야되는 alphabet 수 + //대체해야되는 수 <= k 인 경우 완료 + //""> k 인 경우 left++ + + //빈도수 저장용 + int[] alpha = new int[26]; + int answer =0 ; + + public int characterReplacement(String s, int k) { + + //인덱스 정의 (초기값) + int left= 0; + int right= 0; + + + + while(right < s.length()){ + //현재 갱신된 right까지 빈도수 저장 + //System.out.println("[right] : " + right); + //System.out.println("[left] : " + left); + + alpha[s.charAt(right) - 'A']++; + + int max = mostSeenFrequency(left, right, alpha); + + + + while ((right-left + 1) - max> k) { + alpha[s.charAt(left) - 'A']--; + left++; + max = mostSeenFrequency(left, right, alpha); + } + + if (answer < right-left + 1){ + answer=right-left+1; + } + right++; + + //System.out.println("[answer] : " + answer); + + + }//end of while + + return answer; + + } + + private static int mostSeenFrequency(int left, int right, int[] alpha){ + int max =0; + for(int i=0;i<26;i++){ + if (max < alpha[i]) max=alpha[i]; + } + return max; + } +} + + From acf90533c18a23a1b2bbe0f1babecc6fdc8fd00a Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: 2026年4月21日 21:18:11 +0900 Subject: [PATCH 387/526] sadie100: reverse bits solution --- reverse-bits/sadie100.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 reverse-bits/sadie100.ts diff --git a/reverse-bits/sadie100.ts b/reverse-bits/sadie100.ts new file mode 100644 index 0000000000..82717769e6 --- /dev/null +++ b/reverse-bits/sadie100.ts @@ -0,0 +1,19 @@ +/** + n의 뒤의 자리에서부터 비트로 변환해서 result에 붙이고, result 비트를 앞으로 당기는 일을 32번 반복해서 뒤집어진 비트를 만든다 + + 시간복잡도 : O(1) - 비트 연산 + 공간복잡도 : O(1) + */ + +function reverseBits(n: number): number { + let result = 0 + + for (let i = 0; i < 32; i++) { + let bit = n & 1 + + result = (result << 1) | bit + + n = n>>> 1 + } + return result>>> 0 +} From 65a21a78c5c37a69dca5687706708f540a1fed7a Mon Sep 17 00:00:00 2001 From: sounmind Date: 2026年4月22日 08:35:51 -0400 Subject: [PATCH 388/526] feat: add blindCategories field to problem-categories.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 각 문제에 Blind Top 75 큐레이션 기준 카테고리(10개 중 하나 이상)를 `blindCategories` 필드로 추가한다. 출처: https://www.teamblind.com/post/new-year-gift-curated-list-of-top-75-leetcode-questions-to-save-your-time-oam1oreu 관련: DaleStudy/github#34 — GitHub App 의 "문제 풀이 현황" 표를 20+개 LC 카테고리에서 Blind 10개로 축소. Worker 가 이 필드를 직접 읽도록 하여 메타데이터를 원본 JSON 에 일원화. 10개 카테고리: Array, Binary, Dynamic Programming, Graph, Interval, Linked List, Matrix, String, Tree, Heap Co-Authored-By: Claude Opus 4.7 (1M context) Co-Authored-By: soobing <16860535+soobing@users.noreply.github.com> --- problem-categories.json | 226 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) diff --git a/problem-categories.json b/problem-categories.json index 9ecff41ddb..79c4c6456b 100644 --- a/problem-categories.json +++ b/problem-categories.json @@ -6,6 +6,9 @@ "Two Pointers", "Sorting" ], + "blindCategories": [ + "Array" + ], "intended_approach": "배열을 정렬한 뒤, 각 원소를 기준으로 투 포인터를 사용해 O(n2)으로 풀어야 합니다." }, "alien-dictionary": { @@ -18,6 +21,9 @@ "Graph Theory", "Topological Sort" ], + "blindCategories": [ + "Graph" + ], "intended_approach": "인접한 단어 쌍에서 문자 순서 관계를 엣지로 추출하고, 위상 정렬(BFS/DFS)로 순서를 결정합니다." }, "best-time-to-buy-and-sell-stock": { @@ -26,6 +32,9 @@ "Array", "Dynamic Programming" ], + "blindCategories": [ + "Array" + ], "intended_approach": "한 번의 순회로 최솟값을 추적하면서 현재 가격과의 차이를 계산합니다. O(n), O(1)." }, "binary-tree-level-order-traversal": { @@ -35,6 +44,9 @@ "Breadth-First Search", "Binary Tree" ], + "blindCategories": [ + "Tree" + ], "intended_approach": "큐를 사용한 BFS로 레벨별로 노드를 처리합니다." }, "binary-tree-maximum-path-sum": { @@ -45,6 +57,9 @@ "Depth-First Search", "Binary Tree" ], + "blindCategories": [ + "Tree" + ], "intended_approach": "DFS로 각 노드에서의 최대 gain을 계산하고, 좌우 자식을 포함한 경로 합을 전역 최댓값과 비교합니다." }, "climbing-stairs": { @@ -54,6 +69,9 @@ "Dynamic Programming", "Memoization" ], + "blindCategories": [ + "Dynamic Programming" + ], "intended_approach": "dp[i] = dp[i-1] + dp[i-2] 피보나치 점화식으로 풀어야 합니다." }, "clone-graph": { @@ -64,6 +82,9 @@ "Breadth-First Search", "Graph Theory" ], + "blindCategories": [ + "Graph" + ], "intended_approach": "HashMap으로 원본 노드와 복제 노드를 매핑하면서 BFS 또는 DFS로 순회합니다." }, "coin-change": { @@ -73,6 +94,9 @@ "Dynamic Programming", "Breadth-First Search" ], + "blindCategories": [ + "Dynamic Programming" + ], "intended_approach": "dp[i] = amount i를 만드는 최소 동전 수로 정의하고, Bottom-up DP로 풀어야 합니다." }, "combination-sum": { @@ -81,6 +105,9 @@ "Array", "Backtracking" ], + "blindCategories": [ + "Dynamic Programming" + ], "intended_approach": "백트래킹으로 후보 목록을 탐색하고, 중복 사용을 허용하기 위해 현재 인덱스부터 재귀합니다." }, "construct-binary-tree-from-preorder-and-inorder-traversal": { @@ -92,6 +119,9 @@ "Tree", "Binary Tree" ], + "blindCategories": [ + "Tree" + ], "intended_approach": "preorder의 첫 원소가 루트이고, inorder에서 루트 위치를 HashMap으로 O(1) 조회해 재귀적으로 트리를 구성합니다." }, "container-with-most-water": { @@ -101,6 +131,9 @@ "Two Pointers", "Greedy" ], + "blindCategories": [ + "Array" + ], "intended_approach": "양 끝에서 시작해 더 짧은 쪽 포인터를 이동하는 투 포인터로 O(n)에 풀어야 합니다." }, "contains-duplicate": { @@ -110,6 +143,9 @@ "Hash Table", "Sorting" ], + "blindCategories": [ + "Array" + ], "intended_approach": "HashSet에 원소를 추가하면서 이미 존재하는지 확인합니다. O(n), O(n)." }, "counting-bits": { @@ -118,6 +154,9 @@ "Dynamic Programming", "Bit Manipulation" ], + "blindCategories": [ + "Binary" + ], "intended_approach": "dp[i] = dp[i>> 1] + (i & 1) 점화식을 활용해 O(n)으로 풀어야 합니다." }, "course-schedule": { @@ -128,6 +167,9 @@ "Graph Theory", "Topological Sort" ], + "blindCategories": [ + "Graph" + ], "intended_approach": "방향 그래프에서 사이클 존재 여부를 DFS(색칠 기법) 또는 BFS 위상 정렬로 감지합니다." }, "decode-ways": { @@ -136,6 +178,9 @@ "String", "Dynamic Programming" ], + "blindCategories": [ + "Dynamic Programming" + ], "intended_approach": "dp[i] = s[:i]를 디코딩하는 경우의 수로 정의하고, 1자리/2자리 해석 가능 여부에 따라 Bottom-up DP로 풀어야 합니다." }, "design-add-and-search-words-data-structure": { @@ -146,6 +191,9 @@ "Design", "Trie" ], + "blindCategories": [ + "Tree" + ], "intended_approach": "Trie를 구현하고, '.' 와일드카드 처리를 위해 DFS로 모든 자식 노드를 탐색합니다." }, "encode-and-decode-strings": { @@ -155,6 +203,9 @@ "String", "Design" ], + "blindCategories": [ + "String" + ], "intended_approach": "각 문자열 앞에 길이를 접두사로 붙이는 방식(예: '4#word')으로 구분자 충돌 없이 인코딩/디코딩합니다." }, "find-median-from-data-stream": { @@ -166,6 +217,9 @@ "Heap (Priority Queue)", "Data Stream" ], + "blindCategories": [ + "Heap" + ], "intended_approach": "최대 힙(작은 절반)과 최소 힙(큰 절반)을 유지하며 중앙값을 O(log n)에 구합니다." }, "find-minimum-in-rotated-sorted-array": { @@ -174,6 +228,9 @@ "Array", "Binary Search" ], + "blindCategories": [ + "Array" + ], "intended_approach": "이진 탐색으로 정렬된 절반을 판별해 O(log n)에 최솟값을 찾아야 합니다." }, "graph-valid-tree": { @@ -184,6 +241,9 @@ "Union-Find", "Graph Theory" ], + "blindCategories": [ + "Graph" + ], "intended_approach": "Union-Find 또는 DFS로 사이클 여부를 확인하고, 모든 노드가 연결되어 있는지 검증합니다." }, "group-anagrams": { @@ -194,6 +254,9 @@ "String", "Sorting" ], + "blindCategories": [ + "String" + ], "intended_approach": "정렬된 문자열 또는 문자 카운팅 튜플을 HashMap의 키로 사용해 그룹핑합니다." }, "house-robber": { @@ -202,6 +265,9 @@ "Array", "Dynamic Programming" ], + "blindCategories": [ + "Dynamic Programming" + ], "intended_approach": "dp[i] = max(dp[i-1], dp[i-2] + nums[i]) 점화식으로 O(n), O(1) DP로 풀어야 합니다." }, "house-robber-ii": { @@ -210,6 +276,9 @@ "Array", "Dynamic Programming" ], + "blindCategories": [ + "Dynamic Programming" + ], "intended_approach": "원형 배열을 첫 집 포함/제외 두 경우로 분리해 house-robber를 두 번 실행합니다." }, "implement-trie-prefix-tree": { @@ -220,6 +289,9 @@ "Design", "Trie" ], + "blindCategories": [ + "Tree" + ], "intended_approach": "각 노드가 자식 맵과 is_end 플래그를 갖는 Trie 자료구조를 직접 구현합니다." }, "insert-interval": { @@ -227,6 +299,9 @@ "categories": [ "Array" ], + "blindCategories": [ + "Interval" + ], "intended_approach": "새 구간의 앞/겹치는/뒤 세 구역으로 나눠 선형 순회로 O(n)에 처리합니다." }, "invert-binary-tree": { @@ -237,6 +312,9 @@ "Breadth-First Search", "Binary Tree" ], + "blindCategories": [ + "Tree" + ], "intended_approach": "DFS 재귀 또는 BFS로 각 노드의 좌우 자식을 교환합니다." }, "jump-game": { @@ -246,6 +324,9 @@ "Dynamic Programming", "Greedy" ], + "blindCategories": [ + "Dynamic Programming" + ], "intended_approach": "현재까지 도달 가능한 최대 인덱스를 추적하는 Greedy로 O(n)에 풀어야 합니다." }, "kth-smallest-element-in-a-bst": { @@ -256,6 +337,9 @@ "Binary Search Tree", "Binary Tree" ], + "blindCategories": [ + "Tree" + ], "intended_approach": "BST의 중위 순회(In-order traversal)는 오름차순이므로 k번째 원소가 정답입니다." }, "linked-list-cycle": { @@ -265,6 +349,9 @@ "Linked List", "Two Pointers" ], + "blindCategories": [ + "Linked List" + ], "intended_approach": "플로이드 사이클 감지(빠른/느린 포인터)로 O(n), O(1)에 풀어야 합니다." }, "longest-common-subsequence": { @@ -273,6 +360,9 @@ "String", "Dynamic Programming" ], + "blindCategories": [ + "Dynamic Programming" + ], "intended_approach": "2D DP 테이블 dp[i][j] = text1[:i]와 text2[:j]의 LCS 길이로 풀어야 합니다." }, "longest-consecutive-sequence": { @@ -282,6 +372,9 @@ "Hash Table", "Union-Find" ], + "blindCategories": [ + "Graph" + ], "intended_approach": "HashSet에 모든 수를 넣고, 시퀀스 시작점(num-1이 없는 수)에서만 연속 길이를 셉니다. O(n)." }, "longest-increasing-subsequence": { @@ -291,6 +384,9 @@ "Binary Search", "Dynamic Programming" ], + "blindCategories": [ + "Dynamic Programming" + ], "intended_approach": "O(n log n)은 이진 탐색으로 patience sorting, O(n2)은 기본 DP로 풀어야 합니다." }, "longest-palindromic-substring": { @@ -300,6 +396,9 @@ "String", "Dynamic Programming" ], + "blindCategories": [ + "String" + ], "intended_approach": "각 문자(및 문자 사이)를 중심으로 확장하는 중심 확장법으로 O(n2), O(1)에 풀어야 합니다." }, "longest-repeating-character-replacement": { @@ -309,6 +408,9 @@ "String", "Sliding Window" ], + "blindCategories": [ + "String" + ], "intended_approach": "슬라이딩 윈도우로 윈도우 내 최다 빈도 문자를 추적하고, (window 크기 - 최다 빈도) ≤ k 조건을 유지합니다." }, "longest-substring-without-repeating-characters": { @@ -318,6 +420,9 @@ "String", "Sliding Window" ], + "blindCategories": [ + "String" + ], "intended_approach": "슬라이딩 윈도우 + HashMap으로 중복 문자 발생 시 왼쪽 포인터를 이동합니다. O(n)." }, "lowest-common-ancestor-of-a-binary-search-tree": { @@ -328,6 +433,9 @@ "Binary Search Tree", "Binary Tree" ], + "blindCategories": [ + "Tree" + ], "intended_approach": "BST 속성(p, q가 모두 왼쪽/오른쪽이면 내려가고, 분기되면 현재 노드가 LCA)을 활용해 재귀합니다." }, "maximum-depth-of-binary-tree": { @@ -338,6 +446,9 @@ "Breadth-First Search", "Binary Tree" ], + "blindCategories": [ + "Tree" + ], "intended_approach": "DFS 재귀로 max(left, right) + 1을 반환하거나 BFS로 레벨을 셉니다." }, "maximum-product-subarray": { @@ -346,6 +457,9 @@ "Array", "Dynamic Programming" ], + "blindCategories": [ + "Array" + ], "intended_approach": "음수 곱셈을 고려해 현재 최댓값과 최솟값을 동시에 추적하는 DP로 풀어야 합니다." }, "maximum-subarray": { @@ -355,6 +469,9 @@ "Divide and Conquer", "Dynamic Programming" ], + "blindCategories": [ + "Array" + ], "intended_approach": "카데인 알고리즘: 현재 합이 음수가 되면 초기화하는 방식으로 O(n), O(1)에 풀어야 합니다." }, "meeting-rooms": { @@ -363,6 +480,9 @@ "Array", "Sorting" ], + "blindCategories": [ + "Interval" + ], "intended_approach": "시작 시간 기준으로 정렬 후, 인접한 회의의 겹침 여부를 확인합니다." }, "meeting-rooms-ii": { @@ -375,6 +495,9 @@ "Heap (Priority Queue)", "Prefix Sum" ], + "blindCategories": [ + "Interval" + ], "intended_approach": "최소 힙으로 진행 중인 회의의 종료 시간을 관리하고, 새 회의가 시작될 때 가장 빨리 끝나는 회의와 비교합니다." }, "merge-intervals": { @@ -383,6 +506,9 @@ "Array", "Sorting" ], + "blindCategories": [ + "Interval" + ], "intended_approach": "시작 시간으로 정렬 후 선형 순회하며 이전 구간과 겹치면 병합합니다." }, "merge-k-sorted-lists": { @@ -393,6 +519,10 @@ "Heap (Priority Queue)", "Merge Sort" ], + "blindCategories": [ + "Linked List", + "Heap" + ], "intended_approach": "최소 힙(Priority Queue)에 각 리스트의 헤드를 넣고 순서대로 추출합니다. O(n log k)." }, "merge-two-sorted-lists": { @@ -401,6 +531,9 @@ "Linked List", "Recursion" ], + "blindCategories": [ + "Linked List" + ], "intended_approach": "두 포인터로 작은 쪽을 연결하는 반복 또는 재귀로 풀어야 합니다." }, "minimum-window-substring": { @@ -410,6 +543,9 @@ "String", "Sliding Window" ], + "blindCategories": [ + "String" + ], "intended_approach": "슬라이딩 윈도우 + 문자 카운팅 HashMap으로, 조건 충족 시 윈도우를 줄이며 최솟값을 갱신합니다." }, "missing-number": { @@ -422,6 +558,9 @@ "Bit Manipulation", "Sorting" ], + "blindCategories": [ + "Binary" + ], "intended_approach": "XOR(모든 수 XOR 인덱스) 또는 가우스 공식(n*(n+1)/2 - 합)으로 O(n), O(1)에 풀어야 합니다." }, "non-overlapping-intervals": { @@ -432,6 +571,9 @@ "Greedy", "Sorting" ], + "blindCategories": [ + "Interval" + ], "intended_approach": "종료 시간 기준으로 정렬 후, Greedy로 겹치는 구간 중 종료 시간이 긴 쪽을 제거합니다." }, "number-of-1-bits": { @@ -440,6 +582,9 @@ "Divide and Conquer", "Bit Manipulation" ], + "blindCategories": [ + "Binary" + ], "intended_approach": "n & (n-1)로 가장 낮은 1 비트를 제거하는 방식으로 set bit 수를 셉니다." }, "number-of-connected-components-in-an-undirected-graph": { @@ -450,6 +595,9 @@ "Union-Find", "Graph Theory" ], + "blindCategories": [ + "Graph" + ], "intended_approach": "Union-Find 또는 DFS/BFS로 연결 컴포넌트 수를 셉니다." }, "number-of-islands": { @@ -461,6 +609,9 @@ "Union-Find", "Matrix" ], + "blindCategories": [ + "Graph" + ], "intended_approach": "육지 셀을 발견하면 DFS/BFS로 연결된 육지를 모두 방문 처리하고 카운트합니다." }, "pacific-atlantic-water-flow": { @@ -471,6 +622,9 @@ "Breadth-First Search", "Matrix" ], + "blindCategories": [ + "Graph" + ], "intended_approach": "역방향으로 태평양/대서양 경계에서 DFS/BFS를 시작해 도달 가능한 셀의 교집합을 구합니다." }, "palindromic-substrings": { @@ -480,6 +634,9 @@ "String", "Dynamic Programming" ], + "blindCategories": [ + "String" + ], "intended_approach": "각 문자와 문자 사이를 중심으로 확장하는 중심 확장법으로 O(n2)에 팰린드롬 수를 셉니다." }, "product-of-array-except-self": { @@ -488,6 +645,9 @@ "Array", "Prefix Sum" ], + "blindCategories": [ + "Array" + ], "intended_approach": "나눗셈 없이 prefix 곱 배열과 suffix 곱을 활용해 O(n), O(1) 추가 공간으로 풀어야 합니다." }, "remove-nth-node-from-end-of-list": { @@ -496,6 +656,9 @@ "Linked List", "Two Pointers" ], + "blindCategories": [ + "Linked List" + ], "intended_approach": "빠른 포인터를 n+1 앞서 출발시키는 투 포인터로 한 번의 순회에 처리합니다." }, "reorder-list": { @@ -506,6 +669,9 @@ "Stack", "Recursion" ], + "blindCategories": [ + "Linked List" + ], "intended_approach": "중간 찾기(느린/빠른 포인터) → 후반 역전 → 교차 병합 세 단계로 풀어야 합니다." }, "reverse-bits": { @@ -514,6 +680,9 @@ "Divide and Conquer", "Bit Manipulation" ], + "blindCategories": [ + "Binary" + ], "intended_approach": "비트를 하나씩 추출해 결과에 왼쪽으로 추가하는 비트 시프트 연산으로 풀어야 합니다." }, "reverse-linked-list": { @@ -522,6 +691,9 @@ "Linked List", "Recursion" ], + "blindCategories": [ + "Linked List" + ], "intended_approach": "prev/curr 포인터로 방향을 뒤집는 반복(O(1) 공간) 또는 재귀로 풀어야 합니다." }, "rotate-image": { @@ -531,6 +703,9 @@ "Math", "Matrix" ], + "blindCategories": [ + "Matrix" + ], "intended_approach": "전치(Transpose) 후 각 행을 좌우 반전하면 O(1) 추가 공간으로 90도 회전됩니다." }, "same-tree": { @@ -541,6 +716,9 @@ "Breadth-First Search", "Binary Tree" ], + "blindCategories": [ + "Tree" + ], "intended_approach": "두 트리를 동시에 DFS 재귀로 순회하며 값과 구조를 비교합니다." }, "search-in-rotated-sorted-array": { @@ -549,6 +727,9 @@ "Array", "Binary Search" ], + "blindCategories": [ + "Array" + ], "intended_approach": "이진 탐색에서 mid를 기준으로 좌/우 절반 중 정렬된 쪽을 판별해 탐색 범위를 줄입니다." }, "serialize-and-deserialize-binary-tree": { @@ -561,6 +742,9 @@ "Design", "Binary Tree" ], + "blindCategories": [ + "Tree" + ], "intended_approach": "BFS(레벨 순서) 또는 DFS 전위 순회로 직렬화하고, null 마커로 구조를 복원합니다." }, "set-matrix-zeroes": { @@ -570,6 +754,9 @@ "Hash Table", "Matrix" ], + "blindCategories": [ + "Matrix" + ], "intended_approach": "첫 행/열을 마커 행으로 활용해 O(1) 추가 공간으로 풀어야 합니다." }, "spiral-matrix": { @@ -579,6 +766,9 @@ "Matrix", "Simulation" ], + "blindCategories": [ + "Matrix" + ], "intended_approach": "상/하/좌/우 경계를 좁혀가며 시뮬레이션으로 순회합니다." }, "subtree-of-another-tree": { @@ -590,6 +780,9 @@ "Binary Tree", "Hash Function" ], + "blindCategories": [ + "Tree" + ], "intended_approach": "각 노드에서 same-tree 판별 함수를 호출하는 DFS로 풀어야 합니다." }, "sum-of-two-integers": { @@ -598,6 +791,9 @@ "Math", "Bit Manipulation" ], + "blindCategories": [ + "Binary" + ], "intended_approach": "XOR로 합(올림 없는 덧셈), AND 후 왼쪽 시프트로 올림을 계산하고 올림이 0이 될 때까지 반복합니다." }, "top-k-frequent-elements": { @@ -612,6 +808,9 @@ "Counting", "Quickselect" ], + "blindCategories": [ + "Heap" + ], "intended_approach": "버킷 정렬(빈도를 인덱스로 사용)로 O(n)에 풀거나, 최소 힙으로 O(n log k)에 풀어야 합니다." }, "two-sum": { @@ -620,6 +819,9 @@ "Array", "Hash Table" ], + "blindCategories": [ + "Array" + ], "intended_approach": "HashMap으로 target - nums[i]를 조회하며 한 번의 순회로 O(n)에 풀어야 합니다." }, "unique-paths": { @@ -629,6 +831,9 @@ "Dynamic Programming", "Combinatorics" ], + "blindCategories": [ + "Dynamic Programming" + ], "intended_approach": "dp[i][j] = dp[i-1][j] + dp[i][j-1]로 2D DP, 또는 조합 C(m+n-2, m-1)으로 수학적으로 풀 수 있습니다." }, "valid-anagram": { @@ -638,6 +843,9 @@ "String", "Sorting" ], + "blindCategories": [ + "String" + ], "intended_approach": "문자 카운팅 배열(26) 또는 HashMap으로 두 문자열의 빈도를 비교합니다." }, "valid-palindrome": { @@ -646,6 +854,9 @@ "Two Pointers", "String" ], + "blindCategories": [ + "String" + ], "intended_approach": "양 끝에서 시작하는 투 포인터로 영숫자만 비교합니다. O(n), O(1)." }, "valid-parentheses": { @@ -654,6 +865,9 @@ "String", "Stack" ], + "blindCategories": [ + "String" + ], "intended_approach": "스택을 사용해 여는 괄호를 push하고, 닫는 괄호가 나오면 스택 top과 대응 여부를 확인합니다." }, "validate-binary-search-tree": { @@ -664,6 +878,9 @@ "Binary Search Tree", "Binary Tree" ], + "blindCategories": [ + "Tree" + ], "intended_approach": "DFS로 각 노드에 유효 범위(min, max)를 전달하며 BST 조건을 검증합니다." }, "word-break": { @@ -676,6 +893,9 @@ "Trie", "Memoization" ], + "blindCategories": [ + "Dynamic Programming" + ], "intended_approach": "dp[i] = s[:i]가 wordDict로 분리 가능한지 여부로 정의하고, Bottom-up DP로 O(n2)에 풀어야 합니다." }, "word-search": { @@ -687,6 +907,9 @@ "Depth-First Search", "Matrix" ], + "blindCategories": [ + "Matrix" + ], "intended_approach": "각 셀에서 DFS 백트래킹으로 탐색하고, 방문한 셀을 임시 마킹해 중복 방문을 방지합니다." }, "word-search-ii": { @@ -698,6 +921,9 @@ "Trie", "Matrix" ], + "blindCategories": [ + "Tree" + ], "intended_approach": "단어 목록으로 Trie를 구성하고, 그리드를 DFS 백트래킹으로 탐색하며 Trie 노드와 함께 매칭합니다." } } From a44e9d7bc84fe0b9bdee5f1a25a6e53c987b9b69 Mon Sep 17 00:00:00 2001 From: Dale Seo <5466341+daleseo@users.noreply.github.com> Date: 2026年4月22日 21:06:57 -0400 Subject: [PATCH 389/526] longest-repeating-character-replacement --- .../DaleSeo.rs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 longest-repeating-character-replacement/DaleSeo.rs diff --git a/longest-repeating-character-replacement/DaleSeo.rs b/longest-repeating-character-replacement/DaleSeo.rs new file mode 100644 index 0000000000..5f4584fc41 --- /dev/null +++ b/longest-repeating-character-replacement/DaleSeo.rs @@ -0,0 +1,27 @@ +// TC: O(n), where n is s.len() +// SC: O(1), fixed 26-slot frequency array +impl Solution { + pub fn character_replacement(s: String, k: i32) -> i32 { + let bytes = s.as_bytes(); + let mut counts = [0i32; 26]; + let mut start = 0usize; + let mut max_freq = 0i32; + let mut result = 0i32; + + for end in 0..bytes.len() { + let idx = (bytes[end] - b'A') as usize; + counts[idx] += 1; + max_freq = max_freq.max(counts[idx]); + + while (end - start + 1) as i32 - max_freq> k { + let left_idx = (bytes[start] - b'A') as usize; + counts[left_idx] -= 1; + start += 1; + } + + result = result.max((end - start + 1) as i32); + } + + result + } +} From 2b46133d6721344203afd420995df3963f182cbd Mon Sep 17 00:00:00 2001 From: Ted Date: 2026年4月22日 22:13:02 -0400 Subject: [PATCH 390/526] add reverse bits --- reverse-bits/tedkimdev.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 reverse-bits/tedkimdev.rs diff --git a/reverse-bits/tedkimdev.rs b/reverse-bits/tedkimdev.rs new file mode 100644 index 0000000000..cfc8574f34 --- /dev/null +++ b/reverse-bits/tedkimdev.rs @@ -0,0 +1,12 @@ +// TC: O(1) +// SC: O(1) +impl Solution { + pub fn reverse_bits(n: u32) -> u32 { + let mut res: u32 = 0; + for i in 0..32 { + let bit = (n>> i) & 1; + res += bit << (31 - i); + } + res + } +} From 498939dca0959a55f303da75ca12afed7eaff54a Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年4月23日 12:11:38 +0900 Subject: [PATCH 391/526] add: reverseBits solution --- reverse-bits/Cyjin-jani.js | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 reverse-bits/Cyjin-jani.js diff --git a/reverse-bits/Cyjin-jani.js b/reverse-bits/Cyjin-jani.js new file mode 100644 index 0000000000..b0c393e406 --- /dev/null +++ b/reverse-bits/Cyjin-jani.js @@ -0,0 +1,7 @@ +// tc: O(1) -> 32비트로 고정되어있어 1로 봄.. +// sc: O(1) +const reverseBits = function (n) { + const binaryStr = n.toString(2).padStart(32, '0'); + const answer = binaryStr.split('').reverse().join(''); + return parseInt(answer, 2); +}; From 4b29af85b4548deb7f0156b8835ef95a4acb77fa Mon Sep 17 00:00:00 2001 From: Se Hee Kim <82367039+sadie100@users.noreply.github.com> Date: 2026年4月23日 12:48:44 +0900 Subject: [PATCH 392/526] Update reverse-bits/sadie100.ts Co-authored-by: Dale Seo <5466341+daleseo@users.noreply.github.com> --- reverse-bits/sadie100.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reverse-bits/sadie100.ts b/reverse-bits/sadie100.ts index 82717769e6..f079c8c382 100644 --- a/reverse-bits/sadie100.ts +++ b/reverse-bits/sadie100.ts @@ -9,7 +9,7 @@ function reverseBits(n: number): number { let result = 0 for (let i = 0; i < 32; i++) { - let bit = n & 1 + const bit = n & 1 result = (result << 1) | bit From ecb467957e220aab9ddb21d6f8ec4488968f2e03 Mon Sep 17 00:00:00 2001 From: jamiebase <100mgml@gmail.com> Date: 2026年4月23日 18:24:53 +0900 Subject: [PATCH 393/526] add solution for character replacement problem --- .../jamiebase.py | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 longest-repeating-character-replacement/jamiebase.py diff --git a/longest-repeating-character-replacement/jamiebase.py b/longest-repeating-character-replacement/jamiebase.py new file mode 100644 index 0000000000..631eb6069c --- /dev/null +++ b/longest-repeating-character-replacement/jamiebase.py @@ -0,0 +1,34 @@ +""" +# Approach +1. 구간에서 제일 많은 문자 찾는다 +2. 나머지를 바꾼다 +3. 바꾸는 개수가 k 이하인지 본다 +4. 가능하면 구간 길이를 키운다 + +# Complexity +문자열 s에서 서로 다른 글자의 종류 U, s의 길이 N +- Time complexity: O(N) +- Space complexity: O(U) => 영어 대문자만 나오므로 사실상 O(1) +""" + +from collections import defaultdict + + +class Solution: + def characterReplacement(self, s: str, k: int) -> int: + count = defaultdict(int) + left = 0 + max_freq = 0 + answer = 0 + + for right in range(len(s)): + count[s[right]] += 1 + max_freq = max(max_freq, count[s[right]]) + + while (right - left + 1) - max_freq> k: + count[s[left]] -= 1 + left += 1 + + answer = max(answer, right - left + 1) + + return answer From f54ec27095695c83808d235a5c0c7d9c06e02fb5 Mon Sep 17 00:00:00 2001 From: jamiebase <100mgml@gmail.com> Date: 2026年4月23日 18:30:24 +0900 Subject: [PATCH 394/526] add solution for reversing bits with two approaches --- reverse-bits/jamiebase.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 reverse-bits/jamiebase.py diff --git a/reverse-bits/jamiebase.py b/reverse-bits/jamiebase.py new file mode 100644 index 0000000000..deb72199ea --- /dev/null +++ b/reverse-bits/jamiebase.py @@ -0,0 +1,29 @@ +""" +# Approach +1) 정수를 이진 문자열로 변환한 뒤, +32비트로 맞추고 뒤집어서 다시 정수로 변환한다. + +2) n에서 비트를 하나씩 꺼내서 res에 역순으로 붙인다 + +# Complexity +- Time complexity: O(1) +- Space complexity: O(1) +""" + + +# 1 +class Solution: + def reverseBits(self, n: int) -> int: + b_num = format(n, "b") + b_reversed = b_num.zfill(32)[::-1] + return int(b_reversed, 2) + + +# 2 +class Solution: + def reverseBits(self, n: int) -> int: + res = 0 + for _ in range(32): + res = (res << 1) | (n & 1) + n>>= 1 + return res From 2517fa188482327c4e1b7569b161d4264ef19eee Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月23日 20:30:43 +0900 Subject: [PATCH 395/526] longest-common-subsequence solution --- longest-common-subsequence/hyeri0903.java | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 longest-common-subsequence/hyeri0903.java diff --git a/longest-common-subsequence/hyeri0903.java b/longest-common-subsequence/hyeri0903.java new file mode 100644 index 0000000000..cced12a890 --- /dev/null +++ b/longest-common-subsequence/hyeri0903.java @@ -0,0 +1,28 @@ +class Solution { + public int longestCommonSubsequence(String text1, String text2) { + /** + 1.문제: 가장 긴 common subsequence length return, 없으면 0 return + 2.constraints + - length min = 1, max = 1000 + - text1, text2 모두 lowercase로 구성 + 3.풀이 + - dp[i][j] = text1의 앞 i개, text2의 앞 j개를 비교했을 때 LCS 길이 + - 문자가 같으면: dp[i][j] = dp[i-1][j-1] + 1 + - 문자가 다르면: dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + */ + int t1Size = text1.length(); //row + int t2Size = text2.length(); //col + int[][] dp = new int[t1Size + 1][t2Size + 1]; + + for(int i = 1; i <= t1Size; i++) { + for(int j = 1; j <= t2Size; j++) { + if(text1.charAt(i-1) == text2.charAt(j-1)) { + dp[i][j] = dp[i-1][j-1] + 1; + } else { + dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]); + } + } + } + return dp[t1Size][t2Size]; + } +} From 5a3ce87ccb52a4b5799ad56e724f2609b9d9c71d Mon Sep 17 00:00:00 2001 From: jla670 Date: 2026年4月23日 10:52:06 -0700 Subject: [PATCH 396/526] longest repeating character replacement solution --- .../jylee2033.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 longest-repeating-character-replacement/jylee2033.py diff --git a/longest-repeating-character-replacement/jylee2033.py b/longest-repeating-character-replacement/jylee2033.py new file mode 100644 index 0000000000..6f9f3f6f15 --- /dev/null +++ b/longest-repeating-character-replacement/jylee2033.py @@ -0,0 +1,27 @@ +class Solution: + def characterReplacement(self, s: str, k: int) -> int: + # "AABABBA", 1 + # l = 0 + # r = 4 + # max_freq = 0 + # max_len = 4 + # {"A":1, "B":2} + + l = 0 + max_len = 0 + max_freq = 0 + seen = {} + + for r, char in enumerate(s): + seen[char] = seen.get(char, 0) + 1 + max_freq = max(max_freq, seen[char]) + + while (r - l + 1) - max_freq> k: + seen[s[l]] -= 1 + l += 1 + + max_len = max(max_len, r - l + 1) + return max_len + +# Time Complexity: O(n) +# Space Complexity: O(1) From f3219760f06956af0527ad2d17109a15e46f599b Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月19日 23:21:29 +0900 Subject: [PATCH 397/526] [7th batch] week 7 - set matrix zero --- set-matrix-zeroes/liza0525.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 set-matrix-zeroes/liza0525.py diff --git a/set-matrix-zeroes/liza0525.py b/set-matrix-zeroes/liza0525.py new file mode 100644 index 0000000000..b2651c8789 --- /dev/null +++ b/set-matrix-zeroes/liza0525.py @@ -0,0 +1,33 @@ +# 7기 풀이 +# 시간 복잡도: O(m * n) +# - matrix 크기 만큼 시간 복잡도가 듦 +# 공간 복잡도: O(m + n) +# - 가로, 세로에서 각각 대상 인덱스를 저장 +class Solution: + def setZeroes(self, matrix: List[List[int]]) -> None: + """ + Do not return anything, modify matrix in-place instead. + """ + len_i = len(matrix) + len_j = len(matrix[0]) + + # 0이 발견된 행/열 인덱스를 각각 저장하는 set + target_i_set, target_j_set = set(), set() + + for i in range(len_i): + for j in range(len_j): + if matrix[i][j] != 0: + continue + + # matrix[i][j]가 0인 경우에는 인덱스를 저장한다. + target_i_set.add(i) + target_j_set.add(j) + + + for i in range(len_i): + for j in range(len_j): + if matrix[i][j] == 0: + continue + if i in target_i_set or j in target_j_set: + # i, j 인덱스가 set에 있는 경우에는 0으로 변경한다. + matrix[i][j] = 0 From 9be1187368681bfde6556c9a36de46c4afda681d Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月24日 14:11:46 +0900 Subject: [PATCH 398/526] [7th batch] week 8 - reverse bits --- reverse-bits/liza0525.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 reverse-bits/liza0525.py diff --git a/reverse-bits/liza0525.py b/reverse-bits/liza0525.py new file mode 100644 index 0000000000..fe2deaf3a0 --- /dev/null +++ b/reverse-bits/liza0525.py @@ -0,0 +1,25 @@ +# 7기 풀이 +# 시간 복잡도: O(1) +# - 해당 문제는 조건 자체가 32자릿수로 되어 있어 최대 32번까지만 계산 +# 공간 복잡도: O(1) +# - result, idx와 같은 변수만 사용 +class Solution: + def reverseBits(self, n: int) -> int: + result = 0 + idx = 0 # 자릿수 계산을 위한 앵커 + + while n> 0: # n이 0이 되기 전까지 돌린다. + remainder = n % 2 # 수를 2로 나눴을 때의 나머지가 해당 자리수에서의 2진수 값 (0 or 1) + quotient = n // 2 # 몫은 다음 루프의 피젯수로 + + if remainder: + # 나머지가 있는 경우에는 해당 2진수 자리수에 값이 있다. + # reversed한 값을 계산해야 하기 때문에 32 - idx - 1의 자릿수로 변환 + # (문제 조건 상 32자릿수가 기준) + # 변환한 후 result에 값을 더해준다. + result += 2 ** (32 - idx - 1) + + n = quotient + idx += 1 # 자릿수를 하나 올린다 + + return result From e793bf4760b6b4db889028e6af1fb06a7cc99067 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月24日 14:46:17 +0900 Subject: [PATCH 399/526] [7th batch] week 8 - clone graph --- clone-graph/liza0525.py | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 clone-graph/liza0525.py diff --git a/clone-graph/liza0525.py b/clone-graph/liza0525.py new file mode 100644 index 0000000000..a57cafa368 --- /dev/null +++ b/clone-graph/liza0525.py @@ -0,0 +1,46 @@ +from typing import Optional + +# 7기 풀이 +# 시간 복잡도: O(V + E) +# - 모든 노드의 수와 모든 엣지의 수만큼 탐방하므로 그만큼의 시간이 걸림(V: 노드 수, E: 엣지 수) +# 공간 복잡도: O(V) +# - memo에 모든 노드를 복사해서 추가(V: 노드의 갯수) +class Solution: + def cloneGraph(self, node: Optional['Node']) -> Optional['Node']: + memo = {} + + def copy_graph(node): + if not node: + # 더이상 복사할 노드가 없다면 None을 return + return None + + if node.val in memo: + # node의 값이 memo에 있다면 memo에 있는 값을 return + return memo[node.val] + + # Node의 복사를 위해 새 노드 생성 및 node.val 값을 초기값으로 입력 + res_node = Node(node.val) + memo[node.val] = res_node # memo에 새로만든 객체를 value로 하여 저장(key는 node.val 값으로) + + # neighbors도 복사, 이 때 copy_graph를 재귀로 호출하여 모든 neighbors들을 복사하도록 한다. + res_node.neighbors = [ + copy_graph(neighbor) for neighbor in node.neighbors + ] + + # res_node를 return + return res_node + + return copy_graph(node)# 다음과 같이 파이썬의 built-in 함수인 deepcopy를 사용하면 바로 문제가 풀리기도 했다. + + +# 정리 목적 +# 다음과 같이 파이썬의 built-in 함수인 deepcopy를 사용하면 바로 문제가 풀리기도 했다. +# 실제 deepcopy 구현이 memo를 이용하며 +# copier의 deepcopy를 호출하여 재귀와 비슷하게 구현했다는 것을 확인할 수 있었다 +# ref: https://github.com/python/cpython/blob/main/Lib/copy.py +from copy import deepcopy + + +class Solution: + def cloneGraph(self, node: Optional['Node']) -> Optional['Node']: + return deepcopy(node) From bbc338e6ec5e603e710ff67d33beeb08975f5321 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月24日 15:01:44 +0900 Subject: [PATCH 400/526] [7th batch] week 8 - palindrome substrings --- palindromic-substrings/liza0525.py | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 palindromic-substrings/liza0525.py diff --git a/palindromic-substrings/liza0525.py b/palindromic-substrings/liza0525.py new file mode 100644 index 0000000000..ff0f6499dd --- /dev/null +++ b/palindromic-substrings/liza0525.py @@ -0,0 +1,32 @@ +# 7기 풀이 +# 시간 복잡도: O(n ** 2) +# - for문으로 문자의 중심을 탐색 * while문으로 양쪽으로 뻗어나가며 문자열 탐색 +# 공간 복잡도: O(1) +# - 변수 몇 개만 사용 +class Solution: + # 해당 문제의 기본 아이디어: 중심 확장법을 이용하여 펠린드롬 찾기 + def countSubstrings(self, s: str) -> int: + res = 0 + + # 펠린드롬의 길이가 짝수일 수도 홀수일 수도 있기 때문에 + # 2 * len(s)를 돌고 나눈 수 몫을 이용해서 중심을 먼저 잡는다 + for idx in range(2 * len(s) - 1): + # 펠린드롬 길이가 짝수일 때는 left와 right의 값이 1 차이나지만 + # 홀수일 때는 left == right 이다. + left = idx // 2 + right = (idx + 1) // 2 + delta = 0 + + while ( + 0 <= left - delta # 왼쪽으로 확장했을 때의 index와 + and right + delta < len(s) # 오른쪽으로 확장했을 때의 index가 모두 s길이 범위 내에 있어야 함 + ): + if s[left - delta] == s[right + delta]: # 두 개가 같은 경우에는 펠린드롬 + res += 1 # 결과 값을 하나 추가하고 + delta += 1 # 확장을 위한 값을 1 올려준다 + else: + # 확장했을 때의 양 쪽 문자가 다른 경우에는 펠린드롬이 아니므로 break하고 + # 다음 루프에서 새로운 중심을 잡은 후 다시 펠린드롬을 찾는다. + break + + return res From 775b2afd15bd5c4278c430bf8d7e0d3b315c58ff Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月24日 15:20:08 +0900 Subject: [PATCH 401/526] [7th batch] week 8 - longest repeating characer replacement --- .../liza0525.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 longest-repeating-character-replacement/liza0525.py diff --git a/longest-repeating-character-replacement/liza0525.py b/longest-repeating-character-replacement/liza0525.py new file mode 100644 index 0000000000..0ac4726172 --- /dev/null +++ b/longest-repeating-character-replacement/liza0525.py @@ -0,0 +1,32 @@ +from collections import defaultdict + + +# 7기 풀이 +# 시간 복잡도: O(n) +# - right는 매 루프마다 전진하고 left도 최대 n번 전진하므로 합쳐서 O(n) +# 공간 복잡도: O(1) +# - s에 있는 문자들의 개수만큼 공간 복잡도가 늘어나겠지만 모두 대문자인 알파벳만이 key로 들어오므로 최대 26개 +class Solution: + # 기본 아이디어: 슬라이딩 윈도우를 사용하면서 + # 윈도우 내에 가장 많이 있는 문자의 개수와 k값을 더한 값이 윈도우를 초과하는지 아닌지를 확인 + def characterReplacement(self, s: str, k: int) -> int: + left = 0 # 윈도우 왼쪽 인덱스 값 + max_len = 0 # 문제의 답(변경 시 가장 긴 substring 길이) + char_dict = defaultdict(int) # 윈도우 내의 각 문자들 개수를 확인하기 위한 dict + max_char_cnt = 0 # 윈도우 내에 가장 많은 문자의 개수 그 자체(dict의 value() 메서드를 매번 호출하지 않게 하기 위함) + + for right in range(len(s)): # 윈도우 오른쪽 인덱스 값 + char_dict[s[right]] += 1 # 오른쪽 인덱스에 해당하는 문자(예: A)에 대한 개수를 하나 올림 + max_char_cnt = max(max_char_cnt, char_dict[s[right]]) # 현재 윈도우에서 가장 많은 문자의 개수를 업데이트 + + if max_char_cnt + k>= right - left + 1: + # 가장 많은 문자열 사이에 있는 다른 문자들의 개수가 k보다 작으면 변경 가능 + # -> 윈도우 내에서 가장 긴 repeating substring을 만들 수 있음 + max_len = max(max_len, right - left + 1) + else: + # 만들 수 없는 경우에는 기존 left의 문자를 char_dict로부터 하나 줄이고 + # left를 하나 옮긴다(새로운 윈도우를 만든다는 의미) + char_dict[s[left]] -= 1 + left += 1 + + return max_len From c8b2d2a508a5bf25e704aed971a0c423f81da065 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年4月24日 15:31:16 +0900 Subject: [PATCH 402/526] [7th batch] week 8 - longest common subsequence --- longest-common-subsequence/liza0525.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 longest-common-subsequence/liza0525.py diff --git a/longest-common-subsequence/liza0525.py b/longest-common-subsequence/liza0525.py new file mode 100644 index 0000000000..0596953233 --- /dev/null +++ b/longest-common-subsequence/liza0525.py @@ -0,0 +1,26 @@ +# 7기 풀이 +# 시간 복잡도: O(n * m) +# - text1의 길이 n과 text2의 길이 m만큼 순회하며 계산함 +# 공간 복잡도: O(n * m) +# - text1의 길이 n과 text2의 길이 m만큼의 2차 배열을 만들어 DP 계산을 하기 때문 +class Solution: + def longestCommonSubsequence(self, text1: str, text2: str) -> int: + dp = [ + [0 for _ in range(len(text2) + 1)] + for _ in range(len(text1) + 1) + ] + + for i in range(1, len(text1) + 1): + for j in range(1, len(text2) + 1): + if text1[i - 1] == text2[j - 1]: + # text1의 i번째 문자와 text2의 j번째 문자가 같다면 + # 이 문자는 공통 subsequence에 포함될 수 있으므로 + # 두 문자를 제외한 나머지(dp[i-1][j-1])에 1을 더한 값이 현재의 LCS 길이가 된다 + dp[i][j] = dp[i - 1][j - 1] + 1 + else: + # 같지 않다면 둘 중 하나를 제외했을 때의 LCS 중 더 큰 값을 가져온다 + # dp[i][j-1]: text2의 j번째 문자를 제외한 경우 + # dp[i-1][j]: text1의 i번째 문자를 제외한 경우 + dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]) + + return dp[-1][-1] From f40ebfb53ed19e516303e0ea581adb79301feac2 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月24日 21:33:15 +0900 Subject: [PATCH 403/526] palindromic-substrings solutions --- palindromic-substrings/hyeri0903.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 palindromic-substrings/hyeri0903.java diff --git a/palindromic-substrings/hyeri0903.java b/palindromic-substrings/hyeri0903.java new file mode 100644 index 0000000000..e69de29bb2 From 8c9defe98ae3b5e3098ec96265d04fd29b268b3a Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月24日 21:57:06 +0900 Subject: [PATCH 404/526] longest-repeating-character-replacement solution --- .../hyeri0903.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 longest-repeating-character-replacement/hyeri0903.java diff --git a/longest-repeating-character-replacement/hyeri0903.java b/longest-repeating-character-replacement/hyeri0903.java new file mode 100644 index 0000000000..d85906bcfc --- /dev/null +++ b/longest-repeating-character-replacement/hyeri0903.java @@ -0,0 +1,39 @@ +class Solution { + public int characterReplacement(String s, int k) { + /** + 1.problem: k번 특정 문자를 골라서 바꿀 수 있다. 이때 same letter 로 이루어진 가장 긴 substring 의 길이을 구하라. + 2.constraints + - s.length min = 1, max = 10^5 + - k.length min = 0, max = s.length + 3.solution + - sliding window: time O(n), space O(1) + */ + + int[] table = new int[26]; + int n = s.length(); + int maxFreq = 0; + int maxLen = 0; + int left = 0; + + for(int right = 0; right < n; right++) { + //1.right 확장 -> count 증가 + int currentChar = s.charAt(right) - 'A'; + table[currentChar]++; + + //2.maxFreq update + maxFreq = Math.max(maxFreq, table[currentChar]); + + //3.조건 깨지면 left 이동하면서 count-- + //바꿔야하는 문자 개수가 k 보다 큰 경우 + if((right - left + 1 - maxFreq)> k) { + int idx = s.charAt(left) - 'A'; + table[idx]--; + left++; + } + + //4.maxLen update + maxLen = Math.max(maxLen, right - left + 1); + } + return maxLen; + } +} From 2a3f7c8cfb6d74ec547a46163cc2d1ea2a89f943 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月24日 22:07:39 +0900 Subject: [PATCH 405/526] reverse-bits solution --- reverse-bits/hyeri0903.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 reverse-bits/hyeri0903.java diff --git a/reverse-bits/hyeri0903.java b/reverse-bits/hyeri0903.java new file mode 100644 index 0000000000..9512e0d885 --- /dev/null +++ b/reverse-bits/hyeri0903.java @@ -0,0 +1,11 @@ +class Solution { + public int reverseBits(int n) { + int result = 0; + for(int i = 0; i < 32; i++) { + result <<= 1; //왼쪽 이동 + result |= (n & 1); //마지막 비트 붙이기 + n>>= 1; // 오른쪽 이동 + } + return result; + } +} From 5cf072be417dbbe0d7837f8f3a8eddb1f7546d64 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月24日 22:31:43 +0900 Subject: [PATCH 406/526] palindromic-substrings solution --- palindromic-substrings/hyeri0903.java | 38 +++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/palindromic-substrings/hyeri0903.java b/palindromic-substrings/hyeri0903.java index e69de29bb2..e7a19f8df3 100644 --- a/palindromic-substrings/hyeri0903.java +++ b/palindromic-substrings/hyeri0903.java @@ -0,0 +1,38 @@ +class Solution { + public int countSubstrings(String s) { + /** + 1.문제: s 에서 palindromoic substring 개수 return + 2.constraints: + - 연속적인 문자 + - s.length min = 1, max = 1000 + 3.풀이 + - bruteforce: time:O(n^3), space:O(n) + - expand around : time(On^2), space:O(1) + */ + + int n = s.length(); + if(n == 1) return 1; + int count = 0; + + for(int i = 0; i < n; i++) { + //odd + count += checkPalindrome(s, i, i); + + //even + count += checkPalindrome(s, i, i+1); + } + return count; + + } + + private int checkPalindrome(String s, int left, int right) { + int count = 0; + while(left>= 0 && right < s.length() && s.charAt(right) == s.charAt(left)) { + count += 1; + left -= 1; + right += 1; + } + return count; + } + +} From ccd1c10f4ebd2c073851a46930e575edce414dc3 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月24日 22:40:05 +0900 Subject: [PATCH 407/526] clone-graph solution --- clone-graph/hyeri0903.java | 44 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 clone-graph/hyeri0903.java diff --git a/clone-graph/hyeri0903.java b/clone-graph/hyeri0903.java new file mode 100644 index 0000000000..a09359d187 --- /dev/null +++ b/clone-graph/hyeri0903.java @@ -0,0 +1,44 @@ +/* +// Definition for a Node. +class Node { + public int val; + public List neighbors; + public Node() { + val = 0; + neighbors = new ArrayList(); + } + public Node(int _val) { + val = _val; + neighbors = new ArrayList(); + } + public Node(int _val, ArrayList _neighbors) { + val = _val; + neighbors = _neighbors; + } +} +*/ + +class Solution { + //key: original node, value: clone node + private Map map = new HashMap(); + + public Node cloneGraph(Node node) { + if(node == null) { + return null; + } + //이미 존재하면 return + if(map.containsKey(node)) { + return map.get(node); + } + + //현재 노드 복제 + Node clone = new Node(node.val); + map.put(node, clone); + + //이웃 노드들 복제해서 연결 + for(Node neighbor: node.neighbors) { + clone.neighbors.add(cloneGraph(neighbor)); + } + return clone; + } +} From ca310996860e74c0052fcbe1f68464bc04f2be85 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年4月25日 10:31:57 +0900 Subject: [PATCH 408/526] =?UTF-8?q?feat:=20=EA=B8=B0=EB=B3=B8=EC=A0=81?= =?UTF-8?q?=EC=9D=B8=20=ED=92=80=EC=9D=B4=EB=B2=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reverse-bits/gyeo-ri.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 reverse-bits/gyeo-ri.py diff --git a/reverse-bits/gyeo-ri.py b/reverse-bits/gyeo-ri.py new file mode 100644 index 0000000000..1d7a173992 --- /dev/null +++ b/reverse-bits/gyeo-ri.py @@ -0,0 +1,26 @@ +class Solution: + def reverseBits(self, n: int) -> int: + n_binary_str = bin(n).replace("0b", "").zfill(32) + n_reversed_binary = "".join(reversed(n_binary_str)) + return int(n_reversed_binary, 2) + + +if __name__ == "__main__": + test_cases = [ + (43261596, 964176192), + (2147483644, 1073741822), + (0, 0), + (2, 1073741824), + ] + + solution = Solution() + + for idx, (inp, expected) in enumerate(test_cases, start=1): + + result = solution.reverseBits(inp) + + assert ( + result == expected + ), f"Test Case {idx} Failed: Expected {expected}, Got {result}" + + print("All test cases passed.") From ee78a85ad63a9650ca29cc667c4443ad871433ec Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年4月25日 10:33:16 +0900 Subject: [PATCH 409/526] =?UTF-8?q?fix:=20=EC=A4=84=EB=B0=94=EA=BF=88=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reverse-bits/gyeo-ri.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/reverse-bits/gyeo-ri.py b/reverse-bits/gyeo-ri.py index 1d7a173992..10e6d7e28b 100644 --- a/reverse-bits/gyeo-ri.py +++ b/reverse-bits/gyeo-ri.py @@ -12,15 +12,11 @@ def reverseBits(self, n: int) -> int: (0, 0), (2, 1073741824), ] - solution = Solution() for idx, (inp, expected) in enumerate(test_cases, start=1): - result = solution.reverseBits(inp) - assert ( result == expected ), f"Test Case {idx} Failed: Expected {expected}, Got {result}" - print("All test cases passed.") From 9fea5c6c1e71e2985491846061a19950e1f65976 Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年4月25日 22:30:26 +0900 Subject: [PATCH 410/526] week8: reverse-bits --- reverse-bits/reeseo3o.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 reverse-bits/reeseo3o.js diff --git a/reverse-bits/reeseo3o.js b/reverse-bits/reeseo3o.js new file mode 100644 index 0000000000..a53805b6ee --- /dev/null +++ b/reverse-bits/reeseo3o.js @@ -0,0 +1,22 @@ +// Time Complexity: O(1) +// Space Complexity: O(1) + +const reverseBits = (n) => { + let result = 0; + + // 32비트 고정 - 정확히 32번 + for (let i = 0; i < 32; i++) { + // 1. n의 마지막 비트만 뽑기 (0 또는 1) + const bit = n & 1; + + // 2. result를 한 칸 왼쪽으로 밀고, 거기에 bit를 붙이기 + result = (result << 1) | bit; + + // 3. n은 오른쪽으로 한 칸 밀어서 다음 비트 준비 + n>>>= 1; + } + + // 항상 32비트 unsigned로 보이게 하기 위해 마지막에 한 번 더>>> 0 + return result>>> 0; + }; + \ No newline at end of file From f5c466cca792a375a9a7c520375059bea5195544 Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年4月25日 22:32:32 +0900 Subject: [PATCH 411/526] fix: remove unnecessary newline at the end --- reverse-bits/reeseo3o.js | 1 - 1 file changed, 1 deletion(-) diff --git a/reverse-bits/reeseo3o.js b/reverse-bits/reeseo3o.js index a53805b6ee..a87a04f730 100644 --- a/reverse-bits/reeseo3o.js +++ b/reverse-bits/reeseo3o.js @@ -19,4 +19,3 @@ const reverseBits = (n) => { // 항상 32비트 unsigned로 보이게 하기 위해 마지막에 한 번 더>>> 0 return result>>> 0; }; - \ No newline at end of file From fbfa650b925f74da8bcb84163e3a2b0ee40ec659 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年4月25日 22:52:21 +0900 Subject: [PATCH 412/526] =?UTF-8?q?feat:=20=EB=B9=84=ED=8A=B8=20=EC=97=B0?= =?UTF-8?q?=EC=82=B0=20=EA=B8=B0=EB=B0=98=EC=9D=98=20=EC=BD=94=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reverse-bits/gyeo-ri.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/reverse-bits/gyeo-ri.py b/reverse-bits/gyeo-ri.py index 10e6d7e28b..5b1d612fe2 100644 --- a/reverse-bits/gyeo-ri.py +++ b/reverse-bits/gyeo-ri.py @@ -1,8 +1,10 @@ class Solution: def reverseBits(self, n: int) -> int: - n_binary_str = bin(n).replace("0b", "").zfill(32) - n_reversed_binary = "".join(reversed(n_binary_str)) - return int(n_reversed_binary, 2) + result = 0 + for _ in range(32): + result = (result << 1) | (n & 1) + n>>= 1 + return result if __name__ == "__main__": From 899a78f7b3c20618f05abc90256eef3ca7b256d4 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年4月25日 22:58:28 +0900 Subject: [PATCH 413/526] =?UTF-8?q?fix:=20=EB=B9=84=ED=8A=B8=20=EC=97=B0?= =?UTF-8?q?=EC=82=B0=EC=9D=98=20=EB=8F=99=EC=9E=91=20=EC=88=9C=EC=84=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=3D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reverse-bits/gyeo-ri.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/reverse-bits/gyeo-ri.py b/reverse-bits/gyeo-ri.py index 5b1d612fe2..4cd7482fc6 100644 --- a/reverse-bits/gyeo-ri.py +++ b/reverse-bits/gyeo-ri.py @@ -2,7 +2,11 @@ class Solution: def reverseBits(self, n: int) -> int: result = 0 for _ in range(32): + # 1. n의 마지막 자리를 뽑아서(n & 1) + # 2. result의 마지막 자리를 0으로 만든 다음(result << 1 -> 마지막 자리가 0) + # 3. 그 마지막 자리에 n의 마지막 자리를 붙임(0과의 OR 연산) result = (result << 1) | (n & 1) + # n의 자리를 이동 n>>= 1 return result From ceaeb0297afaff78c02a251bc67919b99b15033d Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: 2026年4月25日 23:05:45 +0900 Subject: [PATCH 414/526] =?UTF-8?q?fix:=20=ED=92=80=EC=9D=B4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reverse-bits/gyeo-ri.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/reverse-bits/gyeo-ri.py b/reverse-bits/gyeo-ri.py index 4cd7482fc6..9455674ce6 100644 --- a/reverse-bits/gyeo-ri.py +++ b/reverse-bits/gyeo-ri.py @@ -1,3 +1,17 @@ +""" +[결과 요약] +# 시도한 로직 수: 2 + 1. 문자열을 뒤집어 새 객체를 만들기 O(1) / O(1) + - reversed() 또는 문자열 슬라이싱으로 풀 수 있음 + - 메모리를 많이 사용함 + 2. 비트 연산 기반의 코드 O(1) / O(1) + - 파이썬의 특성으로 인해 (1)에 비해 메모리가 크게 개선되지는 않음 + - 파이썬은 int가 ‘기변 길이’의 객체여서 연산마다 새로운 객체를 생성하기 때문 + - 문자열 생성/파싱 등의 오버헤드가 줄기 때문에 성능에서 약간의 이점이 있음(지금 문제에서 큰 차이 x) + +) C, C++ 등의 언어는 int가 고정 크기(primitive)이기 때문에 재할당이 줄어서 메모리 사용에 이점이 있음 +""" + + class Solution: def reverseBits(self, n: int) -> int: result = 0 From a0a5139d5d02c28aa88124c444019bcb1283d85d Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: 2026年4月26日 01:46:27 +0900 Subject: [PATCH 415/526] sadie100: longest repeating character solution --- .../sadie100.ts | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 longest-repeating-character-replacement/sadie100.ts diff --git a/longest-repeating-character-replacement/sadie100.ts b/longest-repeating-character-replacement/sadie100.ts new file mode 100644 index 0000000000..9017f2cd06 --- /dev/null +++ b/longest-repeating-character-replacement/sadie100.ts @@ -0,0 +1,34 @@ +/* +start, end 투 포인터 변수를 생성하고 end를 하나씩 늘려 가며 s를 탐색 +글자별 개수를 저장하는 map, 최빈 등장수 maxCount를 통해 가장 많이 나온 캐릭터의 카운트를 저장하고 +만약 end-start+1-maxCount가 k를 넘어가면 start를 +1한다 +매번 end-start+1와 현 result를 비교하여 큰 값을 result로 갱신한다 + +시간복잡도 : O(N) +*/ + +function characterReplacement(s: string, k: number): number { + let start = 0 + let end = 0 + let result = 0 + let maxCount = 0 + const charMap = new Map() + + while (end < s.length) { + const thisChar = s[end] + const updatedCount = (charMap.get(thisChar) || 0) + 1 + charMap.set(thisChar, updatedCount) + maxCount = Math.max(maxCount, updatedCount) + + if (end - start + 1 - maxCount> k) { + const startChar = s[start] + charMap.set(startChar, charMap.get(startChar) - 1) + start += 1 + } + + result = Math.max(result, end - start + 1) + end += 1 + } + + return result +} From 6515a1e261826e001e6f6eac898426371b2962e2 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年4月26日 18:09:14 +0900 Subject: [PATCH 416/526] =?UTF-8?q?8=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=205=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clone-graph/hwi-middle.cpp | 47 +++++++++++++++++++ longest-common-subsequence/hwi-middle.cpp | 26 ++++++++++ .../hwi-middle.cpp | 25 ++++++++++ palindromic-substrings/hwi-middle.cpp | 35 ++++++++++++++ reverse-bits/hwi-middle.cpp | 17 +++++++ 5 files changed, 150 insertions(+) create mode 100644 clone-graph/hwi-middle.cpp create mode 100644 longest-common-subsequence/hwi-middle.cpp create mode 100644 longest-repeating-character-replacement/hwi-middle.cpp create mode 100644 palindromic-substrings/hwi-middle.cpp create mode 100644 reverse-bits/hwi-middle.cpp diff --git a/clone-graph/hwi-middle.cpp b/clone-graph/hwi-middle.cpp new file mode 100644 index 0000000000..b9bcf7be7a --- /dev/null +++ b/clone-graph/hwi-middle.cpp @@ -0,0 +1,47 @@ +/* +// Definition for a Node. +class Node { +public: + int val; + vector neighbors; + Node() { + val = 0; + neighbors = vector(); + } + Node(int _val) { + val = _val; + neighbors = vector(); + } + Node(int _val, vector _neighbors) { + val = _val; + neighbors = _neighbors; + } +}; +*/ + +class Solution { +public: + Node* cloneGraph(Node* node) { + if (node == nullptr) + { + return node; + } + + if (nodeMap.contains(node)) + { + return nodeMap[node]; + } + + Node* copied = new Node(node->val); + nodeMap[node] = copied; + for (auto n : node->neighbors) + { + copied->neighbors.push_back(cloneGraph(n)); + } + + return copied; + } + +private: + unordered_map nodeMap; +}; diff --git a/longest-common-subsequence/hwi-middle.cpp b/longest-common-subsequence/hwi-middle.cpp new file mode 100644 index 0000000000..1e6e248bc8 --- /dev/null +++ b/longest-common-subsequence/hwi-middle.cpp @@ -0,0 +1,26 @@ +class Solution { +public: + int longestCommonSubsequence(string text1, string text2) { + vector d(text1.length(), 0); + int ans = 0; + + for (auto c : text2) + { + int cur = 0; + for (int i = 0; i < d.size(); i++) + { + if (cur < d[i]) + { + cur = d[i]; + } + else if (c == text1[i]) + { + d[i] = cur + 1; + ans = max(ans, cur + 1); + } + } + } + + return ans; + } +}; diff --git a/longest-repeating-character-replacement/hwi-middle.cpp b/longest-repeating-character-replacement/hwi-middle.cpp new file mode 100644 index 0000000000..f91d10beca --- /dev/null +++ b/longest-repeating-character-replacement/hwi-middle.cpp @@ -0,0 +1,25 @@ +class Solution { +public: + int characterReplacement(string s, int k) { + unordered_map freq; + int res = 0; + int i = 0; + int maxFreq = 0; + + for (int j = 0; j < s.size(); j++) + { + freq[s[j]]++; + maxFreq = max(maxFreq, freq[s[j]]); + + while ((j - i + 1) - maxFreq> k) + { + freq[s[i]]--; + i++; + } + + res = max(res, j - i + 1); + } + + return res; + } +}; diff --git a/palindromic-substrings/hwi-middle.cpp b/palindromic-substrings/hwi-middle.cpp new file mode 100644 index 0000000000..eaba06f269 --- /dev/null +++ b/palindromic-substrings/hwi-middle.cpp @@ -0,0 +1,35 @@ +class Solution { +public: + int countSubstrings(string s) { + int n = s.size(); + if (n == 0) + { + return 0; + } + + vector> dp(n, vector(n)); + + int ans = n; + for (int i = 0; i < n; ++i) + { + dp[i][i] = true; + } + + for (int i = 0; i < n - 1; ++i) + { + dp[i][i + 1] = (s[i] == s[i + 1]); + ans += dp[i][i + 1]; + } + + for (int l = 3; l <= n; ++l) + { + for (int i = 0, j = i + l - 1; j < n; ++i, ++j) + { + dp[i][j] = dp[i + 1][j - 1] && (s[i] == s[j]); + ans += dp[i][j]; + } + } + + return ans; + } +}; diff --git a/reverse-bits/hwi-middle.cpp b/reverse-bits/hwi-middle.cpp new file mode 100644 index 0000000000..51ec953fc1 --- /dev/null +++ b/reverse-bits/hwi-middle.cpp @@ -0,0 +1,17 @@ +class Solution { +public: + int reverseBits(int n) { + int r = 0; + + for (int i = 0; i <= 31; ++i) + { + int pot = 1 << i; + if ((n & pot) != 0) + { + r |= (1 << (31 - i)); + } + } + + return r; + } +}; From 8ac97a97fc5d98ca8f5a3681ee35b7f193d03cab Mon Sep 17 00:00:00 2001 From: yihyun-kim1 Date: 2026年4月26日 23:27:27 +0900 Subject: [PATCH 417/526] add solution: reverse-bits --- reverse-bits/yihyun-kim1.js | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 reverse-bits/yihyun-kim1.js diff --git a/reverse-bits/yihyun-kim1.js b/reverse-bits/yihyun-kim1.js new file mode 100644 index 0000000000..aea83672ef --- /dev/null +++ b/reverse-bits/yihyun-kim1.js @@ -0,0 +1,9 @@ +/** + * @param {number} n + * @return {number} + */ +var reverseBits = function (n) { + const binary = n.toString(2).padStart(32, "0"); + const reversed = binary.split("").reverse().join(""); + return parseInt(reversed, 2); +}; From a42ef1d430690f957ea746c7e1ddb2e7698b47ee Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月27日 20:54:16 +0900 Subject: [PATCH 418/526] sum of two integers solution --- sum-of-two-integers/hyeri0903.java | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 sum-of-two-integers/hyeri0903.java diff --git a/sum-of-two-integers/hyeri0903.java b/sum-of-two-integers/hyeri0903.java new file mode 100644 index 0000000000..ac29adf173 --- /dev/null +++ b/sum-of-two-integers/hyeri0903.java @@ -0,0 +1,5 @@ +class Solution { + public int getSum(int a, int b) { + + } +} From 49d0f66bd4fe11d58abef9e9c7e972983dcedf9b Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月27日 21:05:12 +0900 Subject: [PATCH 419/526] sum of two integers solution --- sum-of-two-integers/hyeri0903.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/sum-of-two-integers/hyeri0903.java b/sum-of-two-integers/hyeri0903.java index ac29adf173..43e715c3e0 100644 --- a/sum-of-two-integers/hyeri0903.java +++ b/sum-of-two-integers/hyeri0903.java @@ -1,5 +1,18 @@ class Solution { public int getSum(int a, int b) { - + /** + 1.operator 을 쓰지않고 two sum 구하는 문제 + 2.constraints + - without using operators + and - + - value min = -1000, max = 1000 + 3.solution + -bit 연산 + */ + while (b != 0) { + int carry = (a & b) << 1; // 자리 올림 + a = a ^ b; // 자리 올림 없는 합 + b = carry; // 다음에 더할 carry + } + return a; } } From 9ddd9a0124c1e9b058ce61d7a531d746635159f2 Mon Sep 17 00:00:00 2001 From: soobing Date: 2026年4月27日 21:09:01 +0900 Subject: [PATCH 420/526] feat: test --- linked-list-cycle/soobing.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/linked-list-cycle/soobing.ts b/linked-list-cycle/soobing.ts index d363c846f3..7b36444da0 100644 --- a/linked-list-cycle/soobing.ts +++ b/linked-list-cycle/soobing.ts @@ -1,3 +1,4 @@ +// 3rd try /** * 문제 설명 * - 링크드리스트 내에 cycle이 존재하는지 확인하는 문제 From af83cb28bef55a8c4c7234884810a5b1ad4e08b2 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月27日 21:19:45 +0900 Subject: [PATCH 421/526] maximum-product-subarray solution --- maximum-product-subarray/hyeri0903.java | 43 +++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 maximum-product-subarray/hyeri0903.java diff --git a/maximum-product-subarray/hyeri0903.java b/maximum-product-subarray/hyeri0903.java new file mode 100644 index 0000000000..6e45f45d0e --- /dev/null +++ b/maximum-product-subarray/hyeri0903.java @@ -0,0 +1,43 @@ +class Solution { + public int maxProduct(int[] nums) { + /** + 1.problem: subarray 중에 가장 큰 product return + 2.constraints + - num.length min = 1 + - value min = -10, max=10 + 3.solutions + - bruteforce, time: O(n^2), space: O(1) + - min, max value 추적, time: O(n), space: O(1) + */ + int n = nums.length; + if (n == 1) return nums[0]; + + // int maxValue = Integer.MIN_VALUE; + // for(int i = 0; i < n; i++) { + // int curValue = 1; + // for(int j = i; j < n; j++) { + // curValue *= nums[j]; + // maxValue = Math.max(maxValue, curValue); + // } + // } + + int max = nums[0]; + int min = nums[0]; + int res = nums[0]; + + for(int i = 1; i < n; i++) { + int cur = nums[i]; + //현재값이 음수이면 min, max swap + if(cur < 0) { + int tmp = min; + min = max; + max = tmp; + } + max = Math.max(cur, max * cur); + min = Math.min(cur, min * cur); + + res = Math.max(max, res); + } + return res; + } +} From d2a3e67dc62d7932c62acca06df523a4a944ffc1 Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: 2026年4月28日 12:07:51 +0900 Subject: [PATCH 422/526] linked list cycle solution --- linked-list-cycle/robinyoon-dev.js | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 linked-list-cycle/robinyoon-dev.js diff --git a/linked-list-cycle/robinyoon-dev.js b/linked-list-cycle/robinyoon-dev.js new file mode 100644 index 0000000000..3f820457de --- /dev/null +++ b/linked-list-cycle/robinyoon-dev.js @@ -0,0 +1,47 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ + +/** + * @param {ListNode} head + * @return {boolean} + */ +var hasCycle = function (head) { + + const visited = new Set(); + let result = false; + + while (head) { + + let next = head.next; + + if (next == null) { + result = false; + break; + } + + let isExist = findElementInDp(head); + + if (!isExist) { + visited.add(head); + head = next; + } else { + result = true; + break; + } + } + + return result; + + function findElementInDp(head) { + if (visited.has(head)) { + return true; + } else { + return false; + } + } +}; From 084bbee6c964e81461588f3ddb0249e71e515222 Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: 2026年4月29日 12:47:03 +0900 Subject: [PATCH 423/526] sadie100: linked list cycle solution --- linked-list-cycle/sadie100.ts | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 linked-list-cycle/sadie100.ts diff --git a/linked-list-cycle/sadie100.ts b/linked-list-cycle/sadie100.ts new file mode 100644 index 0000000000..f39b92329d --- /dev/null +++ b/linked-list-cycle/sadie100.ts @@ -0,0 +1,32 @@ +/** + * Definition for singly-linked list. + * class ListNode { + * val: number + * next: ListNode | null + * constructor(val?: number, next?: ListNode | null) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + * } + */ + +/* +리스트 노드를 저장하는 Map을 생성, 노드를 탐색하며 해당 Map에 노드를 저장하고 이미 있는 노드일 경우 true 리턴 + +시간복잡도 : O(N) - N은 리스트의 개수 +공간복잡도 : O(N) - Map 객체 +*/ + +function hasCycle(head: ListNode | null): boolean { + const nodeMap = new Map() + + while (head) { + if (nodeMap.get(head) === true) { + return true + } + nodeMap.set(head, true) + head = head.next + } + + return false +} From bae3fa785347d2dca1695b3c7225a5f86a56a806 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月29日 20:17:42 +0900 Subject: [PATCH 424/526] linked-list-cycle solution --- linked-list-cycle/hyeri0903.java | 40 ++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 linked-list-cycle/hyeri0903.java diff --git a/linked-list-cycle/hyeri0903.java b/linked-list-cycle/hyeri0903.java new file mode 100644 index 0000000000..aa1e3d2415 --- /dev/null +++ b/linked-list-cycle/hyeri0903.java @@ -0,0 +1,40 @@ +/** + * Definition for singly-linked list. + * class ListNode { + * int val; + * ListNode next; + * ListNode(int x) { + * val = x; + * next = null; + * } + * } + */ +public class Solution { + public boolean hasCycle(ListNode head) { + /** + 1.prob: linked list 이면 true, 아니면 false return + 2.constraints + - # of nodes min = 0, max = 10000 + - pos: -1 or valid index + - pos는 파라미터로 받지 않음 + 3.solution + - pointer 2개를 두고 1개는 2칸씩, 1개는 1칸씩 이동하며 결국 만나는지 체크 + 만나면 true, 안 만나면 false return + */ + + ListNode slow = head; + ListNode fast = head; + + while(fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + + //노드가 동일하면 linked list + if(slow == fast) { + return true; + } + } + return false; + + } +} From 20962c488a21be961f03850c57eb4daefdf27012 Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: 2026年4月30日 09:43:51 +0900 Subject: [PATCH 425/526] solved linked-list-cycle. --- linked-list-cycle/sangbeenmoon.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 linked-list-cycle/sangbeenmoon.py diff --git a/linked-list-cycle/sangbeenmoon.py b/linked-list-cycle/sangbeenmoon.py new file mode 100644 index 0000000000..ccc32055ef --- /dev/null +++ b/linked-list-cycle/sangbeenmoon.py @@ -0,0 +1,18 @@ +# Definition for singly-linked list. +class ListNode: + def __init__(self, x): + self.val = x + self.next = None + +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + MM = 10001 + cnt = 0 + cur = head + while cur != None: + cnt += 1 + if cnt> MM: + return True + cur = cur.next + + return False From a1912615884c2a55ab1c1cfd26eae2c8f44ff517 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月30日 09:47:01 +0900 Subject: [PATCH 426/526] minimum-window-substring solutions --- minimum-window-substring/hyeri0903.java | 66 +++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 minimum-window-substring/hyeri0903.java diff --git a/minimum-window-substring/hyeri0903.java b/minimum-window-substring/hyeri0903.java new file mode 100644 index 0000000000..93fb67423a --- /dev/null +++ b/minimum-window-substring/hyeri0903.java @@ -0,0 +1,66 @@ +class Solution { + public String minWindow(String s, String t) { + /** + 1.prob: t문자를 포함하는 최소 길이의 substring return. + 2.constraints + - 정답은 단 1개 + - t의 모든 문자를 포함 + - m,n length min = 1, max = 100000 + - s,t 는 uppercase or lowercase + - 정답 없으면 emptystring "" return + 3.solution + - brutforce, 모든 substring 구해서 t문자 포함 여부 체크, time complexity: O(n^2) + - two pointer: right pointer 움직이다가 t문자 모두 포함하면 left pointer 옮기면서 가장 작은 사이즈의 substring 구하기, time compliexty: O(n) + 힌트 봐도 모르겠어서 풀이보고 풀었습니다 ᅮᅮ + */ + + int m = s.length(); + int n = t.length(); + String answer = ""; + + if(m < n) return ""; + + int left = 0, right = 0; + int count = n; //필요한 문자 수 = t.length() + int minLen = Integer.MAX_VALUE; + int start = 0; //조건 만족하는 left pointer 시작 포인트 + + int[] freq = new int[128]; + for(char c : t.toCharArray()) { + freq[c]++; + } + + while(right < m) { + char r = s.charAt(right); + //t 문자면 count-- + if(freq[r]> 0) { + count --; + } + freq[r]--; + right++; + + //조건 만족하면 left pointer 이동하며 minimum length 찾음 + while(count == 0) { + //minLen update + if(right - left < minLen) { + minLen = right - left; + start = left; //minLen 업데이트 시 Left pointer index 저장 + } + char l = s.charAt(left); + freq[l]++; + + //t문자(필요한 문자)이면 count 증가 (원래 값으로 복구) + if(freq[l]> 0) count++; + left++; + } + + } + + if(minLen == Integer.MAX_VALUE) { + answer = ""; + } else { + answer = s.substring(start, start + minLen); + } + return answer; + } +} From 26f755cb27d30be14c113633ce2b116890aadde4 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年4月30日 09:47:59 +0900 Subject: [PATCH 427/526] minimum-window-substring solutions --- minimum-window-substring/hyeri0903.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minimum-window-substring/hyeri0903.java b/minimum-window-substring/hyeri0903.java index 93fb67423a..a8b4d3cbc3 100644 --- a/minimum-window-substring/hyeri0903.java +++ b/minimum-window-substring/hyeri0903.java @@ -10,7 +10,7 @@ public String minWindow(String s, String t) { - 정답 없으면 emptystring "" return 3.solution - brutforce, 모든 substring 구해서 t문자 포함 여부 체크, time complexity: O(n^2) - - two pointer: right pointer 움직이다가 t문자 모두 포함하면 left pointer 옮기면서 가장 작은 사이즈의 substring 구하기, time compliexty: O(n) + - two pointer: right pointer 움직이다가 t문자 모두 포함하면 left pointer 옮기면서 가장 작은 사이즈의 substring 구하기, time compliexty: O(m+n), space: O(1) 힌트 봐도 모르겠어서 풀이보고 풀었습니다 ᅮᅮ */ From fb0cd2b90d3de6cea893d6415a6582b8cdd91316 Mon Sep 17 00:00:00 2001 From: Dale Seo <5466341+daleseo@users.noreply.github.com> Date: 2026年4月29日 21:45:03 -0400 Subject: [PATCH 428/526] pacific-atlantic-water-flow --- pacific-atlantic-water-flow/DaleSeo.rs | 80 ++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 pacific-atlantic-water-flow/DaleSeo.rs diff --git a/pacific-atlantic-water-flow/DaleSeo.rs b/pacific-atlantic-water-flow/DaleSeo.rs new file mode 100644 index 0000000000..2e5ee16640 --- /dev/null +++ b/pacific-atlantic-water-flow/DaleSeo.rs @@ -0,0 +1,80 @@ +use std::collections::VecDeque; + +impl Solution { + pub fn pacific_atlantic(heights: Vec>) -> Vec> { + let n_rows = heights.len(); + let n_cols = heights[0].len(); + + let mut pacific = vec![vec![false; n_cols]; n_rows]; + let mut atlantic = vec![vec![false; n_cols]; n_rows]; + + let mut pacific_queue = VecDeque::new(); + let mut atlantic_queue = VecDeque::new(); + + for i in 0..n_rows { + pacific[i][0] = true; + pacific_queue.push_back((i, 0)); + } + for j in 0..n_cols { + pacific[0][j] = true; + pacific_queue.push_back((0, j)); + } + + for i in 0..n_rows { + atlantic[i][n_cols - 1] = true; + atlantic_queue.push_back((i, n_cols - 1)); + } + for j in 0..n_cols { + atlantic[n_rows - 1][j] = true; + atlantic_queue.push_back((n_rows - 1, j)); + } + + Self::bfs(&heights, &mut pacific, pacific_queue); + Self::bfs(&heights, &mut atlantic, atlantic_queue); + + let mut result = vec![]; + + for i in 0..n_rows { + for j in 0..n_cols { + if pacific[i][j] && atlantic[i][j] { + result.push(vec![i as i32, j as i32]); + } + } + } + + result + } + + fn bfs( + heights: &Vec>, + visited: &mut Vec>, + mut queue: VecDeque<(usize, usize)>, + ) { + let directions = vec![(1, 0), (-1, 0), (0, 1), (0, -1)]; + let m = heights.len(); + let n = heights[0].len(); + + while let Some((i, j)) = queue.pop_front() { + for (dx, dy) in &directions { + let ni = i as i32 + dx; + let nj = j as i32 + dy; + + if ni < 0 || nj < 0 || ni>= m as i32 || nj>= n as i32 { + continue; + } + + let ni = ni as usize; + let nj = nj as usize; + + if visited[ni][nj] { + continue; + } + + if heights[ni][nj]>= heights[i][j] { + visited[ni][nj] = true; + queue.push_back((ni, nj)); + } + } + } + } +} From 747055608c7ba36f3ef4f9ebcf09067cdf2389c4 Mon Sep 17 00:00:00 2001 From: Ted Date: 2026年4月29日 22:38:57 -0400 Subject: [PATCH 429/526] add solutions --- linked-list-cycle/tedkimdev.go | 23 +++++++++++ minimum-window-substring/tedkimdev.go | 55 +++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 linked-list-cycle/tedkimdev.go create mode 100644 minimum-window-substring/tedkimdev.go diff --git a/linked-list-cycle/tedkimdev.go b/linked-list-cycle/tedkimdev.go new file mode 100644 index 0000000000..8ff4024ed7 --- /dev/null +++ b/linked-list-cycle/tedkimdev.go @@ -0,0 +1,23 @@ +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ + +// TC: O(n) +// SC: O(1) +func hasCycle(head *ListNode) bool { + slow := head + fast := head + for fast != nil && fast.Next != nil { + slow = slow.Next + fast = fast.Next.Next + if slow == fast { + return true + } + } + + return false +} diff --git a/minimum-window-substring/tedkimdev.go b/minimum-window-substring/tedkimdev.go new file mode 100644 index 0000000000..6cfa523d5a --- /dev/null +++ b/minimum-window-substring/tedkimdev.go @@ -0,0 +1,55 @@ +// TC: O(n * m) +// SC: O(n + m) + +func minWindow(s string, t string) string { + if len(t)> len(s) { + return "" + } + + countT := map[byte]int{} + for i := 0; i < len(t); i++ { + countT[t[i]]++ + } + + windowMap := map[byte]int{} + have, need := 0, len(countT) + + left := 0 + resLeft, resRight := -1, -1 + resLen := len(s) + 1 + + for right := 0; right < len(s); right++ { + c := s[right] + windowMap[c]++ + + // update have + if count, ok := countT[c]; ok { + if windowMap[c] == count { + have++ + } + } + + // window valid -> move left to find minimum + for have == need { + if right-left+1 < resLen { + resLen = right - left + 1 + resLeft, resRight = left, right + } + + // remove left char + lc := s[left] + if count, ok := countT[lc]; ok { + if windowMap[lc] == count { + have-- + } + } + windowMap[lc]-- + left++ + } + } + + if resLeft == -1 { + return "" + } + return s[resLeft : resRight+1] +} From 88ae50e41f4e42ceb23a20d2ddeb2ef3195c012e Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: 2026年4月30日 19:15:34 +0900 Subject: [PATCH 430/526] sadie100: pacific atlantic solution --- pacific-atlantic-water-flow/sadie100.ts | 79 +++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 pacific-atlantic-water-flow/sadie100.ts diff --git a/pacific-atlantic-water-flow/sadie100.ts b/pacific-atlantic-water-flow/sadie100.ts new file mode 100644 index 0000000000..649252eb7a --- /dev/null +++ b/pacific-atlantic-water-flow/sadie100.ts @@ -0,0 +1,79 @@ +/** +pacific에 닿을 수 있는 grid를 판별하는 이중 배열과 atlantic에 닿을 수 있는지를 판별하는 이중 배열을 생성한다. +pacific 배열은 r, c 중 하나라도 0일 경우 true값, +atlantic 배열은 r, c 중 하나라도 length값과 같을 경우 true값을 채운다 + +이후 r, c 탐색을 돌며 pacific/ atlantic true인 값이 있으면 dfs를 돌린다 + - 이전 heights값보다 크거나 같으면 true 처리, 인접한 셀을 또 dfs 탐색 + +두 배열값이 둘 다 true인 위치들을 리턴한다 + +시간복잡도 : O(M*N) - 순회 + */ + +function pacificAtlantic(heights: number[][]): number[][] { + const m = heights.length + const n = heights[0].length + const result = [] + const pacificChecker = Array.from({ length: m }).map((el, idx) => { + if (idx === 0) { + return new Array(n).fill(true) + } else { + const arr = new Array(n).fill(false) + arr[0] = true + return arr + } + }) + const atlanticChecker = Array.from({ length: m }).map((el, idx) => { + if (idx === m - 1) { + return new Array(n).fill(true) + } else { + const arr = new Array(n).fill(false) + arr[n - 1] = true + return arr + } + }) + + const dx = [0, 1, -1, 0] + const dy = [1, 0, 0, -1] + + const search = (row, col, checker, stdValue) => { + const value = heights[row][col] + if (value < stdValue) return + + checker[row][col] = true + + for (let i = 0; i < 4; i++) { + const newRow = row + dx[i] + const newCol = col + dy[i] + if (newRow < 0 || newRow>= m) continue + if (newCol < 0 || newCol>= n) continue + if (checker[newRow][newCol]) continue + + search(newRow, newCol, checker, value) + } + } + + // dfs 탐색 + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (pacificChecker[i][j]) { + search(i, j, pacificChecker, heights[i][j]) + } + if (atlanticChecker[i][j]) { + search(i, j, atlanticChecker, heights[i][j]) + } + } + } + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (pacificChecker[i][j] && atlanticChecker[i][j]) { + result.push([i, j]) + } + } + } + + //pacific, atlantic 모두 true인 인덱스배열 반환 + return result +} From a9f9d3759f33614730679e8372a48aafc0817ecd Mon Sep 17 00:00:00 2001 From: jamiebase <100mgml@gmail.com> Date: Fri, 1 May 2026 18:30:59 +0900 Subject: [PATCH 431/526] Add solution for Pacific Atlantic Water Flow problem --- pacific-atlantic-water-flow/jamiebase.py | 56 ++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 pacific-atlantic-water-flow/jamiebase.py diff --git a/pacific-atlantic-water-flow/jamiebase.py b/pacific-atlantic-water-flow/jamiebase.py new file mode 100644 index 0000000000..60df92c66e --- /dev/null +++ b/pacific-atlantic-water-flow/jamiebase.py @@ -0,0 +1,56 @@ +""" +# Approach +태평양 가장자리에서 출발해서, 물이 거꾸로 올라올 수 있는 칸들을 찾고 대서양도 똑같이 찾은 뒤 둘의 교집합을 구한다. + +# Complexity +- Time complexity: O(rows * cols) +- Space complexity: O(rows * cols) +""" + +from collections import deque + + +class Solution: + def pacificAtlantic(self, heights: list[list[int]]) -> list[list[int]]: + rows, cols = len(heights), len(heights[0]) + directions = [(0, 1), (0, -1), (1, 0), (-1, 0)] + + def bfs(starts): + visited = set(starts) + q = deque(starts) + + while q: + r, c = q.popleft() + + for dr, dc in directions: + nr, nc = r + dr, c + dc + + if not (0 <= nr < rows and 0 <= nc < cols): + continue + if (nr, nc) in visited: + continue + + # 역방향: 현재보다 같거나 높은 곳으로 이동 가능 + if heights[nr][nc] < heights[r][c]: + continue + + visited.add((nr, nc)) + q.append((nr, nc)) + + return visited + + pacific_starts = [] + atlantic_starts = [] + + for r in range(rows): + pacific_starts.append((r, 0)) + atlantic_starts.append((r, cols - 1)) + + for c in range(cols): + pacific_starts.append((0, c)) + atlantic_starts.append((rows - 1, c)) + + pacific = bfs(pacific_starts) + atlantic = bfs(atlantic_starts) + + return [[r, c] for r, c in pacific & atlantic] From 2bef40098205b29d6e65a247f8d61e625156c96d Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Sat, 2 May 2026 02:03:03 +0900 Subject: [PATCH 432/526] [7th batch] week 9 - pacific atlantic water flow --- pacific-atlantic-water-flow/liza0525.py | 37 +++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 pacific-atlantic-water-flow/liza0525.py diff --git a/pacific-atlantic-water-flow/liza0525.py b/pacific-atlantic-water-flow/liza0525.py new file mode 100644 index 0000000000..884d58d3de --- /dev/null +++ b/pacific-atlantic-water-flow/liza0525.py @@ -0,0 +1,37 @@ +# 7기 풀이 +# 시간 복잡도: O(m * n) +# - 최대 재귀 스택 +# 공간 복잡도: O(m * n) +# - 인덱스 모두가 대서양과 태평양에 도달할 때 최대 공간 복잡도 +class Solution: + # 문제 접근 방향 + # 각 지점에서 시작하는 것이 아닌, 태평양과 대서양에 맞닿아 있는 인덱스에서 시작해서 + # 최대 높이에 도달할 때까지 DFS로 접근 후, 두 대양에서 모두 도달하는 인덱스를 찾는다. + def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]: + directions = [(0, -1), (0, 1), (-1, 0), (1, 0)] + + pacific_dest = set() # 태평양에서 시작할 때 갈 수 있는 곳 + atlantic_dest = set() # 대서양에서 시작했을 때 갈 수 있는 곳 + + def dfs(i, j, dest): + dest.add((i, j)) + for dir_i, dir_j in directions: + next_i, next_j = i + dir_i, j + dir_j + + if ( + 0 <= next_i < len(heights) + and 0 <= next_j < len(heights[0]) + and (next_i, next_j) not in dest + and heights[next_i][next_j]>= heights[i][j] # 다음 인덱스가 같거나 높은 경우만 탐색 + ): + dfs(next_i, next_j, dest) + + for j in range(len(heights[0])): + dfs(0, j, pacific_dest) # 태평양에서 시작(맨 윗줄) + dfs(len(heights) - 1, j, atlantic_dest) # 대서양에서 시작(맨 아랫줄) + + for i in range(len(heights)): + dfs(i, 0, pacific_dest) # 태평양에서 시작(맨 왼쪽 줄) + dfs(i, len(heights[0]) - 1, atlantic_dest) # 대서양에서 시작(맨 오른쪽 줄) + + return list(pacific_dest.intersection(atlantic_dest)) # 겹치는 도착지만 리턴 From 1e269c17bfe28c3584a35b35cd05cbb808194737 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Sat, 2 May 2026 02:09:51 +0900 Subject: [PATCH 433/526] [7th batch] week 9 - maximum product subarray --- maximum-product-subarray/liza0525.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 maximum-product-subarray/liza0525.py diff --git a/maximum-product-subarray/liza0525.py b/maximum-product-subarray/liza0525.py new file mode 100644 index 0000000000..648bdaf9f6 --- /dev/null +++ b/maximum-product-subarray/liza0525.py @@ -0,0 +1,27 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - nums의 길이(n)만큼의 시간 복잡도 +# 공간 복잡도: O(1) +# - 몇 개의 변수만 사용 +class Solution: + # 문제에서는 이어지는 subarray 내에 음수가 짝수 번 만큼 있다면 최대가 만들어지기도 하므로 + # max_val과 min_val을 가지고 음수의 곱도 대응할 수 있도록 한다. + def maxProduct(self, nums: List[int]) -> int: + max_val, min_val = nums[0], nums[0] + res = nums[0] + + for num in nums[1:]: + prev_max_val = max_val # 이전 max_val은 업데이트 되기 전에 잠시 저장 + + # 현재 loop에서 num과 max_val(이전까지의 최대곱) * num과 min_val(이전까지의 최소곱) * num 중 + # 가장 큰 수를 max_val로 업데이트 + # 이때 num이 저장된다는 의미는 최대/최소곱을 해당 숫자에서 다시 시작하여 곱한다는 의미 + max_val = max(num, max_val * num, min_val * num) + + # min_val도 max_val과 동일한 원리로 저장, 이때는 미리 저장한 prev_max_val을 이용 + min_val = min(num, prev_max_val * num, min_val * num) + + # 현재까지의 결과와 이번 loop에서의 max_val을 비교하여 더 큰 수를 res로 업데이트 + res = max(res, max_val) + + return res From 03be2d0e03c4ed22c11296b1362b79de3fd4ca9c Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Sat, 2 May 2026 02:19:05 +0900 Subject: [PATCH 434/526] [7th batch] week 9 - minimum window substring --- minimum-window-substring/liza0525.py | 52 ++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 minimum-window-substring/liza0525.py diff --git a/minimum-window-substring/liza0525.py b/minimum-window-substring/liza0525.py new file mode 100644 index 0000000000..c0aae8c9f4 --- /dev/null +++ b/minimum-window-substring/liza0525.py @@ -0,0 +1,52 @@ +from collections import defaultdict + + +# 7기 풀이 +# 시간 복잡도: O(n) +# - s의 길이(n)만큼의 시간복잡도 +# 공간 복잡도: O(1) +# - char_dict에는 최대 26개의 알파벳만큼 저장 + 몇 개의 변수 +class Solution: + # 윈도우가 늘어나는 조건(right가 올라가는 조건): t의 알파벳 전체가 윈도우에 모두 포함될 때까지 + # 윈도우가 유지되는 조건(left가 올라가는 조건): t의 알파벳 전체가 윈도우에 포함이 된 후, 한 개라도 누락될 때까지 + def minWindow(self, s: str, t: str) -> str: + char_dict = defaultdict(int) + + # t의 구성 알파벳 정보 저장 + for tt in t: + # 알파벳 당 몇 개가 있는지 char_dict에 저장 + char_dict[tt] += 1 + # t에 있는 알파벳 종류의 개수 + need_alpha = len(char_dict) + + left = 0 + res = "" + + for right in range(len(s)): + if s[right] in char_dict: + # s[right]가 char_dict에 있다면 윈도우에 해당 알파벳이 있다는 의미로 + # char_dict에서 하나 차감 + char_dict[s[right]] -= 1 + if char_dict[s[right]] == 0: + # 해당 알파벳의 개수가 0이 되면 필요한 알파벳 중 하나를 다 찾았으므로 + # need_alpha를 하나 차감 + need_alpha -= 1 + + while need_alpha == 0: + # need_alpha가 0이라는 의미는 모든 글자를 다 찾았다는 의미 + # 윈도우를 유지하며 left를 올린다 + if not res or right - left + 1 < len(res): + # 현재의 res 글자보다 left / right 간 사이가 작을 때 res 업데이트 + res = s[left:right + 1] + if s[left] in char_dict: + # s[left]가 char_dict에 있다는 것은 left를 옮길 때 해당 알파벳은 누락이 되기 때문에 + # 다음 윈도우 구간에서는 다시 필요하므로 char_dict 내 해당 알파벳 개수를 다시 증가 + # need_alpha도 하나 증가 시켜줘야 한다. + if char_dict[s[left]] == 0: + need_alpha += 1 + char_dict[s[left]] += 1 + + # left 이동 + left += 1 + + return res From b3aa26b6f65c52f0aa951842d1de2de0bf32476d Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Sat, 2 May 2026 02:24:58 +0900 Subject: [PATCH 435/526] [7th batch] week 9 - sum of two integers --- sum-of-two-integers/liza0525.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 sum-of-two-integers/liza0525.py diff --git a/sum-of-two-integers/liza0525.py b/sum-of-two-integers/liza0525.py new file mode 100644 index 0000000000..d08062d1d0 --- /dev/null +++ b/sum-of-two-integers/liza0525.py @@ -0,0 +1,20 @@ +# 7기 풀이 +# 시간 복잡도: O(1) +# - 숫자가 32비트이기 때문에 최대 32번의 루프 +# 공간 복잡도: O(1) +# - 몇 개의 변수만 +class Solution: + # 해당 문제는 bit 연산을 이용해서 덧셈을 구현 + def getSum(self, a: int, b: int) -> int: + # 문제 조건에 두 숫자는 모두 32bit 숫자임을 명시되었으며 + # 이 mask를 사용해야 음수 대응도 가능해진다. + mask = 0xFFFFFFFF + + while b & mask: + carry = (a & b) << 1 # 올림 표현 + a = a ^ b # XOR 연산, 비트의 덧셈은 XOR과 동일하기 때문 + b = carry # 올림한 것을 다음 연산에 사용한다 + + # b가 0이 아니라면 무한 비트로 올라가고 있음을 의미하며 + # 음수 대응을 위해 a와 mask를 and 연산하여 return + return a if b == 0 else a & mask From da022f137a568d856a8c6f30daf7dd5be305eeaf Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Sat, 2 May 2026 02:34:27 +0900 Subject: [PATCH 436/526] [7th batch] week 9 - linked list cycle --- linked-list-cycle/liza0525.py | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 linked-list-cycle/liza0525.py diff --git a/linked-list-cycle/liza0525.py b/linked-list-cycle/liza0525.py new file mode 100644 index 0000000000..e85adb5da5 --- /dev/null +++ b/linked-list-cycle/liza0525.py @@ -0,0 +1,48 @@ +# 7기 풀이 +class Solution: + # 1. 첫번째 풀이: 이 풀이는 한 칸 씩 헤드를 옮기는 것과 두 칸 씩 헤드를 옮기는 것을 비교하여 + # 헤드가 동일해지면 해당 리스트는 순환한다는 아이디어에서 착안 + # 시간 복잡도: O(n) + # - 리스트의 길이(n) 만큼의 시간이 최대 + # 공간 복잡도: O(1) + # - slow, fast 변수만 사용 + def hasCycle(self, head: Optional[ListNode]) -> bool: + slow = head + fast = head + + while slow and fast: + slow = slow.next + + if not fast.next: + # fast의 다음 노드가 없다면 + # 순환이 되지 않다는 것을 의미하므로 loop 탈출 + break + fast = fast.next.next + + if slow == fast: + # 같아지는 순간이 순환한다는 것을 의미하므로 True로 early return + return True + + # loop 탈출 조건에 의해 순환하지 않음을 확인하여 False return + return False + + # 2. 두번째 풀이: 이미 방문한 노드에 다시 방문하는 경우에 순환한다고 판단 + # 시간 복잡도: O(n) + # - 리스트의 길이(n) 만큼의 시간이 최대 + # 공간 복잡도: O(n) + # - list의 길이(n)이 최대 공간 복잡도(checked가 늘어남) + def hasCycle(self, head: Optional[ListNode]) -> bool: + checked = set() # 노드 방문 여부를 저장 + curr = head + + while curr: # curr가 None이 되기 전까지(== 끝에 도달할 때까지) + if curr in checked: + # 이미 방문한 노드라면 순환한다는 의미이므로 True로 early return + return True + + # 방문한 노드는 checked에 추가 + checked.add(curr) + curr = curr.next # 다음 node 탐색 + + # loop 탈출 조건에 의해 순환하지 않음을 확인하여 False return + return False From 778d9acc23b18e9fd64eda97624521cc07470e4f Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: Sat, 2 May 2026 08:51:48 +0900 Subject: [PATCH 437/526] refactor: while condition --- linked-list-cycle/sangbeenmoon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linked-list-cycle/sangbeenmoon.py b/linked-list-cycle/sangbeenmoon.py index ccc32055ef..3e3a24c7df 100644 --- a/linked-list-cycle/sangbeenmoon.py +++ b/linked-list-cycle/sangbeenmoon.py @@ -9,7 +9,7 @@ def hasCycle(self, head: Optional[ListNode]) -> bool: MM = 10001 cnt = 0 cur = head - while cur != None: + while cur: cnt += 1 if cnt> MM: return True From 459aabb692c96be22038105c59edf0d4c6a0412d Mon Sep 17 00:00:00 2001 From: reeseo3o Date: Sat, 2 May 2026 09:11:54 +0900 Subject: [PATCH 438/526] week9: linked-list-cycle --- linked-list-cycle/reeseo3o.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 linked-list-cycle/reeseo3o.js diff --git a/linked-list-cycle/reeseo3o.js b/linked-list-cycle/reeseo3o.js new file mode 100644 index 0000000000..37a0bc2bda --- /dev/null +++ b/linked-list-cycle/reeseo3o.js @@ -0,0 +1,22 @@ +// Time Complexity: O(n) +// Space Complexity: O(1) + +const hasCycle = (head) => { + if (head === null || head.next === null) { + return false; + } + + let slow = head; + let fast = head.next; + + while (slow !== fast) { + if (fast === null || fast.next === null) { + return false; + } + slow = slow.next; + fast = fast.next.next; + } + + return true; +}; + From c121c855c84d0eb66f0b1b9a1ec68e635cc02204 Mon Sep 17 00:00:00 2001 From: reeseo3o Date: Sat, 2 May 2026 09:14:50 +0900 Subject: [PATCH 439/526] week9: pacific-atlantic-water-flow --- pacific-atlantic-water-flow/reeseo3o.js | 49 +++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 pacific-atlantic-water-flow/reeseo3o.js diff --git a/pacific-atlantic-water-flow/reeseo3o.js b/pacific-atlantic-water-flow/reeseo3o.js new file mode 100644 index 0000000000..4b2730b7ff --- /dev/null +++ b/pacific-atlantic-water-flow/reeseo3o.js @@ -0,0 +1,49 @@ +// Time Complexity: O(m * n) +// Space Complexity: O(m * n) + +const pacificAtlantic = (heights) => { + if (!heights?.length || !heights[0]?.length) { + return []; + } + + const m = heights.length; + const n = heights[0].length; + const pacific = Array.from({ length: m }, () => Array(n).fill(false)); + const atlantic = Array.from({ length: m }, () => Array(n).fill(false)); + const dirs = [ + [-1, 0], + [1, 0], + [0, -1], + [0, 1], + ]; + + const dfs = (visited, r, c) => { + visited[r][c] = true; + for (const [dr, dc] of dirs) { + const nr = r + dr; + const nc = c + dc; + if (nr < 0 || nr>= m || nc < 0 || nc>= n || visited[nr][nc]) continue; + if (heights[nr][nc] < heights[r][c]) continue; + dfs(visited, nr, nc); + } + }; + + for (let i = 0; i < m; i++) { + dfs(pacific, i, 0); + dfs(atlantic, i, n - 1); + } + for (let j = 0; j < n; j++) { + dfs(pacific, 0, j); + dfs(atlantic, m - 1, j); + } + + const result = []; + for (let r = 0; r < m; r++) { + for (let c = 0; c < n; c++) { + if (pacific[r][c] && atlantic[r][c]) { + result.push([r, c]); + } + } + } + return result; +}; From fb649e93c626fc9616073bb76b207c5977b9e343 Mon Sep 17 00:00:00 2001 From: hyerijung Date: Sat, 2 May 2026 09:27:02 +0900 Subject: [PATCH 440/526] pacific-atlantic-water-flow solution --- pacific-atlantic-water-flow/hyeri0903.java | 53 ++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 pacific-atlantic-water-flow/hyeri0903.java diff --git a/pacific-atlantic-water-flow/hyeri0903.java b/pacific-atlantic-water-flow/hyeri0903.java new file mode 100644 index 0000000000..0dbb2c3d32 --- /dev/null +++ b/pacific-atlantic-water-flow/hyeri0903.java @@ -0,0 +1,53 @@ +class Solution { + int[][] dirs = {{1,0}, {-1,0}, {0,1}, {0,-1}}; + + public List> pacificAtlantic(int[][] heights) { + /** + 1.2개의 ocean 모두로 도달할 수 있는 칸들을 찾는 문제 + 2.height 높은 곳 -> 낮은 곳으로 이동 + time, space: O(mn) + */ + int m = heights.length; + int n = heights[0].length; + boolean[][] pacific = new boolean[m][n]; + boolean[][] atlantic = new boolean[m][n]; + + List> answer = new ArrayList(); + + for(int i = 0; i < m; i++) { + dfs(i, 0, m, n, heights, pacific); + dfs(i, n-1, m, n, heights, atlantic); + } + for(int j = 0; j < n; j++) { + dfs(0, j, m, n, heights, pacific); + dfs(m-1, j, m, n, heights, atlantic); + } + + for(int i = 0; i < m; i++) { + for(int j = 0; j < n; j++) { + if(pacific[i][j] && atlantic[i][j]) { + answer.add(Arrays.asList(i,j)); + } + } + } + return answer; + } + + void dfs(int i, int j, int m, int n, int[][] heights, boolean[][] visited) { + if(i < 0 || i>= m || j < 0 || j>= n || visited[i][j]) { + return; + } + + visited[i][j] = true; + for(int[] d: dirs) { + int nexti = i + d[0]; + int nextj = j + d[1]; + + //범위 안 && 방문 안했고 && 높이 조건 만족하면 다음 루트 탐색 + if(nexti>= 0 && nexti < m && nextj>= 0 && nextj < n && !visited[nexti][nextj] && heights[nexti][nextj]>= heights[i][j]) { + dfs(nexti, nextj, m, n, heights, visited); + } + + } + } +} From 31dafab6aa001f9fa49e18e4b5cb790c6e104c50 Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: Sat, 2 May 2026 12:48:29 +0900 Subject: [PATCH 441/526] =?UTF-8?q?feat:=20set=EC=9D=84=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=9C=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- linked-list-cycle/gyeo-ri.py | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 linked-list-cycle/gyeo-ri.py diff --git a/linked-list-cycle/gyeo-ri.py b/linked-list-cycle/gyeo-ri.py new file mode 100644 index 0000000000..15b5052051 --- /dev/null +++ b/linked-list-cycle/gyeo-ri.py @@ -0,0 +1,52 @@ +# Definition for singly-linked list. +class ListNode: + def __init__(self, val=0, next=None): + self.val: int = val + self.next: ListNode | None = next + + +class Solution: + def hasCycle(self, head: ListNode | None) -> bool: + visited_nodes = set() + while head is not None: + if head in visited_nodes: + return True + + visited_nodes.add(head) + head = head.next + return False + + +if __name__ == "__main__": + test_cases = [ + ([3, 2, 0, -4], 1, True), + ([1, 2], 0, True), + ([1], -1, False), + ([], -1, False), + ] + + solution = Solution() + + for idx, (inp, pos, expected) in enumerate(test_cases, start=1): + head = None + nodes = [] + + for value in reversed(inp): + head = ListNode(value, head) + + curr = head + + while curr: + nodes.append(curr) + curr = curr.next + + if pos != -1 and nodes: + nodes[-1].next = nodes[pos] + + result = solution.hasCycle(head) + + assert ( + result == expected + ), f"Test Case {idx} Failed: Expected {expected}, Got {result}" + + print("All test cases passed.") From f4b279589e415afdc2838e7aaeb8c3351c84f16b Mon Sep 17 00:00:00 2001 From: gyeo-ri Date: Sat, 2 May 2026 13:34:15 +0900 Subject: [PATCH 442/526] =?UTF-8?q?feat:=20=ED=8F=AC=EC=9D=B8=ED=84=B0=20?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=EC=9D=98=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- linked-list-cycle/gyeo-ri.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/linked-list-cycle/gyeo-ri.py b/linked-list-cycle/gyeo-ri.py index 15b5052051..3dc2a4fcf1 100644 --- a/linked-list-cycle/gyeo-ri.py +++ b/linked-list-cycle/gyeo-ri.py @@ -1,3 +1,14 @@ +""" +[결과 요약] +# 시도한 로직 수: 2 + 1. Set을 사용하여 이전 노드를 저장하기(O(n) / O(n)) + - 메모리를 많이 사용함 + 2. 포인터를 사용하여 메모리 사용량 줄이기(O(n) / O(1) + - set 방식과 시간 복잡도(O(n))은 동일하나, 실제 성능은 개선됨 + - set은 이전 노드 비교를 위해 해시 탐색이 필요하여 상대적으로 성능 저하 +""" + + # Definition for singly-linked list. class ListNode: def __init__(self, val=0, next=None): @@ -7,13 +18,18 @@ def __init__(self, val=0, next=None): class Solution: def hasCycle(self, head: ListNode | None) -> bool: - visited_nodes = set() - while head is not None: - if head in visited_nodes: + node_1_step, node_2_steps = head, head + + # 1. 2 steps를 더 이상 탐색할 수 없을 때까지(node is None or node.next is None) 반복 + while node_2_steps is not None and node_2_steps.next is not None: + node_1_step = node_1_step.next + node_2_steps = node_2_steps.next.next + + # 2. 계속 돌렸을 때 node 1과 node 2가 만나면 순회가 있는 것 + # 일치 비교이므로 is 사용 + if node_1_step is node_2_steps: return True - visited_nodes.add(head) - head = head.next return False @@ -22,6 +38,7 @@ def hasCycle(self, head: ListNode | None) -> bool: ([3, 2, 0, -4], 1, True), ([1, 2], 0, True), ([1], -1, False), + ([1, 2], -1, False), ([], -1, False), ] From 17fedf211d8833fd2514390d0d169406e4da4f9c Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: Sun, 3 May 2026 23:39:10 +0900 Subject: [PATCH 443/526] =?UTF-8?q?9=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=205=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- linked-list-cycle/hwi-middle.cpp | 32 +++++++++ maximum-product-subarray/hwi-middle.cpp | 24 +++++++ minimum-window-substring/hwi-middle.cpp | 77 ++++++++++++++++++++ pacific-atlantic-water-flow/hwi-middle.cpp | 81 ++++++++++++++++++++++ sum-of-two-integers/hwi-middle.cpp | 30 ++++++++ 5 files changed, 244 insertions(+) create mode 100644 linked-list-cycle/hwi-middle.cpp create mode 100644 maximum-product-subarray/hwi-middle.cpp create mode 100644 minimum-window-substring/hwi-middle.cpp create mode 100644 pacific-atlantic-water-flow/hwi-middle.cpp create mode 100644 sum-of-two-integers/hwi-middle.cpp diff --git a/linked-list-cycle/hwi-middle.cpp b/linked-list-cycle/hwi-middle.cpp new file mode 100644 index 0000000000..2d21e79fb8 --- /dev/null +++ b/linked-list-cycle/hwi-middle.cpp @@ -0,0 +1,32 @@ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode(int x) : val(x), next(NULL) {} + * }; + */ +class Solution { +public: + bool hasCycle(ListNode *head) { + if (head == nullptr) + { + return false; + } + + unordered_set ns; + ListNode* cur = head; + while (cur->next != nullptr) + { + if (ns.contains(cur)) + { + return true; + } + + ns.insert(cur); + cur = cur->next; + } + + return false; + } +}; diff --git a/maximum-product-subarray/hwi-middle.cpp b/maximum-product-subarray/hwi-middle.cpp new file mode 100644 index 0000000000..4855084909 --- /dev/null +++ b/maximum-product-subarray/hwi-middle.cpp @@ -0,0 +1,24 @@ +class Solution { +public: + int maxProduct(vector& nums) { + if (nums.size() == 0) + { + return 0; + } + + int max_so_far = nums[0]; + int min_so_far = nums[0]; + int result = max_so_far; + + for (int i = 1; i < nums.size(); i++) + { + int curr = nums[i]; + int temp_max = max(curr, max(max_so_far * curr, min_so_far * curr)); + min_so_far = min(curr, min(max_so_far * curr, min_so_far * curr)); + max_so_far = temp_max; + result = max(max_so_far, result); + } + + return result; + } +}; diff --git a/minimum-window-substring/hwi-middle.cpp b/minimum-window-substring/hwi-middle.cpp new file mode 100644 index 0000000000..a1c37e7ac9 --- /dev/null +++ b/minimum-window-substring/hwi-middle.cpp @@ -0,0 +1,77 @@ +class Solution { +public: + string minWindow(string s, string t) { + if (s.empty() || t.empty()) + { + return ""; + } + + // t에서 각 문자가 등장한 횟수 + unordered_map dictT; + for (auto& c : t) + { + dictT[c]++; + } + + // t에 들어있는 문자의 종류 + // 즉, 윈도우 안에 있는 문자의 종류는 required개 이상이어야 함 + int required = dictT.size(); + + int l = 0; + int r = 0; + + // t에 있는 문자의 종류 중 현재 윈도우 내에서 필요한 만큼 채워진 문자의 수 + int formed = 0; + + // 윈도우에 각 문자가 등장한 횟수 + unordered_map windowCounts; + + // 윈도우 길이, 왼쪽 인덱스, 오른쪽 인덱스 + int ans[3] = { -1, 0, 0 }; + + while (r < s.length()) + { + // 오른쪽 포인터가 가리키는 문자를 윈도우에 추가 + char c = s[r]; + windowCounts[c]++; + + // t에서 등장한 횟수가 같다면 formed 증가 + if (dictT.contains(c) && windowCounts[c] == dictT[c]) + { + formed++; + } + + // 윈도우가 조건을 만족하는 동안 루프 + // 즉, 더 이상 조건을 만족하지 않을 때 까지 왼쪽 포인터를 이동하여 윈도우를 축소시켜봄 + while (l <= r && formed == required) + { + c = s[l]; + + // 현재까지 발견한 가장 작은 윈도우 정보를 저장 + if (ans[0] == -1 || r - l + 1 < ans[0]) + { + ans[0] = r - l + 1; + ans[1] = l; + ans[2] = r; + } + + // 왼쪽 포인터가 가리키는 문자를 윈도우에서 제거 + windowCounts[c]--; + + // 그 결과, 문자가 t에서 등장한 횟수를 충족하지 못하면 formed 감소 + if (dictT.contains(c) && windowCounts[c] < dictT[c]) + { + formed--; + } + + // 왼쪽 포인터 이동 + l++; + } + + // 축소해가며 탐색이 끝났으면 오른쪽 포인터를 이동 + r++; + } + + return ans[0] == -1 ? "" : s.substr(ans[1], ans[2] - ans[1] + 1); + } +}; diff --git a/pacific-atlantic-water-flow/hwi-middle.cpp b/pacific-atlantic-water-flow/hwi-middle.cpp new file mode 100644 index 0000000000..67c35f5360 --- /dev/null +++ b/pacific-atlantic-water-flow/hwi-middle.cpp @@ -0,0 +1,81 @@ +class Solution { +public: + vector> pacificAtlantic(vector>& heights) { + int r = heights.size(); + int c = heights[0].size(); + + vector> result; + if (r == 0 || c == 0) return result; + + vector> pacific(r, vector(c, false)); + vector> atlantic(r, vector(c, false)); + + queue> pacific_q; + queue> atlantic_q; + + for (int i = 0; i < r; ++i) + { + pacific_q.push({i, 0}); + pacific[i][0] = true; + + atlantic_q.push({i, c - 1}); + atlantic[i][c - 1] = true; + } + + for (int j = 0; j < c; ++j) + { + pacific_q.push({0, j}); + pacific[0][j] = true; + + atlantic_q.push({r - 1, j}); + atlantic[r - 1][j] = true; + } + + bfs(pacific_q, pacific, heights); + bfs(atlantic_q, atlantic, heights); + + for (int i = 0; i < r; ++i) + { + for (int j = 0; j < c; ++j) + { + if (pacific[i][j] && atlantic[i][j]) + { + result.push_back({i, j}); + } + } + } + + return result; + } + +private: + void bfs(queue>& q, vector>& visited, const vector>& heights) + { + int r = heights.size(); + int c = heights[0].size(); + + int dx[] = { 0, 1, 0, -1 }; + int dy[] = { 1, 0, -1, 0 }; + + while (!q.empty()) { + int x, y; + tie(x, y) = q.front(); + q.pop(); + + for (int dir = 0; dir < 4; ++dir) + { + int nx = x + dx[dir]; + int ny = y + dy[dir]; + + if (nx < 0 || nx>= r || ny < 0 || ny>= c) continue; + + if (visited[nx][ny]) continue; + + if (heights[nx][ny] < heights[x][y]) continue; + + visited[nx][ny] = true; + q.push({nx, ny}); + } + } + } +}; diff --git a/sum-of-two-integers/hwi-middle.cpp b/sum-of-two-integers/hwi-middle.cpp new file mode 100644 index 0000000000..72c83fa27f --- /dev/null +++ b/sum-of-two-integers/hwi-middle.cpp @@ -0,0 +1,30 @@ +class Solution { +public: + int getSum(int a, int b) { + int res = 0; + + bool carry = false; + for (int i = 0; i < 32; ++i) + { + int mask = 1 << i; + bool bitA = a & mask; + bool bitB = b & mask; + bool sum = adder(bitA, bitB, carry); + if (sum) + { + res |= mask; + } + } + + return res; + } + + bool adder(bool a, bool b, bool& inout_carry) + { + bool axorb = a ^ b; + bool sum = axorb ^ inout_carry; + bool aandb = a & b; + inout_carry = aandb | (axorb & inout_carry); + return sum; + } +}; From a9afd140eb96bde338bc532b18923ad39c7de49e Mon Sep 17 00:00:00 2001 From: hyerijung Date: Tue, 5 May 2026 12:50:23 +0900 Subject: [PATCH 444/526] init --- merge-k-sorted-lists/hyeri0903.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 merge-k-sorted-lists/hyeri0903.java diff --git a/merge-k-sorted-lists/hyeri0903.java b/merge-k-sorted-lists/hyeri0903.java new file mode 100644 index 0000000000..862683cb1a --- /dev/null +++ b/merge-k-sorted-lists/hyeri0903.java @@ -0,0 +1,15 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode mergeKLists(ListNode[] lists) { + +} From 7da059884acff2cbeb32f91517c7ffb11dfeaf33 Mon Sep 17 00:00:00 2001 From: hyerijung Date: Tue, 5 May 2026 13:03:52 +0900 Subject: [PATCH 445/526] merge-k-sorted-lists solutions --- merge-k-sorted-lists/hyeri0903.java | 39 ++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/merge-k-sorted-lists/hyeri0903.java b/merge-k-sorted-lists/hyeri0903.java index 862683cb1a..16f89091d5 100644 --- a/merge-k-sorted-lists/hyeri0903.java +++ b/merge-k-sorted-lists/hyeri0903.java @@ -11,5 +11,42 @@ */ class Solution { public ListNode mergeKLists(ListNode[] lists) { - + /** + 1.문제: ascending liknked list 를 모두 sorted list 로 머지해라. + 2.조건 + - k = list 길이, 최소 = 0, 최대 = 10^4 + - 원소값 0 이상, 500 이하 + 3.풀이 + - priority queue(min-heap): time = O(n log k), space = O(k) + - 각 list 를 min heap 에 넣고 하나씩 뽑아서 새 리스트에 연결. + - Heap 에 들어가고 나올때마다 O(log k), 총 노드 수 N = O(N logk) + - Heap 사용 -> space = k + */ + + if(lists == null || lists.length == 0) return null; + + PriorityQueue pq = new PriorityQueue(lists.length, (a, b) -> a.val - b.val); + + //all list의 첫 노드 넣기 + for(ListNode node: lists) { + if (node != null) { + pq.offer(node); + } + } + + //결과 리스트를 위한 더미 노드 + ListNode dummy = new ListNode(0); + ListNode curr = dummy; + + while(!pq.isEmpty()) { + ListNode node = pq.poll(); //최소값 pop + curr.next = node; //결과 리스트에 연결 + curr = curr.next; //포인터 이동 + //다음 노드를 heap에 insert + if(node.next != null) { + pq.offer(node.next); + } + } + return dummy.next; + } } From c40318f5fffc3ed7ee2fc5da94cadc6e3715edcc Mon Sep 17 00:00:00 2001 From: sangbeenmoon Date: Tue, 5 May 2026 18:44:28 +0900 Subject: [PATCH 446/526] solved invert-bin-tree. --- invert-binary-tree/sangbeenmoon.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 invert-binary-tree/sangbeenmoon.py diff --git a/invert-binary-tree/sangbeenmoon.py b/invert-binary-tree/sangbeenmoon.py new file mode 100644 index 0000000000..89bb915d52 --- /dev/null +++ b/invert-binary-tree/sangbeenmoon.py @@ -0,0 +1,21 @@ +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: + if not root: + return root + + + def go(cur: TreeNode) -> Optional[TreeNode]: + if not cur: + return cur + res = TreeNode(cur.val) + res.left = go(cur.right) + res.right = go(cur.left) + return res + + return go(root) From c6e1bcfbbe6581403fc23fa76eb82e1b709e2783 Mon Sep 17 00:00:00 2001 From: hyerijung Date: Wed, 6 May 2026 16:23:22 +0900 Subject: [PATCH 447/526] invert-binary-tree solution --- invert-binary-tree/hyeri0903.java | 49 +++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 invert-binary-tree/hyeri0903.java diff --git a/invert-binary-tree/hyeri0903.java b/invert-binary-tree/hyeri0903.java new file mode 100644 index 0000000000..b59d3c0cd6 --- /dev/null +++ b/invert-binary-tree/hyeri0903.java @@ -0,0 +1,49 @@ +/** + * 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 TreeNode invertTree(TreeNode root) { + /** + 1.문제: inverted binary tree 출력 + 2.constraints: node 개수 min = 0, max = 100 + 3.solution: left, right node swap + time complexity: O(n), space complexity: O(h) + */ + + if(root == null) { + return null; + } + + dfs(root); + + return root; + + } + + void dfs(TreeNode root) { + if(root == null) { + return; + } + //swap + TreeNode tmp = root.left; + root.left = root.right; + root.right = tmp; + + //left recursion + dfs(root.left); + //right recursion + dfs(root.right); + } +} From 307a0e348aff35fa307b9aeee3a16cf26041aba1 Mon Sep 17 00:00:00 2001 From: hyerijung Date: Wed, 6 May 2026 16:24:19 +0900 Subject: [PATCH 448/526] invert-binary-tree solution --- invert-binary-tree/hyeri0903.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/invert-binary-tree/hyeri0903.java b/invert-binary-tree/hyeri0903.java index b59d3c0cd6..5cef1b3e7e 100644 --- a/invert-binary-tree/hyeri0903.java +++ b/invert-binary-tree/hyeri0903.java @@ -19,7 +19,10 @@ public TreeNode invertTree(TreeNode root) { 1.문제: inverted binary tree 출력 2.constraints: node 개수 min = 0, max = 100 3.solution: left, right node swap - time complexity: O(n), space complexity: O(h) + time complexity: + - BST인 경우 best case : O(log n) + - skwed 인 경우 worst case: O(n) + - space complexity: O(h) */ if(root == null) { From 11d656ca8c59f50bc32f5c6d1a0b650ad64e1a97 Mon Sep 17 00:00:00 2001 From: hyerijung Date: Wed, 6 May 2026 16:41:59 +0900 Subject: [PATCH 449/526] search in rotated sorted array solution --- search-in-rotated-sorted-array/hyeri0903.java | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 search-in-rotated-sorted-array/hyeri0903.java diff --git a/search-in-rotated-sorted-array/hyeri0903.java b/search-in-rotated-sorted-array/hyeri0903.java new file mode 100644 index 0000000000..430cf359b5 --- /dev/null +++ b/search-in-rotated-sorted-array/hyeri0903.java @@ -0,0 +1,44 @@ +class Solution { + public int search(int[] nums, int target) { + /** + 1.prob: index k기준으로 left rotated 된 array 에서 target index return, 존재하지 않으면 -1 return + 2.constraints + - asc 정렬된 배열, 모두 unique 한 값 + - 반드시 O(log n) 으로 풀 것 + - num.length min=1, max = 5000 + 3.solution + - bruteforce, for문 -> time: O(n) + - binary search -> time: O(log n), space: O(1) + */ + + int n = nums.length; + int left = 0, right = n - 1; + + + while(left <= right) { + int mid = (left + right) / 2; + + //target 찾으면 index return + if(nums[mid] == target) { + return mid; + } + + if(nums[left] <= nums[mid]) { + //왼쪽이 정렬된 경우 + if(nums[left] <= target && target < nums[mid]) { + right = mid - 1; + } else { + left = mid + 1; + } + } else { + //오른쪽이 정렬된 경우 + if(nums[mid] < target && target <= nums[right]) { + left = mid + 1; + } else { + right = mid - 1; + } + } + } + return -1; + } +} From 77ccf0d13e61410c0f311ad14569f30bb6cb483d Mon Sep 17 00:00:00 2001 From: Ted Date: Wed, 6 May 2026 23:38:42 -0400 Subject: [PATCH 450/526] add solutions --- jump-game/tedkimdev.rs | 14 ++++++++++ search-in-rotated-sorted-array/tedkimdev.go | 29 +++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 jump-game/tedkimdev.rs create mode 100644 search-in-rotated-sorted-array/tedkimdev.go diff --git a/jump-game/tedkimdev.rs b/jump-game/tedkimdev.rs new file mode 100644 index 0000000000..0274c30d98 --- /dev/null +++ b/jump-game/tedkimdev.rs @@ -0,0 +1,14 @@ +// TC: O(n) +// SC: O(1) +impl Solution { + pub fn can_jump(nums: Vec) -> bool { + let mut last = nums.len() as i32 - 1; + + for i in (0..nums.len() as i32 - 1).rev() { + if i + nums[i as usize]>= last { + last = i; + } + } + last == 0 + } +} diff --git a/search-in-rotated-sorted-array/tedkimdev.go b/search-in-rotated-sorted-array/tedkimdev.go new file mode 100644 index 0000000000..671c2d1807 --- /dev/null +++ b/search-in-rotated-sorted-array/tedkimdev.go @@ -0,0 +1,29 @@ +// TC: O(log n) +// SC: O(1) +func search(nums []int, target int) int { + l, r := 0, len(nums)-1 + + for l <= r { + m := (l + r) / 2 + if nums[m] == target { + return m + } + + // left half is sorted + if nums[l] <= nums[m] { + if target>= nums[l] && target < nums[m] { + r = m - 1 + } else { + l = m + 1 + } + } else { + if target> nums[m] && target <= nums[r] { + l = m + 1 + } else { + r = m - 1 + } + } + } + + return -1 +} From ae0afda79ea65acbd149a701773c93086d7fc48e Mon Sep 17 00:00:00 2001 From: juhui Date: Thu, 7 May 2026 22:44:24 +0900 Subject: [PATCH 451/526] WEEK 10 Solutions --- invert-binary-tree/juhuj-jeong.java | 60 +++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 invert-binary-tree/juhuj-jeong.java diff --git a/invert-binary-tree/juhuj-jeong.java b/invert-binary-tree/juhuj-jeong.java new file mode 100644 index 0000000000..1ebb6c6fea --- /dev/null +++ b/invert-binary-tree/juhuj-jeong.java @@ -0,0 +1,60 @@ +/* +이전 풀이 + * 시간 복잡도: O(n) + * 공간 복잡도: O(n) + */ +public class Solution { + public TreeNode invertTree(TreeNode root) { + if (root == null) { + return null; + } + + Queue
queue = new LinkedList(); + queue.offer(root); + + while (!queue.isEmpty()) { + TreeNode cur = queue.poll(); + + TreeNode temp = cur.left; + cur.left = cur.right; + cur.right = temp; + + if (cur.left != null) { + queue.offer(cur.left); + } + + if (cur.right != null) { + queue.offer(cur.right); + } + } + + return root; + } +} + +/** + * 시간 복잡도: O(n) + * 공간 복잡도: O(n) + * DFS 풀이 + */ +class Solution { + public TreeNode invertTree(TreeNode root) { + if (root == null) return null; + + Deque
stack = new ArrayDeque(); + stack.push(root); + + while(!stack.isEmpty()) { + TreeNode cur = stack.pop(); + + TreeNode temp = cur.left; + cur.left = cur.right; + cur.right = temp; + + if (cur.left != null) stack.push(cur.left); + + if (cur.right != null) stack.push(cur.right); + } + return root; + } +} From 186e0bba33598ee67373e49e1d4df2fa91533f72 Mon Sep 17 00:00:00 2001 From: juhui Date: Thu, 7 May 2026 22:51:11 +0900 Subject: [PATCH 452/526] fix: WEEK 10 Solutions --- invert-binary-tree/juhui-jeong.java | 32 ++++++++++++++- invert-binary-tree/juhuj-jeong.java | 60 ----------------------------- 2 files changed, 30 insertions(+), 62 deletions(-) delete mode 100644 invert-binary-tree/juhuj-jeong.java diff --git a/invert-binary-tree/juhui-jeong.java b/invert-binary-tree/juhui-jeong.java index d03d60a5f1..1ebb6c6fea 100644 --- a/invert-binary-tree/juhui-jeong.java +++ b/invert-binary-tree/juhui-jeong.java @@ -1,6 +1,7 @@ /* - * 시간 복잡도: O(1) - * 공간 복잡도: O(1) +이전 풀이 + * 시간 복잡도: O(n) + * 공간 복잡도: O(n) */ public class Solution { public TreeNode invertTree(TreeNode root) { @@ -30,3 +31,30 @@ public TreeNode invertTree(TreeNode root) { return root; } } + +/** + * 시간 복잡도: O(n) + * 공간 복잡도: O(n) + * DFS 풀이 + */ +class Solution { + public TreeNode invertTree(TreeNode root) { + if (root == null) return null; + + Deque
stack = new ArrayDeque(); + stack.push(root); + + while(!stack.isEmpty()) { + TreeNode cur = stack.pop(); + + TreeNode temp = cur.left; + cur.left = cur.right; + cur.right = temp; + + if (cur.left != null) stack.push(cur.left); + + if (cur.right != null) stack.push(cur.right); + } + return root; + } +} diff --git a/invert-binary-tree/juhuj-jeong.java b/invert-binary-tree/juhuj-jeong.java deleted file mode 100644 index 1ebb6c6fea..0000000000 --- a/invert-binary-tree/juhuj-jeong.java +++ /dev/null @@ -1,60 +0,0 @@ -/* -이전 풀이 - * 시간 복잡도: O(n) - * 공간 복잡도: O(n) - */ -public class Solution { - public TreeNode invertTree(TreeNode root) { - if (root == null) { - return null; - } - - Queue
queue = new LinkedList(); - queue.offer(root); - - while (!queue.isEmpty()) { - TreeNode cur = queue.poll(); - - TreeNode temp = cur.left; - cur.left = cur.right; - cur.right = temp; - - if (cur.left != null) { - queue.offer(cur.left); - } - - if (cur.right != null) { - queue.offer(cur.right); - } - } - - return root; - } -} - -/** - * 시간 복잡도: O(n) - * 공간 복잡도: O(n) - * DFS 풀이 - */ -class Solution { - public TreeNode invertTree(TreeNode root) { - if (root == null) return null; - - Deque
stack = new ArrayDeque(); - stack.push(root); - - while(!stack.isEmpty()) { - TreeNode cur = stack.pop(); - - TreeNode temp = cur.left; - cur.left = cur.right; - cur.right = temp; - - if (cur.left != null) stack.push(cur.left); - - if (cur.right != null) stack.push(cur.right); - } - return root; - } -} From d37b85d19e171de8cc74fb7023bbb9b060fae629 Mon Sep 17 00:00:00 2001 From: Dale Seo <5466341+daleseo@users.noreply.github.com> Date: Thu, 7 May 2026 19:58:23 -0400 Subject: [PATCH 453/526] search-in-rotated-sorted-array --- search-in-rotated-sorted-array/DaleSeo.rs | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 search-in-rotated-sorted-array/DaleSeo.rs diff --git a/search-in-rotated-sorted-array/DaleSeo.rs b/search-in-rotated-sorted-array/DaleSeo.rs new file mode 100644 index 0000000000..f3e32f42dd --- /dev/null +++ b/search-in-rotated-sorted-array/DaleSeo.rs @@ -0,0 +1,33 @@ +// TC: O(log n) +// SC: O(1) +impl Solution { + pub fn search(nums: Vec, target: i32) -> i32 { + let mut low = 0i32; + let mut high = nums.len() as i32 - 1; + + while low <= high { + let mid = low + (high - low) / 2; + let mid_val = nums[mid as usize]; + + if mid_val == target { + return mid; + } + + if nums[low as usize] <= mid_val { + if nums[low as usize] <= target && target < mid_val { + high = mid - 1; + } else { + low = mid + 1; + } + } else { + if mid_val < target && target <= nums[high as usize] { + low = mid + 1; + } else { + high = mid - 1; + } + } + } + + -1 + } +} From 0d6f0016463a3cdc2795e46d02fda57577ea463a Mon Sep 17 00:00:00 2001 From: jamiebase <100mgml@gmail.com> Date: Fri, 8 May 2026 15:24:36 +0900 Subject: [PATCH 454/526] Add invert binary tree solution with approach and complexity analysis --- invert-binary-tree/jamiebase.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 invert-binary-tree/jamiebase.py diff --git a/invert-binary-tree/jamiebase.py b/invert-binary-tree/jamiebase.py new file mode 100644 index 0000000000..4062069366 --- /dev/null +++ b/invert-binary-tree/jamiebase.py @@ -0,0 +1,20 @@ +""" +# Approach +노드를 방문하면서 왼쪽 자식, 오른쪽 자식을 서로 교체합니다. +이 과정을 왼쪽/오른쪽 서브트리에 재귀적으로 반복합니다. + +# Complexity +- Time complexity: 모든 노드를 다 방문해야 하기 때문에 O(N) +- Space complexity: 재귀 호출 스택이 트리 높이만큼 쌓일 수 있기 때문에 O(H) +""" + + +class Solution: + def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: + if not root: + return None + + root.left, root.right = root.right, root.left + self.invertTree(root.left) + self.invertTree(root.right) + return root From 86799f1e9d4de28968cc07e63dcaef1c3063a8fc Mon Sep 17 00:00:00 2001 From: gyeo-ri <69285868+gyeo-ri@users.noreply.github.com> Date: Fri, 8 May 2026 16:33:10 +0900 Subject: [PATCH 455/526] 207. Cource Schedule (#10) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 테스트 코드 작성 * feat: 위상정렬 풀이 * fix: 불필요한 코드 제거 * feat: dfs를 활용한 풀이 * fix: 결과 설명 추가 * fix: dfs 코드 가독성 개선 --- course-schedule/gyeo-ri.py | 113 +++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 course-schedule/gyeo-ri.py diff --git a/course-schedule/gyeo-ri.py b/course-schedule/gyeo-ri.py new file mode 100644 index 0000000000..f274c83f89 --- /dev/null +++ b/course-schedule/gyeo-ri.py @@ -0,0 +1,113 @@ +""" +[결과 요약] +# 시도한 로직 수: 2 + 1. 위상 정렬로 푸는 방법 + - 시간복잡도 O(n) / 공간복잡도 O(n) + - 실제로는 numCourses + len(prerequisites) 만큼의 복잡도 (O(V+E)) + - 원리: 모든 노드를 정렬할 수 있는지 체크(순환이 있으면 모든 노드 정렬 불가) + 2. DFS를 활용하는 방법 + - 1번과 동일하게 O(V+E) + - 원리: 탐색(비순환일때만 가능)을 완료할 수 있는지 체크해서 순환 여부를 판단 + +""" + + +class Solution: + def canFinish(self, numCourses: int, prerequisites: list[list[int]]) -> bool: + # 3. DFS 함수 정의 + def dfs(current: int) -> bool: + match course_states[current]: + case 2: # 탐색 완료 + return True + case 1: # 탐색 중 + return False + case 0: # 탐색 전 + course_states[current] = 1 + for next_ in course_graph[current]: + if not dfs(next_): + return False + + course_states[current] = 2 + return True + + # 1. 인덱스가 0부터 시작하는 그래프 초기화 + course_graph: list[list[int]] = [[] for _ in range(numCourses)] + for after, before in prerequisites: + course_graph[before].append(after) + + # 2. 각 노드별 탐색 상태를 표시하는 객체 + course_states: list[int] = [0] * numCourses + + # 3. 모든 노드를 1회씩 순회하면서 dfs + for course in range(numCourses): + if not dfs(course): + return False + return True + + +""" +# 위상정렬 +from collections import deque + +class Solution: + def canFinish(self, numCourses: int, prerequisites: list[list[int]]) -> bool: + # 1-a. 인덱스가 0부터 시작하는 그래프 초기화 + course_graph: list[list[int]] = [[] for _ in range(numCourses)] + + # 1-b. 각 노드별 선행 조건 갯수 리스트 + required_courses: list[int] = [0] * numCourses + + # 2. 선수과목을 돌면서 그래프를 채우기 + # Prerequisite이 [A, B]이면 A(After)를 수강하기 전에 B(Before)가 필요 + for after, before in prerequisites: + course_graph[before].append(after) + required_courses[after] += 1 + + # 3. 현재 수강 가능한 강의 체크 + available_courses = deque() + for i in range(numCourses): + if required_courses[i] == 0: + available_courses.append(i) + + # 4. queue가 빌 때까지 + done = 0 + while available_courses: + + # 수강 가능한 강의를 하나 꺼내서 수강 처리 + current = available_courses.popleft() + done += 1 + + # 이 강의의 선행 강의 찾기 + for next_ in course_graph[current]: + required_courses[next_] -= 1 + + if required_courses[next_] == 0: + available_courses.append(next_) + + return done == numCourses +""" + + +if __name__ == "__main__": + + test_cases = [ + (2, [[1, 0]], True), + (2, [[1, 0], [0, 1]], False), + (3, [], True), + (4, [[1, 0], [2, 1], [3, 2]], True), + (5, [[1, 0], [2, 0], [3, 1], [3, 2], [4, 3]], True), + (1, [[0, 0]], False), + (4, [[1, 0], [2, 1], [3, 2], [1, 3]], False), + ] + + solution = Solution() + + for idx, (numCourses, prerequisites, expected) in enumerate(test_cases, start=1): + + result = solution.canFinish(numCourses, prerequisites) + + assert ( + result == expected + ), f"Test Case {idx} Failed: Expected {expected}, Got {result}" + + print("All test cases passed.") From 4ee032a009f60ea6cd87cc57fea4875a53581cc6 Mon Sep 17 00:00:00 2001 From: gyeo-ri <69285868+gyeo-ri@users.noreply.github.com> Date: Fri, 8 May 2026 17:24:26 +0900 Subject: [PATCH 456/526] 226. Invert Binary Tree (#11) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 테스트 코드 작성 * feat: dfs를 활용한 풀이 * fix: 노드 교환 로직 가독성 개선 * docs: dfs 풀이 과정 리뷰 * feat: bfs를 활용한 풀이 * fix: 노드가 None인 경우 큐에 넣기 전에 처리함 * docs: 3번 풀이 코멘트 추가 --- invert-binary-tree/gyeo-ri.py | 132 ++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 invert-binary-tree/gyeo-ri.py diff --git a/invert-binary-tree/gyeo-ri.py b/invert-binary-tree/gyeo-ri.py new file mode 100644 index 0000000000..4c8b85a499 --- /dev/null +++ b/invert-binary-tree/gyeo-ri.py @@ -0,0 +1,132 @@ +""" +[결과 요약] +# 시도한 로직 수: 2 + 1. DFS를 활용하는 방법 + - 현재 노드의 좌우를 바꾼 다음 바로 아래 노드로 이동 + - 하위 노드가 없는 노드를 만날 때까지 반복되고 종료됨 + - 시간복잡도는 O(n) + - 공간복잡도는 O(n)이고, 트리가 균형이면 O(logn)까지 가능(B-Tree 같은 경우) + 2. BFS를 활용하는 방법 + - 시간복잡도/공간복잡도 모두 O(n) + - DFS와 성능 차이가 크게 없음 + 3. BFS에서 약간의 메모리 개선하기 + - None을 queue에 넣지 않는 방법 + - 트리 크기가 아주 크지 않다면 큰 효과는 없음 +""" + +from collections import deque + + +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution: + def invertTree(self, root: TreeNode | None) -> TreeNode | None: + if not root: + return root + + next_nodes: deque[TreeNode] = deque([root]) + + while next_nodes: + current = next_nodes.popleft() + if not current: + continue + + current.left, current.right = current.right, current.left + + if current.left: + next_nodes.append(current.left) + if current.right: + next_nodes.append(current.right) + + return root + + +""" +# DFS를 활용한 방법 +class Solution: + def invertTree(self, root: TreeNode | None) -> TreeNode | None: + def dfs(current: TreeNode | None): + if not current: + return + + current.left, current.right = current.right, current.left + + dfs(current.right) + dfs(current.left) + + dfs(root) + return root +""" + +if __name__ == "__main__": + from collections import deque + + def _build_tree(values: list[int | None]) -> TreeNode | None: + if not values: + return None + + nodes = [TreeNode(value) if value is not None else None for value in values] + + child_idx = 1 + + for node in nodes: + if node is not None: + if child_idx < len(nodes): + node.left = nodes[child_idx] + child_idx += 1 + + if child_idx < len(nodes): + node.right = nodes[child_idx] + child_idx += 1 + + return nodes[0] + + def _tree_to_list(root: TreeNode | None) -> list[int | None]: + if root is None: + return [] + + result = [] + queue = deque([root]) + + while queue: + node = queue.popleft() + + if node is None: + result.append(None) + continue + + result.append(node.val) + queue.append(node.left) + queue.append(node.right) + + while result and result[-1] is None: + result.pop() + + return result + + test_cases = [ + ([4, 2, 7, 1, 3, 6, 9], [4, 7, 2, 9, 6, 3, 1]), + ([2, 1, 3], [2, 3, 1]), + ([], []), + ([1], [1]), + ([1, 2], [1, None, 2]), + ] + + solution = Solution() + + for idx, (inp, expected) in enumerate(test_cases, start=1): + root = _build_tree(inp) + + result_root = solution.invertTree(root) + result = _tree_to_list(result_root) + + assert ( + result == expected + ), f"Test Case {idx} Failed: Expected {expected}, Got {result}" + + print("All test cases passed.") From 63241cf62a9388f22ec458be2f468448cb766369 Mon Sep 17 00:00:00 2001 From: hyerijung Date: Fri, 8 May 2026 20:04:54 +0900 Subject: [PATCH 457/526] jump game solution --- jump-game/hyeri0903.java | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 jump-game/hyeri0903.java diff --git a/jump-game/hyeri0903.java b/jump-game/hyeri0903.java new file mode 100644 index 0000000000..628c2fa006 --- /dev/null +++ b/jump-game/hyeri0903.java @@ -0,0 +1,26 @@ +class Solution { + public boolean canJump(int[] nums) { + /** + 1.문제: last index 에 도달 가능하면 true, 아니면 false return + 2.constraints + - first index 에서 시작 + - nums.length min = 1, max = 10000 + - value min = 0, max = 100000 + 3.solution + - brute force: 0 index 부터 1, 2, 3번째 등등 시도, time: O(n^2) + - 가장 먼 index 을 업데이트하면서 체크 : time O(n) + */ + int n = nums.length; + int farthest = 0; + + for(int i = 0; i < n; i++) { + //현재까지 도달 가능한지 체크 + if(i> farthest) { + return false; + } + //도달가능한 가장 먼 인덱스 update + farthest = Math.max(farthest, i + nums[i]); + } + return true; + } +} From 9e561e28ad6e75fee511fd1ebc61a14e8f89cb87 Mon Sep 17 00:00:00 2001 From: hyerijung Date: Fri, 8 May 2026 20:40:29 +0900 Subject: [PATCH 458/526] course schedule solution --- course-schedule/hyeri0903.java | 56 ++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 course-schedule/hyeri0903.java diff --git a/course-schedule/hyeri0903.java b/course-schedule/hyeri0903.java new file mode 100644 index 0000000000..1b179b45ca --- /dev/null +++ b/course-schedule/hyeri0903.java @@ -0,0 +1,56 @@ +class Solution { + public boolean canFinish(int numCourses, int[][] prerequisites) { + /** + 1.문제: [a, b] = b를 수강해야 a 수강 가능, 모두 수강가능하면 true, 아니면 flase return + 2.constraints + - numCourses min = 1, max = 2000 + - prerequisites length min = 0, max = 5000 + 3.solution + - dfs, graph에 cycle 이 존재하는지 check. cycle 이 존재하면 수강 다 못하므로 false return + */ + List> graph = new ArrayList(); + for(int i = 0; i < numCourses; i++) { + graph.add(new ArrayList()); + } + + //graph 생성 + for(int i = 0; i < prerequisites.length; i++) { + int a = prerequisites[i][0]; + int b = prerequisites[i][1]; + + graph.get(b).add(a); + } + + //dfs cycle check + //state: 0 = 방문 전, 1 = 방문 중, 2 = 방문 완료 + int[] state = new int[numCourses]; + //node 개수(numCourses)만큼 순회 + for(int i = 0; i < numCourses; i++) { + //cycle 존재하면 false return + if(dfs(i, graph, state)) { + return false; + } + } + return true; + } + + + boolean dfs(int i, List> graph, int[] state) { + //순회 cycle 발견하면 true + if(state[i] == 1) { + return true; + } + if(state[i] == 2) { + return false; + } + state[i] = 1; + + for(int next: graph.get(i)) { + if(dfs(next, graph, state)) { + return true; + } + } + state[i] = 2; + return false; + } +} From f2868efa49390477bfef8ace37b14c2abad19082 Mon Sep 17 00:00:00 2001 From: juhui Date: Fri, 8 May 2026 22:30:51 +0900 Subject: [PATCH 459/526] add: WEEK 10 Solutions --- .../juhui-jeong.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 search-in-rotated-sorted-array/juhui-jeong.java diff --git a/search-in-rotated-sorted-array/juhui-jeong.java b/search-in-rotated-sorted-array/juhui-jeong.java new file mode 100644 index 0000000000..89bec9ca9a --- /dev/null +++ b/search-in-rotated-sorted-array/juhui-jeong.java @@ -0,0 +1,34 @@ +/** + * 시간 복잡도: O(log n) + * 공간 복잡도: O(1) + */ +class Solution { + public int search(int[] nums, int target) { + int low = 0; + int high = nums.length - 1; + + while (low <= high) { + int mid = (low + high) / 2; + + if (nums[mid] == target) { + return mid; + } + // 왼쪽 구간이 정렬된 경우 + if (nums[low] <= nums[mid]) { + if (nums[low] <= target && target < nums[mid]) { + high = mid - 1; + } else { + low = mid + 1; + } + // 오른쪽 구간이 정렬된 경우 + } else { + if (nums[mid] < target && target <= nums[high]) { + low = mid + 1; + } else { + high = mid - 1; + } + } + } + return -1; + } +} From 23bb64397f66ddc4a146a4b983f2964e1a4f445a Mon Sep 17 00:00:00 2001 From: reeseo3o Date: Fri, 8 May 2026 23:47:17 +0900 Subject: [PATCH 460/526] week10: invert-binary-tree --- invert-binary-tree/reeseo3o.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 invert-binary-tree/reeseo3o.js diff --git a/invert-binary-tree/reeseo3o.js b/invert-binary-tree/reeseo3o.js new file mode 100644 index 0000000000..037a4c50ac --- /dev/null +++ b/invert-binary-tree/reeseo3o.js @@ -0,0 +1,14 @@ +// Time Complexity: O(n) +// Space Complexity: O(n) + +const invertTree = (root) => { + if (!root) return null; + + const left = invertTree(root.left); + const right = invertTree(root.right); + + root.left = right; + root.right = left; + + return root; +}; From 9be3b9794e5ae8ac0cba03d5d91451cc1c11190b Mon Sep 17 00:00:00 2001 From: reeseo3o Date: Sat, 9 May 2026 00:04:10 +0900 Subject: [PATCH 461/526] week10: search-in-rotated-sorted-array --- search-in-rotated-sorted-array/reeseo3o.js | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 search-in-rotated-sorted-array/reeseo3o.js diff --git a/search-in-rotated-sorted-array/reeseo3o.js b/search-in-rotated-sorted-array/reeseo3o.js new file mode 100644 index 0000000000..3617ab9f0d --- /dev/null +++ b/search-in-rotated-sorted-array/reeseo3o.js @@ -0,0 +1,32 @@ +const searchRotated = (nums, target) => { + let left = 0; + let right = nums.length - 1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + + if (nums[mid] === target) return mid; + + const isLeftSorted = nums[left] <= nums[mid]; + + if (isLeftSorted) { + const inLeft = + nums[left] <= target && target < nums[mid]; + if (inLeft) { + right = mid - 1; + } else { + left = mid + 1; + } + } else { + const inRight = + nums[mid] < target && target <= nums[right]; + if (inRight) { + left = mid + 1; + } else { + right = mid - 1; + } + } + } + + return -1; +}; From 9d0d57a013782c5640498b144ade49d16e92586a Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Sat, 9 May 2026 01:31:41 +0900 Subject: [PATCH 462/526] [7th batch] week 4 - find minimum in rotated sorted array --- .../liza0525.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/find-minimum-in-rotated-sorted-array/liza0525.py b/find-minimum-in-rotated-sorted-array/liza0525.py index cc67e1adb8..fd74989f1e 100644 --- a/find-minimum-in-rotated-sorted-array/liza0525.py +++ b/find-minimum-in-rotated-sorted-array/liza0525.py @@ -63,3 +63,35 @@ def findMinBinarySearch(self, nums: List[int]) -> int: # # 파이썬의 내장함수인 min을 이용해도 문제 풀이 가능 # # https://wiki.python.org/moin/TimeComplexity애 의하면 min 함수도 O(n)임 # return min(nums) + + +# 7기 풀이 +# 시간 복잡도: O(log n) +# - binary search를 이용했기 때문에 최악의 경우는 log n +# 공간 복잡도: O(1) +# - 몇 가지 변수만 사용됨 +class Solution: + def findMin(self, nums: List[int]) -> int: + # 양 끝을 먼저 잡아준다 + left, right = 0, len(nums) - 1 + + # left보다 right가 클 때 계속 루프를 돈다 + # 이는 left와 right가 같아질 때까지 돈다는 말과 동일하다 + while left < right: + # 중간 index 계산 + mid = (left + right) // 2 + + if nums[mid]> nums[right]: + # 중간 index의 값이 오른쪽 index의 값보다 크다는 것은 + # 최소 값이 mid 기준 오른쪽 구역에 존재하기 때문에 left을 mid쪽으로 움직인다. + # mid의 값 자체는 최소값이 될 수 없기 때문에 left는 이보다 한 칸 옆으로 움직여야 함 + left = mid + 1 + else: + # 중간 index의 값이 오른쪽 index의 값보다 작다는 것은 + # 최소 값이 mid 기준 왼쪽 구역에 존재하기 때문에 right를 mid쪽으로 움직인다. + # mid의 값 자체는 최소값이 될 수 있기 때문에 right는 mid 값을 할당한다. + right = mid + + # left와 right가 같아질 때(최소값을 찾았을 때) 루프 탈출을 하기 때문에 + # nums[left] 또는 nums[right]를 반환 + return nums[left] From 1edf5d69eb490c071d473cdad73e807f2ef47f1d Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Sat, 9 May 2026 01:32:10 +0900 Subject: [PATCH 463/526] [7th batch] week 10 - course schedule --- course-schedule/liza0525.py | 48 +++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 course-schedule/liza0525.py diff --git a/course-schedule/liza0525.py b/course-schedule/liza0525.py new file mode 100644 index 0000000000..e8c9d68a33 --- /dev/null +++ b/course-schedule/liza0525.py @@ -0,0 +1,48 @@ +from collections import defaultdict + +# 7기 풀이 +# 시간 복잡도: O(V + E) +# - numCourses(V)와 prerequisites의 길이(E)에 비례 +# 공간 복잡도: O(V) +# - 각 과목의 상태를 계산하는 state와 prereq_map의 공간은 numCourses(V)에 비례 + +BEFORE_START = 0 +IN_PROGRESS = 1 +DONE = 2 +class Solution: + def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool: + # states: 각 과목의 상태 저장, index가 곧 과목을 나타냄 + states = [BEFORE_START] * numCourses + + # 선수과목(key) 당 다음 과목들(value) 정보 저장 + prereq_map = defaultdict(list) + + for next_course, pre_course in prerequisites: + prereq_map[pre_course].append(next_course) + + def dfs(course): + if states[course] != BEFORE_START: + # 이미 들었거나, 듣는 중이라면 더이상 탐색하지 않아도 됨 + return + + states[course] = IN_PROGRESS # 현재 과목을 듣는 중 상태로 변경 + + next_courses = prereq_map.get(course, []) # 다음 과목의 정보 가져오기 + + for next_course in next_courses: + # 다음 과목들도 모두 돌아본다 + if states[next_course] == IN_PROGRESS: + # 다음 과목을 듣고 있는 중이라면, 서로가 선수과목이 된다는 이야기(그래프의 사이클이 생김) + # 이 때는 더이상 탐색하지 않고 return한다. + return + # 다음 과목에 대한 탐색 + dfs(next_course) + + # 다음 과목들도 다 들었다고 하면 사이클이 없으므로 해당 과목도 들었음 상태로 변경 + states[course] = DONE + + + for course in range(numCourses): + dfs(course) + + return IN_PROGRESS not in states # 듣는 중 상태의 존재 여부를 return From 6e21b3b68aafc9dbffce8150b48cafdbd20abdb6 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Sat, 9 May 2026 01:32:37 +0900 Subject: [PATCH 464/526] [7th batch] week 10 - invert binary tree --- invert-binary-tree/liza0525.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 invert-binary-tree/liza0525.py diff --git a/invert-binary-tree/liza0525.py b/invert-binary-tree/liza0525.py new file mode 100644 index 0000000000..04293075ce --- /dev/null +++ b/invert-binary-tree/liza0525.py @@ -0,0 +1,20 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - 노드의 개수(n)만큼 시간 소요 +# 공간 복잡도: O(h) +# - 주어진 트리의 높이(h)만큼 재귀 스택 사용 +class Solution: + def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]: + def invert_binary_tree(node): + if not node: + return + + # 트리 탐색 시 right -> left 순서로 순회하도록 재귀 호출 + invert_binary_tree(node.right) + invert_binary_tree(node.left) + + # node의 right와 left를 서로 바꿔준다. + node.right, node.left = node.left, node.right + + invert_binary_tree(root) + return root From 3114a38ea76fb94215ea44a4133a01c794ad9fed Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Sat, 9 May 2026 01:32:49 +0900 Subject: [PATCH 465/526] [7th batch] week 10 - jump game --- jump-game/liza0525.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 jump-game/liza0525.py diff --git a/jump-game/liza0525.py b/jump-game/liza0525.py new file mode 100644 index 0000000000..ba5b9ac50e --- /dev/null +++ b/jump-game/liza0525.py @@ -0,0 +1,22 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - nums의 길이(n) 만큼 시간 소요 +# 공간 복잡도: O(1) +# - 변수(max_reach)만 사용 +class Solution: + def canJump(self, nums: List[int]) -> bool: + max_reach = 0 # 매 순간에 가장 멀리 갈 수 있는 index 저장 + + for i in range(len(nums)): + if i> max_reach: + # 현재의 인덱스가 max_reach보다 크면, 도달 자체를 할 수 없음을 의미 + # 따라서 False로 early return + return False + + # 기존의 max_reach와 i에서 최대로 갈 수 있는 거리를 계산한 값을 비교하여 + # 더 큰값으로 max_reach 업데이트 + max_reach = max(max_reach, i + nums[i]) + + # for문을 모두 돌았다는 것은 맨 끝 인덱스에 도달 가능하다는 것을 의미 + # True로 리턴한다. + return True From ac6842360a6755cb7810189ca244ced1b43ae503 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Sat, 9 May 2026 01:33:04 +0900 Subject: [PATCH 466/526] [7th batch] week 10 - merge k sorted lists --- merge-k-sorted-lists/liza0525.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 merge-k-sorted-lists/liza0525.py diff --git a/merge-k-sorted-lists/liza0525.py b/merge-k-sorted-lists/liza0525.py new file mode 100644 index 0000000000..1ebcb8f9e6 --- /dev/null +++ b/merge-k-sorted-lists/liza0525.py @@ -0,0 +1,32 @@ +import heapq + +# 7기 풀이 +# 시간 복잡도: O(n log k) +# - while문의 매 루프마다 최소힙 계산(리스트의 개수 k에 입각) * 전체 노드 수(n) 만큼 최대 시간복잡도 나옴 +# 공간 복잡도: O(k) +# - 리스트의 개수(k) 만큼의 heap 사이즈가 나옴 +class Solution: + def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]: + dummy = ListNode() + head = dummy # 초기 head를 dummy로 지정 + + heap = [] # 최소힙 계산을 위한 heap + + # 먼저 힙에 노드를 push + for i, node in enumerate(lists): + if node: + # heap push 기준은 node.val과 node가 위치한 index를 기준으로 + heapq.heappush(heap, (node.val, i, node)) + + # heap의 모든 노드를 pop할 때까지 while 루프 돌린다 + while heap: + _, i, node = heapq.heappop(heap) # 최소값이 들어있는 node를 pop + head.next = node # head의 next에 현재의 node를 저장 후 + head = head.next # head 다음 노드로 변경 + + if node.next: + # node에 next 노드가 있었다면 해당 노드의 val을 기준으로 heap에 push한다 + heapq.heappush(heap, (node.next.val, i, node.next)) + + # dummy 노드였으므로 next node를 return + return dummy.next From 565016363b5900f65deef293a72ebb046c88e716 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Sat, 9 May 2026 01:33:20 +0900 Subject: [PATCH 467/526] [7th batch] week 10 - search in rotated sorted array --- search-in-rotated-sorted-array/liza0525.py | 44 ++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/search-in-rotated-sorted-array/liza0525.py b/search-in-rotated-sorted-array/liza0525.py index 18fbf3f0d4..24031f06e9 100644 --- a/search-in-rotated-sorted-array/liza0525.py +++ b/search-in-rotated-sorted-array/liza0525.py @@ -1,3 +1,5 @@ +# NOTE: 문제 위치를 잘못 잡음 4주차 find-minimum-in-rotated-sorted-array로 옮겨감 +# 삭제는 추후에(이유: github 리뷰 시 diff가 생겨 리뷰가 불편해질 수 있음) # 7기 풀이 # 시간 복잡도: O(log n) # - binary search를 이용했기 때문에 최악의 경우는 log n @@ -28,3 +30,45 @@ def findMin(self, nums: List[int]) -> int: # left와 right가 같아질 때(최소값을 찾았을 때) 루프 탈출을 하기 때문에 # nums[left] 또는 nums[right]를 반환 return nums[left] + + +# 7기 풀이 +# 시간 복잡도: O(log n) +# - binary search를 하므로 nums의 길이(n)의 로그 값 만큼의 시간 소요 +# 공간 복잡도: O(1) +# - 변수 몇 개만 사용 +class Solution: + def search(self, nums: List[int], target: int) -> int: + left, right = 0, len(nums) - 1 # 양 끝을 left, right로 설정 + + while left <= right: + mid = (left + right) // 2 # 중간 값 설정 + + if target == nums[mid]: + # 중간 값이 곧 target값이면 중간 index를 return + return mid + elif nums[left] <= nums[mid]: + # left ~ mid 사이가 정렬이 되어 있다면, + # (비고: 문제 조건 상, sorted list에서 rotate한 상황이므로 + # left와 mid만 비교해도 내부는 sorted 되어 있음 + # 이는 right ~ mid 비교 때와 동일함) + if nums[left] <= target < nums[mid]: + # target이 오름차순이 되어 있는 구간에 있는지 확인 + # 맞다면 right를 변경 + right = mid - 1 + else: + # 오름차순 쪽이 아닌 곳에 있다면 rotate되어 순서가 뒤틀린 쪽에 있다는 의미라 + # left를 변경 + left = mid + 1 + elif nums[mid] <= nums[right]: + # mid ~ right 사이가 정렬이 되어 있다면, + # 마찬가지로 오름차순 구간에 target이 존재하는지 아닌지를 판별하여 + # left와 right를 조절한다 + if nums[mid] < target <= nums[right]: + left = mid + 1 + else: + right = mid - 1 + + # while문을 모두 돌았음에도 return이 안되었다는 것은 + # target을 찾지 못했다는 의미이므로 문제 조건에 따라 -1 리턴 + return -1 From 8bcdfa6afcd8e14f26629cb10d5dc3964daccd4b Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: Sat, 9 May 2026 16:18:20 +0900 Subject: [PATCH 468/526] invert binary tree solution --- invert-binary-tree/robinyoon-dev.js | 36 +++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 invert-binary-tree/robinyoon-dev.js diff --git a/invert-binary-tree/robinyoon-dev.js b/invert-binary-tree/robinyoon-dev.js new file mode 100644 index 0000000000..e386e65b8f --- /dev/null +++ b/invert-binary-tree/robinyoon-dev.js @@ -0,0 +1,36 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {TreeNode} + */ +var invertTree = function (root) { + + let node = root; + + let result = changeLeftAndRight(node); + + return result; + + function changeLeftAndRight(root) { + // 종료 조건 + if (root === null) return root; + + tempLeft = root.left; + tempRight = root.right; + + root.left = tempRight; + root.right = tempLeft; + + changeLeftAndRight(root.left); + changeLeftAndRight(root.right); + + return root; + } +}; From f4ab9ae815dc37759a6dab4df6d76869e6fb63bb Mon Sep 17 00:00:00 2001 From: Robin Yoon Date: Sat, 9 May 2026 19:41:55 +0900 Subject: [PATCH 469/526] search in rotated sorted array solution --- search-in-rotated-sorted-array/robinyoon-dev.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 search-in-rotated-sorted-array/robinyoon-dev.js diff --git a/search-in-rotated-sorted-array/robinyoon-dev.js b/search-in-rotated-sorted-array/robinyoon-dev.js new file mode 100644 index 0000000000..6c4cbc54c0 --- /dev/null +++ b/search-in-rotated-sorted-array/robinyoon-dev.js @@ -0,0 +1,16 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ +var search = function(nums, target) { + let targetIndex = -1; + + for(let i = 0; i < nums.length; i++){ + if(nums[i] === target){ + targetIndex = i; + break; + } + } + return targetIndex; +}; From 0efebc08cb7c126692ad640fdd42ace1c1224362 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年5月10日 14:13:25 +0900 Subject: [PATCH 470/526] missing numebr solutions --- missing-number/hyeri0903.java | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 missing-number/hyeri0903.java diff --git a/missing-number/hyeri0903.java b/missing-number/hyeri0903.java new file mode 100644 index 0000000000..14f7efa416 --- /dev/null +++ b/missing-number/hyeri0903.java @@ -0,0 +1,30 @@ +class Solution { + public int missingNumber(int[] nums) { + /** + 1.distinc number 로 이루어진 0~n 까지의 배열 중 missing number return + 2.constraints + - n 최소 = 1, 최대 = 10000 + - 배열길이 min=0, max=n + 3.solutions + - sorting 하고 for문으로 missing num check. time: O(n log n), space: O(1) + - 전체 sum - 실제 sum + */ + + Arrays.sort(nums); + int n = nums.length; + int answer = 0; + int i = 0; + + for(i = 0; i < n; i++) { + if(nums[i] != i) { + answer = i; + return answer; + } + } + if(i == n) { + answer = n; + return answer; + } + return answer; + } +} From ecef2db41cd73860ef42e94fd30b22f8d32bcde5 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年5月10日 19:10:47 +0900 Subject: [PATCH 471/526] =?UTF-8?q?10=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=205=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- course-schedule/hwi-middle.cpp | 64 +++++++++++++++++++ invert-binary-tree/hwi-middle.cpp | 26 ++++++++ jump-game/hwi-middle.cpp | 18 ++++++ merge-k-sorted-lists/hwi-middle.cpp | 58 +++++++++++++++++ search-in-rotated-sorted-array/hwi-middle.cpp | 38 +++++++++++ 5 files changed, 204 insertions(+) create mode 100644 course-schedule/hwi-middle.cpp create mode 100644 invert-binary-tree/hwi-middle.cpp create mode 100644 jump-game/hwi-middle.cpp create mode 100644 merge-k-sorted-lists/hwi-middle.cpp create mode 100644 search-in-rotated-sorted-array/hwi-middle.cpp diff --git a/course-schedule/hwi-middle.cpp b/course-schedule/hwi-middle.cpp new file mode 100644 index 0000000000..f921df1b79 --- /dev/null +++ b/course-schedule/hwi-middle.cpp @@ -0,0 +1,64 @@ +class Solution { +private: + enum class eVisitStatus + { + Unvisited, + Visiting, + Visited + }; + +public: + bool canFinish(int numCourses, vector>& prerequisites) { + vector> graph(numCourses); + + for (auto& p : prerequisites) + { + int course = p[0]; + int prerequisite = p[1]; + + graph[course].push_back(prerequisite); + } + + vector status(numCourses, eVisitStatus::Unvisited); + + for (int i = 0; i < numCourses; ++i) + { + if (status[i] == eVisitStatus::Unvisited) + { + if (!dfs(i, graph, status)) + { + return false; + } + } + } + + return true; + } + +private: + bool dfs(int course, vector>& graph, vector& status) + { + if (status[course] == eVisitStatus::Visiting) + { + return false; + } + + if (status[course] == eVisitStatus::Visited) + { + return true; + } + + status[course] = eVisitStatus::Visiting; + + for (int prerequisite : graph[course]) + { + if (!dfs(prerequisite, graph, status)) + { + return false; + } + } + + status[course] = eVisitStatus::Visited; + return true; + } +}; diff --git a/invert-binary-tree/hwi-middle.cpp b/invert-binary-tree/hwi-middle.cpp new file mode 100644 index 0000000000..aa37163f27 --- /dev/null +++ b/invert-binary-tree/hwi-middle.cpp @@ -0,0 +1,26 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + TreeNode* invertTree(TreeNode* root) { + if (root == nullptr || (root->left == nullptr && root->right == nullptr)) + { + return root; + } + + invertTree(root->left); + invertTree(root->right); + swap(root->left, root->right); + + return root; + } +}; diff --git a/jump-game/hwi-middle.cpp b/jump-game/hwi-middle.cpp new file mode 100644 index 0000000000..f9005dbe30 --- /dev/null +++ b/jump-game/hwi-middle.cpp @@ -0,0 +1,18 @@ +class Solution { +public: + bool canJump(vector& nums) { + int maxDist = 0; + + for (int i = 0; i < nums.size(); ++i) + { + if (maxDist < i) + { + return false; + } + + maxDist = max(maxDist, i + nums[i]); + } + + return true; + } +}; diff --git a/merge-k-sorted-lists/hwi-middle.cpp b/merge-k-sorted-lists/hwi-middle.cpp new file mode 100644 index 0000000000..40d4d2b4a7 --- /dev/null +++ b/merge-k-sorted-lists/hwi-middle.cpp @@ -0,0 +1,58 @@ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +private: + struct cmp + { + bool operator() (ListNode* a, ListNode* b) + { + return a->val> b->val; + } + }; + +public: + ListNode* mergeKLists(vector& lists) { + if (lists.empty()) + { + return nullptr; + } + + priority_queue, cmp> pq; + + for (ListNode* list: lists) + { + while (list != nullptr) + { + pq.push(list); + list = list->next; + } + } + + if (pq.empty()) + { + return nullptr; + } + + ListNode* res = pq.top(); + ListNode* prev = res; + while (!pq.empty()) + { + ListNode* n = pq.top(); + pq.pop(); + prev->next = n; + prev = n; + } + + prev->next = nullptr; + + return res; + } +}; diff --git a/search-in-rotated-sorted-array/hwi-middle.cpp b/search-in-rotated-sorted-array/hwi-middle.cpp new file mode 100644 index 0000000000..d9d9d4d8ed --- /dev/null +++ b/search-in-rotated-sorted-array/hwi-middle.cpp @@ -0,0 +1,38 @@ +class Solution { +public: + int search(vector& nums, int target) { + return searchImpl(nums, 0, nums.size() - 1, target); + } + +private: + int searchImpl(vector& nums, int start, int end, int target) + { + if (start> end) + { + return -1; + } + + int mid = (start + end) / 2; + if (nums[mid] == target) + { + return mid; + } + + if (nums[start] <= nums[mid]) + { + if (nums[start] <= target && nums[mid]>= target) + { + return searchImpl(nums, start, mid - 1, target); + } + + return searchImpl(nums, mid + 1, end, target); + } + + if (nums[mid] <= target && nums[end]>= target) + { + return searchImpl(nums, mid + 1, end, target); + } + + return searchImpl(nums, start, mid - 1, target); + } +}; From 739c4308c4bfb8c6fa53ba147bd39b06445f0d43 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年5月11日 15:44:12 +0900 Subject: [PATCH 472/526] merge intervlas solution --- merge-intervals/hyeri0903.java | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 merge-intervals/hyeri0903.java diff --git a/merge-intervals/hyeri0903.java b/merge-intervals/hyeri0903.java new file mode 100644 index 0000000000..e14d30afad --- /dev/null +++ b/merge-intervals/hyeri0903.java @@ -0,0 +1,40 @@ +class Solution { + public int[][] merge(int[][] intervals) { + /** + 1.prob: overlapping 되는 곳을 merge 해서 return + 2.constraints + - len(intervalse) min = 1, max= 10000 + - start, end value min = 0, max = 10000 + 3.solution + - sorting array -> merge overlapping values + time: O(n log n) + */ + + int n = intervals.length; + Arrays.sort(intervals, (a,b) -> Integer.compare(a[0], b[0])); + + List answer = new ArrayList(); + int start = intervals[0][0]; + int end = intervals[0][1]; + + for(int i = 1; i < n; i++) { + int nextStart = intervals[i][0]; + int nextEnd = intervals[i][1]; + + //overlap + if(end>= nextStart) { + end = Math.max(end, nextEnd); + } else { + answer.add(new int[]{start, end}); + + start = nextStart; + end = nextEnd; + + } + } + + //last intervals + answer.add(new int[]{start, end}); + return answer.toArray(new int[answer.size()][]); + } +} From 9aa3b020ec6665c6f337112e1be2096bf993d1e7 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年5月11日 16:47:08 +0900 Subject: [PATCH 473/526] [7th batch] week 11 - missing number --- missing-number/liza0525.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 missing-number/liza0525.py diff --git a/missing-number/liza0525.py b/missing-number/liza0525.py new file mode 100644 index 0000000000..b97a817e75 --- /dev/null +++ b/missing-number/liza0525.py @@ -0,0 +1,17 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - nums의 전체 합을 계산할 때 nums의 길이 만큼 시간 소요 +# 공간 복잡도: O(1) +# - 계산에 필요한 변수 몇 개만 사용 +class Solution: + def missingNumber(self, nums: List[int]) -> int: + # nums에서 빠진 값까지 함께 더했을 때의 값 + # 최소값(0) + 최대값(len(nums))을 2로 나눈 후, nums의 개수 + 1(0 포함)의 개수만큼 곱한 값 + # 등차수열의 전체 합 + all_sum_nums = int(len(nums) / 2 * (len(nums) + 1)) + + # nums 리스트의 전체 합 + sum_nums = sum(nums) + + # 두 값의 차이가 곧 누락된 값 + return all_sum_nums - sum_nums From 7088021725bfe0607cecdb0695bffdc1b62b4d8b Mon Sep 17 00:00:00 2001 From: Cyjin-jani Date: 2026年5月12日 23:56:58 +0900 Subject: [PATCH 474/526] add: missingNumber solution --- missing-number/Cyjin-jani.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 missing-number/Cyjin-jani.js diff --git a/missing-number/Cyjin-jani.js b/missing-number/Cyjin-jani.js new file mode 100644 index 0000000000..22e880ef10 --- /dev/null +++ b/missing-number/Cyjin-jani.js @@ -0,0 +1,29 @@ +/** + * + * SC: O(n) + * TC: O(n) + */ +const missingNumber = function (nums) { + const n = nums.length; + const range_min = 0; + const range_max = n; + const numsMap = new Set(); + + for (let num of nums) { + numsMap.add(num); + } + + for (let i = range_min; i <= range_max; i++) { + if (!numsMap.has(i)) return i; + } +}; + +// 위 풀이의 경우 공간복잡도가 O(1)이 되지 않음. +// 아래의 경우가 공간복잡도 O(1)이 되는 풀이. +// 가우스 합 공식 이용. n개의 숫자에서 0부터 n까지의 합에서 실제 배열의 합을 빼면 누락된 숫자가 나옴. +const missingNumber_v2 = function (nums) { + const n = nums.length; + const expectedSum = (n * (n + 1)) / 2; + const actualSum = nums.reduce((acc, num) => acc + num, 0); + return expectedSum - actualSum; +}; From d97ebe7ba677b356fc29dfdf3298d0a7b89da2cb Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年5月13日 20:22:08 +0900 Subject: [PATCH 475/526] [7th batch] week 11 - reorder list --- reorder-list/liza0525.py | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 reorder-list/liza0525.py diff --git a/reorder-list/liza0525.py b/reorder-list/liza0525.py new file mode 100644 index 0000000000..1e89d136d4 --- /dev/null +++ b/reorder-list/liza0525.py @@ -0,0 +1,43 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - head 리스트의 길이 만큼의 시간 복잡도가 든다. +# 공간 복잡도: O(1) +# - 변수 몇 개만 사용 +class Solution: + def reorderList(self, head: Optional[ListNode]) -> None: + """ + Do not return anything, modify head in-place instead. + """ + + # slow-fast를 이용해서 리스트의 중간 노드를 찾는다 + # fast는 두 칸, slow는 한 칸을 움직이며 fast가 끝 노드에 도달할 때까지 loop를 돌면 + # slow로 중간 노드 찾을 수 있다. + slow, fast = head, head + + while fast and fast.next: + slow = slow.next + fast = fast.next.next + + # 중간 노드부터 마지막 노드까지의 리스트를 reversing해준다. + # prev, curr로 노드 포인터를 잡아 리스트를 뒤집느다. + prev, curr = None, slow + + while curr: + next_ = curr.next + curr.next, prev = prev, curr + curr = next_ + + # 원본이었던 head와 prev(중간부터 뒤집은 리스트)를 번갈아 가며 붙여준다. + # head의 포인터는 first, prev의 포인터는 second로 지정 + first, second = head, prev + + # second의 리스트를 다 돌 때까지 노드를 서로 연결해주면 된다. + while second.next: + first_next = first.next + second_next = second.next + + first.next = second + second.next = first_next + + second = second_next + first = first_next From c5da7e79a7504553b70020d0f26ed08bf5e4dd22 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年5月13日 21:56:03 +0900 Subject: [PATCH 476/526] [7th batch] week 11 - graph valid tree --- graph-valid-tree/liza0525.py | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 graph-valid-tree/liza0525.py diff --git a/graph-valid-tree/liza0525.py b/graph-valid-tree/liza0525.py new file mode 100644 index 0000000000..8640732831 --- /dev/null +++ b/graph-valid-tree/liza0525.py @@ -0,0 +1,51 @@ +from collections import defaultdict + +# 7기 풀이 +# 시간 복잡도: O(V + E) +# - 노드 개수(V) 및 엣지의 개수(E)만큼 탐색하므로 이에 따라 시간이 걸림 +# 공간 복잡도: O(V + E) +# - visited 노드의 개수(V)만큼, node_map는 엣지의 개수(E)만큼 생성함 +# - 재귀 스택은 최대 V만큼 생김 +class Solution: + def validTree(self, n: int, edges: List[List[int]]) -> bool: + visited = [0 for _ in range(n)] + node_map = defaultdict(list) # 노드 연결 정보 저장할 mapper + + for node1, node2 in edges: + # 각 엣지는 방향이 없으므로 양방향 정보 저장 + node_map[node1].append(node2) + node_map[node2].append(node1) + + def check_is_not_cycle(prev_node, node): + if visited[node]: + # node를 이미 방문했다면 cycle이 있다는 의미이므로 tree가 아님 + # False를 return한다 + return False + + visited[node] = 1 # 현재 노드 방문 확인 + + next_nodes = node_map[node] + if not next_nodes: + # 더이상 방문할 것이 없다는 의미로 + # 해당 탐색은 cycle 없이 끝났다는 것을 의미 + return True + + for next_node in next_nodes: + if prev_node == next_node: + # 양방향 노드 특성 상 prev_node 노드가 다음 노드와 같을 수 있다 + # 이 때는 체크하지 않고 넘어간다 + continue + + if not check_is_not_cycle(node, next_node): + # 재귀 함수의 결과가 False이면 False로 전파 + return False + + # 함수 내의 모든 로직의 실행이 끝났다면 싸이클이 없다는 의미이므로 + # True를 return + return True + + is_not_cycle = check_is_not_cycle(None, 0) + + # 싸이클이 없더라도 연결이 되지 않은 노드는 방문을 하지 않을 수 있기 때문에 + # visited에 0이 있는지 같이 확인하여 valid tree 여부를 return + return 0 not in visited if is_not_cycle else False From 7d887cd0e65ca3ad3b4f35949e6b83298c786d12 Mon Sep 17 00:00:00 2001 From: Ted Date: 2026年5月13日 10:33:11 -0400 Subject: [PATCH 477/526] add missing number --- missing-number/tedkimdev.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 missing-number/tedkimdev.rs diff --git a/missing-number/tedkimdev.rs b/missing-number/tedkimdev.rs new file mode 100644 index 0000000000..a9193c27f4 --- /dev/null +++ b/missing-number/tedkimdev.rs @@ -0,0 +1,12 @@ +// TC: O(n) +// SC: O(1) +impl Solution { + pub fn missing_number(nums: Vec) -> i32 { + let n = nums.len() as i32; + let mut xor_result = n; + for i in 0..nums.len() { + xor_result ^= i as i32 ^ nums[i]; + } + xor_result + } +} From 88c5162a5f5cd75dee756ed8ad7590477f04aead Mon Sep 17 00:00:00 2001 From: jamiebase <100mgml@gmail.com> Date: 2026年5月14日 15:06:03 +0900 Subject: [PATCH 478/526] Add solution for finding the missing number in a list --- missing-number/jamiebase.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 missing-number/jamiebase.py diff --git a/missing-number/jamiebase.py b/missing-number/jamiebase.py new file mode 100644 index 0000000000..8b61899014 --- /dev/null +++ b/missing-number/jamiebase.py @@ -0,0 +1,17 @@ +""" +# Approach +nums 집합을 만들어 없는 숫자를 찾습니다. + +# Complexity +- Time complexity: nums 의 길이를 n이라고 할 때, O(n) +- Space complexity: O(n) +""" + + +class Solution: + def missingNumber(self, nums: list[int]) -> int: + nums_set = set(nums) + n = len(nums) + for i in range(0, n + 1): + if i not in nums_set: + return i From 05f4a4cbd16ccb8a72e7c08fcb20d9beed0d9b1b Mon Sep 17 00:00:00 2001 From: jamiebase <100mgml@gmail.com> Date: 2026年5月14日 15:50:06 +0900 Subject: [PATCH 479/526] Add merge intervals solution with approach and complexity analysis --- merge-intervals/jamiebase.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 merge-intervals/jamiebase.py diff --git a/merge-intervals/jamiebase.py b/merge-intervals/jamiebase.py new file mode 100644 index 0000000000..6486469dba --- /dev/null +++ b/merge-intervals/jamiebase.py @@ -0,0 +1,33 @@ +""" +# Approach +1. 현재 범위 & 비교 범위 변수 +2. 비교 범위의 start가 현재 범위의 end보다 같거나 작으면 merge 가능 +3. 최종 merge 범위를 현재 범위로 재갱신 & output 배열에 추가하는 방식 + +# Complexity +- Time complexity: intervals의 길이를 N, 정렬 때문에 O(N log N) +- Space complexity: output 배열이 최악의 경우 O(N) +""" + + +class Solution: + def merge(self, intervals: list[list[int]]) -> list[list[int]]: + if (n := len(intervals)) == 1: + return intervals + + intervals.sort(key=lambda x: x[0]) + output = [] + right = 1 + start, end = intervals[0] + + while right < n: + comp_start, comp_end = intervals[right] + if comp_start <= end: + end = max(comp_end, end) + else: + output.append([start, end]) + start, end = comp_start, comp_end + right += 1 + + output.append([start, end]) + return output From 0f17d56724e17ecb1b75891d1fd5e2604860e258 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年5月15日 11:39:01 +0900 Subject: [PATCH 480/526] [7th batch] week 11 - merge intervals --- merge-intervals/liza0525.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 merge-intervals/liza0525.py diff --git a/merge-intervals/liza0525.py b/merge-intervals/liza0525.py new file mode 100644 index 0000000000..5ed856ca3e --- /dev/null +++ b/merge-intervals/liza0525.py @@ -0,0 +1,31 @@ +# 7기 풀이 +# 시간 복잡도: O(n log n) +# - merge하는 로직은 intervals의 길이(n)만큼의 시간 소요 +# - intervals를 sorting하는 로직은 n log n 만큼의 시간 소요 +# 공간 복잡도: O(1) +# - 결과 리스트(res) 제외, 몇 개의 변수만 사용 +class Solution: + def merge(self, intervals: List[List[int]]) -> List[List[int]]: + # 먼저 intervals를 오름차순으로 sorting한다. + # 각 요소의 첫번째 값을 기준으로 + intervals.sort() + + i, j = 0, 1 + res = [] + + # intervals를 탐색하는 i가 그 길이보다 작을 때 loop를 돈다 + while i < len(intervals): + curr_start, curr_end = intervals[i] # 첫번째 머지 대상을 기준으로 + while j < len(intervals): # j번째 요소들을 계속 머지함(범위 머지가 가능한 한) + next_start, next_end = intervals[j] + if curr_start <= next_start <= curr_end: # 다음 요소의 첫번째 값이 현재 요소 범위 내에 있을 때 + curr_end = max(curr_end, next_end) # 더 큰 범위로 머지 + else: # 그렇지 않으면 이번 텀에서의 머지가 완료된 것이므로 loop 탈출 + break + j += 1 # 머지가 가능한 한 j를 계속 올려준다. + + res.append([curr_start, curr_end]) # 머지 완료된 구간은 res에 담고 + i = j # 이번 loop에서 사용했던 j가 다음 루프의 i가 되고 + j = i + 1 # j는 i의 다음 인덱스부터 다시 머지를 할 수 있도록 변경 + + return res From 9ad0665211ffb8452b02a30482d5721316ae0f06 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年5月15日 11:48:36 +0900 Subject: [PATCH 481/526] [7th batch] week 11 - binary tree maximum path sum --- binary-tree-maximum-path-sum/liza0525.py | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 binary-tree-maximum-path-sum/liza0525.py diff --git a/binary-tree-maximum-path-sum/liza0525.py b/binary-tree-maximum-path-sum/liza0525.py new file mode 100644 index 0000000000..bfe43020ef --- /dev/null +++ b/binary-tree-maximum-path-sum/liza0525.py @@ -0,0 +1,35 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - 트리 전체를 탐색이므로 전체 노드 개수(n) 만큼 시간 소요 +# 공간 복잡도: O(h) +# - 트리의 높이(h)만큼 재귀 스택 쌓임 +# - 최악의 경우(편향 트리) O(n), 평균적으로 O(log n) +class Solution: + def maxPathSum(self, root: Optional[TreeNode]) -> int: + self.res = root.val # 결과 변수를 클래스 멤버 변수로 지정 + + # 후위 탐색을 이용해서 문제를 풀면 된다 + def postorder(node): + if not node: # 노드가 None인 경우는 0을 리턴해준다 + return 0 + + # 자식 노드들 각각의 최대합을 먼저 계산한다. + # 자식들의 최대합이 음수인 경우는 현재 노드의 최대합 계산에 방해가 되므로 + # 0과 비교하여 더 큰 값을 저장하도록 한다 + left_total = max(postorder(node.left), 0) + right_total = max(postorder(node.right), 0) + + # 지금까지의 최대합(self.res)와 자식 노드 및 현재 노드 val의 합을 비교하여 + # 더 큰 값을 지금까지의 최대합으로 업데이트 한다. + # - 현재 노드가 root인 subtree의 값이 최대일 수 있기 때문에 + self.res = max( + self.res, + left_total + right_total + node.val + ) + + # 위로 올릴 때는 왼쪽 노드와 오른쪽 노드 최대합 중에 + # 더 큰 값을 현재 노드 value와 더해서 올려준다. + return max(left_total, right_total) + node.val + + postorder(root) + return self.res From ba870029b2dc4bad297baf58108460f729631513 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年5月15日 12:06:26 +0900 Subject: [PATCH 482/526] [7th batch] week 1 - top k frequent elements --- top-k-frequent-elements/liza0525.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 top-k-frequent-elements/liza0525.py diff --git a/top-k-frequent-elements/liza0525.py b/top-k-frequent-elements/liza0525.py new file mode 100644 index 0000000000..7b0342a538 --- /dev/null +++ b/top-k-frequent-elements/liza0525.py @@ -0,0 +1,23 @@ +from collections import defaultdict + +# 7기 풀이 +# 시간 복잡도: O(n log n) +# - sorting 로직으로 인해 n log n만큼(n: nums의 길이)의 시간 소요 +# 공간 복잡도: O(n) +# - nums 내에 distinct 요소의 개수만큼 count_map으로 공간 소요 +# - 최대 값: distinct요소 개수가 nums의 길이 값(n)과 동일할 때 +class Solution: + def topKFrequent(self, nums: List[int], k: int) -> List[int]: + count_map = defaultdict(int) + + # 각 요소(num)의 개수를 저장 + for num in nums: + count_map[num] += 1 + + # count 기준으로 내림차순 정렬한 수 k만큼 list를 잘라준다. + return [ + num for num, _ in sorted( + [(num, count) for num, count in count_map.items()], + key=lambda x: -x[1] + ) + ][:k] From db2fb7748219b00b122f2b710ec37fdbc2e11a9b Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年5月15日 23:01:00 +0900 Subject: [PATCH 483/526] =?UTF-8?q?11=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=203=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- graph-valid-tree/hwi-middle.cpp | 47 +++++++++++++++++++++++++++++++++ merge-intervals/hwi-middle.cpp | 39 +++++++++++++++++++++++++++ missing-number/hwi-middle.cpp | 15 +++++++++++ 3 files changed, 101 insertions(+) create mode 100644 graph-valid-tree/hwi-middle.cpp create mode 100644 merge-intervals/hwi-middle.cpp create mode 100644 missing-number/hwi-middle.cpp diff --git a/graph-valid-tree/hwi-middle.cpp b/graph-valid-tree/hwi-middle.cpp new file mode 100644 index 0000000000..a6d1c5b357 --- /dev/null +++ b/graph-valid-tree/hwi-middle.cpp @@ -0,0 +1,47 @@ +class Solution { +public: + bool validTree(int n, vector>& edges) { + vector> adj(n + 1); + vector vis(n + 1); + + for (vector& edge : edges) + { + adj[edge[0]].push_back(edge[1]); + adj[edge[1]].push_back(edge[0]); + } + + // BFS 수행 + int visited = 1; + queue> q; + q.push({0, -1}); + while (!q.empty()) + { + int cur; + int parent; + tie(cur, parent) = q.front(); + q.pop(); + + for (int n : adj[cur]) + { + // 자기가 왔던 노드면 넘어감 + if (n == parent) + { + continue; + } + + // 이미 방문한 노드면 유효하지 않음 + if (vis[n]) + { + return false; + } + + vis[n] = true; + visited++; + q.push({n, cur}); + } + } + + // BFS를 통해 전체 노드를 방문할 수 있었어야 함 + return visited == n; + } +}; diff --git a/merge-intervals/hwi-middle.cpp b/merge-intervals/hwi-middle.cpp new file mode 100644 index 0000000000..40d0b6e3b3 --- /dev/null +++ b/merge-intervals/hwi-middle.cpp @@ -0,0 +1,39 @@ +class Solution { +public: + vector> merge(vector>& intervals) { + // start 순으로 정렬 + sort(intervals.begin(), intervals.end(), + [](const vector& a, const vector& b) { + return a[0] < b[0]; + }); + + vector> res; + res.reserve(intervals.size()); + + int start = intervals[0][0]; + int end = intervals[0][1]; + + for (int i = 1; i < intervals.size(); ++i) + { + // 현재 구간의 end보다 start가 크다면 틈이 벌어진 것 + if (end < intervals[i][0]) + { + vector v = { start, end }; + res.push_back(v); + start = intervals[i][0]; + end = intervals[i][1]; + } + // 그렇지 아니면 합칠 수 있음 + else + { + start = min(start, intervals[i][0]); + end = max(end, intervals[i][1]); + } + } + + vector v = { start, end }; + res.push_back(v); + + return res; + } +}; diff --git a/missing-number/hwi-middle.cpp b/missing-number/hwi-middle.cpp new file mode 100644 index 0000000000..d49ccaf00a --- /dev/null +++ b/missing-number/hwi-middle.cpp @@ -0,0 +1,15 @@ +class Solution { +public: + int missingNumber(vector& nums) { + // 1부터 n까지 합을 구하고, 배열 요소들의 합을 빼서 빠진 수를 찾음 + int n = nums.size(); + int sum = (n * (n + 1)) / 2; + int acc = 0; + for (int num : nums) + { + acc += num; + } + + return sum - acc; + } +}; From fe2d14dab1dd3385cd73c5d2cbbd5dc941d681b0 Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年5月16日 11:12:11 +0900 Subject: [PATCH 484/526] week11: missing-number --- missing-number/reeseo3o.js | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 missing-number/reeseo3o.js diff --git a/missing-number/reeseo3o.js b/missing-number/reeseo3o.js new file mode 100644 index 0000000000..6f3a25cb41 --- /dev/null +++ b/missing-number/reeseo3o.js @@ -0,0 +1,6 @@ +const missingNumber = (nums) => { + const n = nums.length; + const total = (n * (n + 1)) / 2; // 가우스 공식 + const sum = nums.reduce((acc, cur) => acc + cur, 0); + return total - sum; +}; From 2829e94ea326f35bbd057c1e831c06d3035d6ea1 Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年5月16日 11:15:18 +0900 Subject: [PATCH 485/526] week11: reorder-list --- reorder-list/reeseo3o.js | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 reorder-list/reeseo3o.js diff --git a/reorder-list/reeseo3o.js b/reorder-list/reeseo3o.js new file mode 100644 index 0000000000..5c4f6e63be --- /dev/null +++ b/reorder-list/reeseo3o.js @@ -0,0 +1,42 @@ +// Time Complexity: O(n) +// Space Complexity: O(1) + +const reorderList = (head) => { + if (!head || !head.next || !head.next.next) return; + + // 1. 가운데 찾기 (slow는 앞쪽 리스트의 끝) + let slow = head; + let fast = head; + while (fast && fast.next) { + slow = slow.next; + fast = fast.next.next; + } + + // 2. 뒷부분 뒤집기 (slow.next ~ 끝) + let prev = null; + let curr = slow.next; + slow.next = null; // 앞부분과 뒷부분 분리 + + while (curr) { + const next = curr.next; + curr.next = prev; + prev = curr; + curr = next; + } + // prev: 뒤집힌 두 번째 리스트의 head + + // 3. 교차 머지 (head: 첫 번째, prev: 두 번째) + let first = head; + let second = prev; + + while (second) { + const nextFirst = first.next; + const nextSecond = second.next; + + first.next = second; + second.next = nextFirst; + + first = nextFirst; + second = nextSecond; + } + }; From 006bd9b916a82755e9df1c55f6e5d502983f95d8 Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年5月16日 11:15:41 +0900 Subject: [PATCH 486/526] week11: add ts, sc comments --- missing-number/reeseo3o.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/missing-number/reeseo3o.js b/missing-number/reeseo3o.js index 6f3a25cb41..a1f8d6a3c3 100644 --- a/missing-number/reeseo3o.js +++ b/missing-number/reeseo3o.js @@ -1,3 +1,6 @@ +// Time Complexity: O(n) +// Space Complexity: O(1) + const missingNumber = (nums) => { const n = nums.length; const total = (n * (n + 1)) / 2; // 가우스 공식 From 89a94a2eae23d685340148533220fc16eb4914d6 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年5月16日 14:48:29 +0900 Subject: [PATCH 487/526] =?UTF-8?q?11=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=201=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reorder-list/hwi-middle.cpp | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 reorder-list/hwi-middle.cpp diff --git a/reorder-list/hwi-middle.cpp b/reorder-list/hwi-middle.cpp new file mode 100644 index 0000000000..8a2674d0da --- /dev/null +++ b/reorder-list/hwi-middle.cpp @@ -0,0 +1,53 @@ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ + + // Editorial 코드 +class Solution { +public: + void reorderList(ListNode* head) { + if (head == nullptr) + { + return; + } + + ListNode* slow = head; + ListNode* fast = head; + while (fast != nullptr && fast->next != nullptr) + { + slow = slow->next; + fast = fast->next->next; + } + + ListNode* prev = nullptr; + ListNode* curr = slow; + ListNode* tmp; + while (curr != nullptr) + { + tmp = curr->next; + curr->next = prev; + prev = curr; + curr = tmp; + } + + + ListNode* first = head; + ListNode* second = prev; + while (second->next != nullptr) + { + tmp = first->next; + first->next = second; + first = tmp; + tmp = second->next; + second->next = first; + second = tmp; + } + } +}; From 11a86bd5a5ad67d7188220d8d2c5674db0ec2625 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年5月16日 16:43:58 +0900 Subject: [PATCH 488/526] =?UTF-8?q?11=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=201=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- binary-tree-maximum-path-sum/hwi-middle.cpp | 40 +++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 binary-tree-maximum-path-sum/hwi-middle.cpp diff --git a/binary-tree-maximum-path-sum/hwi-middle.cpp b/binary-tree-maximum-path-sum/hwi-middle.cpp new file mode 100644 index 0000000000..54180ebfee --- /dev/null +++ b/binary-tree-maximum-path-sum/hwi-middle.cpp @@ -0,0 +1,40 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + int maxPathSum(TreeNode* root) { + int ans = -1000; + impl(root, ans); + return ans; + } + +private: + int impl(TreeNode* root, int& ans) + { + if (root == nullptr) + { + return 0; + } + + // 왼쪽과 오른쪽 자식을 재귀적으로 순회 + int l = impl(root->left, ans); + int r = impl(root->right, ans); + int cur = root->val; + + // 최댓값 업데이트 + ans = max(ans, max(0, l) + max(0, r) + cur); + + // 부모에게 전달할 값 + // -> 재방문이 허용되지 않으므로 최댓값과는 다름 + return max(0, max(l, r) + cur); + } +}; From 86f9100cd3b2eaecf6ab7d7a9f67ce01e8ae1332 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年5月16日 17:15:04 +0900 Subject: [PATCH 489/526] reorder-list solution --- reorder-list/hyeri0903.java | 61 +++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 reorder-list/hyeri0903.java diff --git a/reorder-list/hyeri0903.java b/reorder-list/hyeri0903.java new file mode 100644 index 0000000000..756da52a1c --- /dev/null +++ b/reorder-list/hyeri0903.java @@ -0,0 +1,61 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public void reorderList(ListNode head) { + /** + 1.Reorder linekd list from 0, n, 1, n-1, ... + 2.solution: + - 중간을 반으로 쪼개고,앞/뒤 리스트를 번갈아가면서 연결 + - step 1) 중간 노드 찾기 + - step 2) 뒤 리스트 reverse + - step 3) 두 리스트 merge + time: O(n), space: O(1) + */ + + ListNode slow = head; + ListNode fast = head; + + while(fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + + ListNode second = slow.next; + slow.next = null; + + ListNode prev = null; + ListNode curr = second; + + //reverse second linked list + while(curr != null) { + ListNode next = curr.next; + curr.next = prev; + prev = curr; + curr = next; + } + + //merge two linked list + ListNode first = head; + LintNode secondHalf = prev; + + while(secondHalf != null) { + ListNode next1 = first.next; + ListNode next2 = secondHalf.next; + + next1.next = secondHalf + secondHalf.next = next1; + + first = next1; + secondHalf = next2; + } + + } +} From c966a4f953417b5a834f4769d6345abbf0cb7924 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年5月16日 17:48:56 +0900 Subject: [PATCH 490/526] binary-tree-maximum-path-sum solution --- binary-tree-maximum-path-sum/hyeri0903.java | 48 +++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 binary-tree-maximum-path-sum/hyeri0903.java diff --git a/binary-tree-maximum-path-sum/hyeri0903.java b/binary-tree-maximum-path-sum/hyeri0903.java new file mode 100644 index 0000000000..89ccae88f2 --- /dev/null +++ b/binary-tree-maximum-path-sum/hyeri0903.java @@ -0,0 +1,48 @@ +/** + * 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 { + int maxValue = Integer.MIN_VALUE; + + public int maxPathSum(TreeNode root) { + /** + 1.노드의 sum이 가장 최대가 되는 path 의 maximum sum 찾기 + 2.solution : DFS + */ + + dfs(root); + return maxValue; + + } + + private int dfs(TreeNode node) { + if(node == null) { + return 0; + } + + int left = Math.max(0, dfs(node.left)); + int right = Math.max(0, dfs(node.right)); + + //현재 노드를 중심으로하는 Path + int currPath = left + node.val + right; + + //update max value + maxValue = Math.max(maxValue, currPath); + + //부모 노드에게 최대값 전달 + return node.val + Math.max(left, right); + } + +} From ac7518041afbb213ff32cf467ac1e9a681b1fdd5 Mon Sep 17 00:00:00 2001 From: hyerijung Date: 2026年5月16日 18:17:20 +0900 Subject: [PATCH 491/526] graph-valid-tree solution --- graph-valid-tree/hyeri0903.java | 63 +++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 graph-valid-tree/hyeri0903.java diff --git a/graph-valid-tree/hyeri0903.java b/graph-valid-tree/hyeri0903.java new file mode 100644 index 0000000000..a2c659b551 --- /dev/null +++ b/graph-valid-tree/hyeri0903.java @@ -0,0 +1,63 @@ +public class Solution { + /** + * @param n: An integer + * @param edges: a list of undirected edges + * @return: true if it's a valid tree, or false + */ + public boolean validTree(int n, int[][] edges) { + /** + 1. n개의 노드 valid tree 검사 + 2. constraints + - no cycle + - all nodes are connected + 3. Solution: DFS + - 간선 개수 체크 + - 그래프 만들어서 cycle 없고 && 모두 방문했는지 체크 + 너모 어려워요... + */ + + //간선 개수 체크 + if(edges.length != n-1) { + return false; + } + + //그래프 만들기 + List> graph = new ArrayList(); + + for(int i = 0; i < n; i++) { + graph.add(new ArrayList()); + } + for(int[] edge: edges) { + int a = edge[0]; + int b = edge[1]; + graph.get(a).add(b); + graph.get(b).add(a); + } + //check through DFS + Set visited = new HashSet(); + + if(hasCycle(0, -1, graph, visited)) { + return false; + } + if(visited.size() != n) { + return false; + } + return true; + } + private boolean hasCycle(int node, int parent, List> graph, Set visited) { + //이미 방문했으면 cycle + if(visited.contains(node)) { + return true; + } + visited.add(node); + for(int neighbor: graph.get(node)) { + if(neighbor == parent) { + continue; + } + if(hasCycle(neighbor, node, graph, visited)) { + return true; + } + } + return false; + } +} From 8367540ff1c51a973f4399898669b822bcf57d22 Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年5月16日 22:08:52 +0900 Subject: [PATCH 492/526] style: improve code formatting --- reorder-list/reeseo3o.js | 76 ++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/reorder-list/reeseo3o.js b/reorder-list/reeseo3o.js index 5c4f6e63be..7ea721fba3 100644 --- a/reorder-list/reeseo3o.js +++ b/reorder-list/reeseo3o.js @@ -2,41 +2,41 @@ // Space Complexity: O(1) const reorderList = (head) => { - if (!head || !head.next || !head.next.next) return; - - // 1. 가운데 찾기 (slow는 앞쪽 리스트의 끝) - let slow = head; - let fast = head; - while (fast && fast.next) { - slow = slow.next; - fast = fast.next.next; - } - - // 2. 뒷부분 뒤집기 (slow.next ~ 끝) - let prev = null; - let curr = slow.next; - slow.next = null; // 앞부분과 뒷부분 분리 - - while (curr) { - const next = curr.next; - curr.next = prev; - prev = curr; - curr = next; - } - // prev: 뒤집힌 두 번째 리스트의 head - - // 3. 교차 머지 (head: 첫 번째, prev: 두 번째) - let first = head; - let second = prev; - - while (second) { - const nextFirst = first.next; - const nextSecond = second.next; - - first.next = second; - second.next = nextFirst; - - first = nextFirst; - second = nextSecond; - } - }; + if (!head || !head.next || !head.next.next) return; + + // 1. 가운데 찾기 (slow는 앞쪽 리스트의 끝) + let slow = head; + let fast = head; + while (fast && fast.next) { + slow = slow.next; + fast = fast.next.next; + } + + // 2. 뒷부분 뒤집기 (slow.next ~ 끝) + let prev = null; + let curr = slow.next; + slow.next = null; // 앞부분과 뒷부분 분리 + + while (curr) { + const next = curr.next; + curr.next = prev; + prev = curr; + curr = next; + } + // prev: 뒤집힌 두 번째 리스트의 head + + // 3. 교차 머지 (head: 첫 번째, prev: 두 번째) + let first = head; + let second = prev; + + while (second) { + const nextFirst = first.next; + const nextSecond = second.next; + + first.next = second; + second.next = nextFirst; + + first = nextFirst; + second = nextSecond; + } +}; From 5f820cc5a5792d546daa25b3569040a787cce983 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年5月17日 23:01:04 +0900 Subject: [PATCH 493/526] [7th batch] week 12 - same tree --- same-tree/liza0525.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 same-tree/liza0525.py diff --git a/same-tree/liza0525.py b/same-tree/liza0525.py new file mode 100644 index 0000000000..b442bdd6c6 --- /dev/null +++ b/same-tree/liza0525.py @@ -0,0 +1,36 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - 두 트리의 노드 개수가 동일할 때 모든 노드를 탐색하므로 O(n) +# - 다를 경우 early return으로 그보다 적게 탐색 +# 공간 복잡도: O(n) +# - stack에는 최대 트리의 너비(width)만큼 pair가 쌓임 +class Solution: + def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool: + stack = [(p, q)] # p와 q를 tuple의 형태로 stack에 저장 + + while stack: # stack의 요소가 다 없어질 때까지 트리 탐색 + p_node, q_node = stack.pop() # node 꺼내기 + + if not p_node and not q_node: + # 둘 다 없는 경우(null인 경우)는 leaf node로부터 온 것이기 때문에 + # 더이상 탐색을 안해도 됨 + continue + elif ( + not p_node and q_node + or p_node and not q_node + ): + # 둘 중 하나만 null인 경우에는 tree가 같지 않으므로 + # False로 early return + return False + elif p_node.val != q_node.val: + # 둘 다 있는데 값이 같지 않은 경우도 + # False로 early return + return False + + # 두 트리의 왼쪽 쌍과 오른쪽 쌍을 각각 stack에 저장 + stack.append((p_node.left, q_node.left)) + stack.append((p_node.right, q_node.right)) + + # 모든 loop를 다 돌았다면 두 트리가 같다는 의미로 + # True로 return + return True From 090916aa91b61391bf3f442f977ba8e68ccb1ed8 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年5月18日 23:49:21 +0900 Subject: [PATCH 494/526] [7th batch] week 12 - remove nth node from end of list --- remove-nth-node-from-end-of-list/liza0525.py | 30 ++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 remove-nth-node-from-end-of-list/liza0525.py diff --git a/remove-nth-node-from-end-of-list/liza0525.py b/remove-nth-node-from-end-of-list/liza0525.py new file mode 100644 index 0000000000..245979f127 --- /dev/null +++ b/remove-nth-node-from-end-of-list/liza0525.py @@ -0,0 +1,30 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - 마지막 노드까지, 모든 노드를 탐색해야 하므로 노드의 개수에 시간 복잡도가 정해짐 +# 공간 복잡도: O(n) +# - 재귀 스택이 노드의 개수만큼 쌓임 +class Solution: + def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]: + # dummy 노드와 next node 설정 및 curr_node로 포인터 지정 + dummy = ListNode() + dummy.next = head + curr_node = head + + def dfs(parent, node): + if not node: + # 끝에 도달했으므로 카운팅 시작점 0을 return + # 호출부에서 +1을 하면 마지막 노드가 1이 됨 + return 0 + + curr_i = dfs(node, node.next) + 1 + + # (뒤로부터 셌을 때의) 현재 노드의 순번이 주어진 n과 같을 때 + if curr_i == n: + # 부모 노드의 next 노드를, 현재 노드의 next 노드로 변경하여 + # 현재 노드의 연결을 끊는다. + parent.next = node.next + + return curr_i + + dfs(dummy, curr_node) + return dummy.next From 16987584867cf741c8fd33bbf5be0f81f72b861f Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年5月20日 16:23:58 +0900 Subject: [PATCH 495/526] [7th batch] week 12 - non overlappng intervals --- non-overlapping-intervals/liza0525.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 non-overlapping-intervals/liza0525.py diff --git a/non-overlapping-intervals/liza0525.py b/non-overlapping-intervals/liza0525.py new file mode 100644 index 0000000000..de6ed8d642 --- /dev/null +++ b/non-overlapping-intervals/liza0525.py @@ -0,0 +1,20 @@ +# 7기 풀이 +# 시간 복잡도: O(n log n) +# - sorting에 O(n log n), 이후 전체 탐색에 O(n) +# - 종합 O(n log n) +# 공간 복잡도: O(1) +# - 추가 자료구조 없이 변수만 사용 +class Solution: + def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int: + intervals.sort(key=lambda x: x[1]) # end 기준으로 구간들을 오름차순 + res = 0 + + prev_end = intervals[0][1] # 제일 첫번째 구간의 end를 prev_end로 저장 + + for curr_start, curr_end in intervals[1:]: # 1번 인덱스부터 loop + if curr_start < prev_end: # 이전 구간 end와 curr_start 구간이 겹칠 때 + res += 1 # res를 하나 올린다 + else: # 겹치지 않는다면 + prev_end = curr_end # 지금 구간의 end를 다음 loop의 prev_end가 되도록 할당 + + return res From 8c6dfdf3aee1aafd79ca2fd2b4612155265adc03 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年5月22日 22:10:35 +0900 Subject: [PATCH 496/526] [7th batch] week 12 - serialize and deserialize binary tree --- .../liza0525.py | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 serialize-and-deserialize-binary-tree/liza0525.py diff --git a/serialize-and-deserialize-binary-tree/liza0525.py b/serialize-and-deserialize-binary-tree/liza0525.py new file mode 100644 index 0000000000..b258fd468e --- /dev/null +++ b/serialize-and-deserialize-binary-tree/liza0525.py @@ -0,0 +1,56 @@ +from collections import deque + +# 7기 풀이 +# 시간 복잡도: O(n) +# - 모든 노드를 순회하여 serialize / deserialize 하므로 노드의 개수만큼 시간 소요 +# 공간 복잡도: O(n) +# - 모든 노드에 대한 값을 list에 넣어 사용하므로 노드의 개수만큼 공간 사용 +class Codec: + DELIMITER = "$" # serialize할 때 노드의 값을 구분하기 위한 구분자 + NONE_VALUE = "N" # serialize할 때 노드가 None인 경우를 구분하기 위한 구분자 + + def serialize(self, root): + """Encodes a tree to a single string. + + :type root: TreeNode + :rtype: str + """ + data = [] # node의 값들을 저장할 list 추가 + + def dfs(node): + if not node: + # node가 None인 경우에는 None 구분자를 저장 + data.append(self.NONE_VALUE) + return + + data.append(str(node.val)) # node가 있는 경우에 val를 data에 저장 + + dfs(node.left) # 왼쪽 자식 노드 탐색 + dfs(node.right) # 오른쪽 자식 노드 탐색 + + dfs(root) # 전체 트리 탐색 + return f"{self.DELIMITER}".join(data) # 탐색하여 저장한 data list를 구분자를 이용해 string으로 변환하여 return + + def deserialize(self, data): + """Decodes your encoded data to tree. + + :type data: str + :rtype: TreeNode + """ + + data = deque(data.split(self.DELIMITER)) # string 값을 구분자를 기준으로 split 한 후 deque에 저장 + + def dfs(): + val = data.popleft() # data 값 중 가장 왼쪽에 있는 값을 pop + if val == self.NONE_VALUE: + # None 구분자의 값이 나온 경우에는 node가 없었던 것이므로 None 리턴 + return None + + node = TreeNode(val) # 노드 생성 + node.left = dfs() # 왼쪽 자식 노드 생성 + node.right = dfs() # 오른쪽 자식 노드 생성 + + return node # 완성한 노드 return + + root = dfs() + return root From 0ca92953fce870ff07e93f94e8cca9bdf50bf2a4 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: 2026年5月22日 23:37:19 +0900 Subject: [PATCH 497/526] [7th batch] week 12 - number of connected components in an undirected graph --- .../liza0525.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 number-of-connected-components-in-an-undirected-graph/liza0525.py diff --git a/number-of-connected-components-in-an-undirected-graph/liza0525.py b/number-of-connected-components-in-an-undirected-graph/liza0525.py new file mode 100644 index 0000000000..89002a15c3 --- /dev/null +++ b/number-of-connected-components-in-an-undirected-graph/liza0525.py @@ -0,0 +1,51 @@ +from typing import List +from collections import defaultdict, deque + + +# 7기 풀이 +# 시간 복잡도: O(V + E) +# - 모든 노드과 연결된 엣지를 탐색하면서 component 개수를 확인하므로 노드 개수(V)와 엣지 개수(E)만큼 시간 소요 +# 공간 복잡도: O(V + E) +# - 노드의 개수(V)와 엣지의 개수(E)만큼 mappers를 만드므로 V + E 만큼 공간 사용 +class Solution: + def count_components(self, n: int, edges: List[List[int]]) -> int: + res = 0 + mappers = defaultdict(list) + + for node1, node2 in edges: + # 무방향 그래프의 정보 저장 + mappers[node1].append(node2) + mappers[node2].append(node1) + + visited = [0 for _ in range(n)] + + def bfs(node): + # bfs로 어떤 node들이 연결되어 있는 지 탐색한다. + queue = deque([node]) + + while queue: # queue에 요소가 있는 동안은 계속 탐색 + node = queue.popleft() # queue에서 가장 빠른 요소 pop + visited[node] = 1 # 해당 노드는 방문 처리 + + next_nodes = mappers.get(node, []) # mappers에서 다음 노드 정보 가져오기 + for next_node in next_nodes: + if visited[next_node]: + # 다음 노드가 이미 방문한 노드라면 탐색하지 않고 스킵해도 됨 + continue + # 다음 노드를 queue에 저장하여 다음 탐색 때 이용 + queue.append((next_node)) + + + for node in range(n): + if visited[node]: + # 이미 방문 처리가 되었다면 해당 노드는 이전에 탐색 완료되었다는 의미 + # bfs 탐색의 시작점으로 사용하지 않고 skip한다 + continue + + # bfs 탐색 + bfs(node) + + # 탐색을 마쳤다면 component 하나를 찾았다는 의미로 res를 하나 올린다. + res += 1 + + return res From c05e453cdc6a36c768169fab12079f0fff99b793 Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年5月23日 15:55:01 +0900 Subject: [PATCH 498/526] =?UTF-8?q?12=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=205=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- non-overlapping-intervals/hwi-middle.cpp | 28 +++++ .../hwi-middle.cpp | 51 ++++++++ .../hwi-middle.cpp | 40 ++++++ same-tree/hwi-middle.cpp | 28 +++++ .../hwi-middle.cpp | 116 ++++++++++++++++++ 5 files changed, 263 insertions(+) create mode 100644 non-overlapping-intervals/hwi-middle.cpp create mode 100644 number-of-connected-components-in-an-undirected-graph/hwi-middle.cpp create mode 100644 remove-nth-node-from-end-of-list/hwi-middle.cpp create mode 100644 same-tree/hwi-middle.cpp create mode 100644 serialize-and-deserialize-binary-tree/hwi-middle.cpp diff --git a/non-overlapping-intervals/hwi-middle.cpp b/non-overlapping-intervals/hwi-middle.cpp new file mode 100644 index 0000000000..ee517d5a57 --- /dev/null +++ b/non-overlapping-intervals/hwi-middle.cpp @@ -0,0 +1,28 @@ +class Solution { +public: + int eraseOverlapIntervals(vector>& intervals) { + sort(intervals.begin(), intervals.end(), [](vector& a, vector& b) { + return a[1] < b[1]; + }); + + int ans = 0; + int k = INT_MIN; + + for (int i = 0; i < intervals.size(); i++) + { + int s = intervals[i][0]; + int e = intervals[i][1]; + + if (s>= k) + { + k = e; + } + else + { + ans++; + } + } + + return ans; + } +}; diff --git a/number-of-connected-components-in-an-undirected-graph/hwi-middle.cpp b/number-of-connected-components-in-an-undirected-graph/hwi-middle.cpp new file mode 100644 index 0000000000..c05a854675 --- /dev/null +++ b/number-of-connected-components-in-an-undirected-graph/hwi-middle.cpp @@ -0,0 +1,51 @@ +class Solution { +public: + int countComponents(int n, vector>& edges) { + int components = n; + vector p(n, -1); + for (auto& e : edges) + { + if (uni(p, e[0], e[1])) // 이 엣지를 통해 합쳐지면 + { + components--; // 컴포넌트 수는 하나 감소 + } + } + + return components; + } + + // union-find + int find(vector&p, int x) + { + if(p[x] < 0) + { + return x; + } + + return p[x] = find(p, p[x]); + } + + bool uni(vector&p, int u, int v) + { + u = find(p, u); + v = find(p, v); + + if (u == v) + { + return false; + } + + if (p[v] < p[u]) + { + swap(u, v); + } + + if (p[u] == p[v]) + { + p[u]--; + } + + p[v] = u; + return true; + } +}; diff --git a/remove-nth-node-from-end-of-list/hwi-middle.cpp b/remove-nth-node-from-end-of-list/hwi-middle.cpp new file mode 100644 index 0000000000..609ca9b05b --- /dev/null +++ b/remove-nth-node-from-end-of-list/hwi-middle.cpp @@ -0,0 +1,40 @@ +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode() : val(0), next(nullptr) {} + * ListNode(int x) : val(x), next(nullptr) {} + * ListNode(int x, ListNode *next) : val(x), next(next) {} + * }; + */ +class Solution { +public: + ListNode* removeNthFromEnd(ListNode* head, int n) { + // 스택에 넣고 뒤집어서 n번째 노드 찾기 + stack s; + ListNode* cur = head; + while (cur != nullptr) + { + s.push(cur); + cur = cur->next; + } + + for (int i = 0; i < n; ++i) + { + cur = s.top(); + s.pop(); + } + + // 스택이 빌 때 까지 pop한 경우는 head를 제거하는 경우 + if (s.empty()) + { + return head->next; + } + + // 그 외에는 prev가 존재 + ListNode* prev = s.top(); + prev->next = cur->next; + return head; + } +}; diff --git a/same-tree/hwi-middle.cpp b/same-tree/hwi-middle.cpp new file mode 100644 index 0000000000..bb63fbb074 --- /dev/null +++ b/same-tree/hwi-middle.cpp @@ -0,0 +1,28 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ + +// 재귀를 통해 동일한 트리인지 확인 +class Solution { +public: + bool isSameTree(TreeNode* p, TreeNode* q) { + if (p == nullptr || q == nullptr) + { + return p == q; + } + + bool l = isSameTree(p->left, q->left); + bool r = isSameTree(p->right, q->right); + bool cur = p->val == q->val; + + return l && r && cur; + } +}; diff --git a/serialize-and-deserialize-binary-tree/hwi-middle.cpp b/serialize-and-deserialize-binary-tree/hwi-middle.cpp new file mode 100644 index 0000000000..fa8ba544bd --- /dev/null +++ b/serialize-and-deserialize-binary-tree/hwi-middle.cpp @@ -0,0 +1,116 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ + + // 그래야할 필요는 없다고 명시하지만, LeetCode 형식과 동일하게 직렬화/역직렬화 구현 +class Codec { +public: + // Encodes a tree to a single string. + string serialize(TreeNode* root) { + vector tokens; + queue
q; + q.push(root); + while (!q.empty()) + { + auto node = q.front(); + q.pop(); + if (node == nullptr) + { + tokens.push_back("null"); + continue; + } + + tokens.push_back(to_string(node->val)); + q.push(node->left); + q.push(node->right); + } + + // 굳이 지우지 않아도 역직렬화가 가능 + // 하지만 LeetCode와 동일하게 구현하기 위한 처리 + while (!tokens.empty() && tokens.back() == "null") + { + tokens.pop_back(); + } + + string s = "["; + for (int i = 0; i < tokens.size(); i++) + { + if (i) + { + s += ","; + + } + s += tokens[i]; + } + + s += "]"; + //cout << s; + return s; + } + + // Decodes your encoded data to tree. + TreeNode* deserialize(string data) { + if (data == "[]") + { + return nullptr; + } + + data = data.substr(1, data.size() - 2); // '[', ']' 제거 + stringstream ss(data); + string token; + + queue v; + while (getline(ss, token, ',')) + { + v.push(token); + } + + TreeNode* root = new TreeNode(stoi(v.front())); + v.pop(); + queue
q; + q.push(root); + while (!q.empty()) + { + auto cur = q.front(); + q.pop(); + + // 만약 직렬화 과정에서 null을 제거하지 않았다면 이러한 확인은 필요없어짐 + if (v.empty()) + { + break; + } + + string l = v.front(); + v.pop(); + if (l != "null") + { + cur->left = new TreeNode(stoi(l)); + q.push(cur->left); + } + + if (v.empty()) + { + break; + } + + string r = v.front(); + v.pop(); + if (r != "null") + { + cur->right = new TreeNode(stoi(r)); + q.push(cur->right); + } + } + return root; + } +}; + +// Your Codec object will be instantiated and called as such: +// Codec ser, deser; +// TreeNode* ans = deser.deserialize(ser.serialize(root)); From 998e2b84463f0109caddd1b02adf44e687ce33dd Mon Sep 17 00:00:00 2001 From: reeseo3o Date: 2026年5月23日 17:21:09 +0900 Subject: [PATCH 499/526] week12: same-tree --- same-tree/reeseo3o.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 same-tree/reeseo3o.js diff --git a/same-tree/reeseo3o.js b/same-tree/reeseo3o.js new file mode 100644 index 0000000000..91279364cf --- /dev/null +++ b/same-tree/reeseo3o.js @@ -0,0 +1,10 @@ +// Time Complexity: O(n) +// Space Complexity: O(n) +const isSameTree = (p, q) => { + if (p === null && q === null) return true; + + if (p === null || q === null) return false; + if (p.val !== q.val) return false; + + return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); +}; From fd5b98c6c3040dc0434b2ec6775c9ccfe5d0b6e8 Mon Sep 17 00:00:00 2001 From: Dale Seo <5466341+daleseo@users.noreply.github.com> Date: 2026年5月23日 14:50:20 -0400 Subject: [PATCH 500/526] reorder-list (#2605) --- reorder-list/DaleSeo.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 reorder-list/DaleSeo.rs diff --git a/reorder-list/DaleSeo.rs b/reorder-list/DaleSeo.rs new file mode 100644 index 0000000000..8e32dcce56 --- /dev/null +++ b/reorder-list/DaleSeo.rs @@ -0,0 +1,41 @@ +// TC: O(n) +// SC: O(1) +impl Solution { + pub fn reorder_list(head: &mut Option>) { + let mut len = 0; + let mut curr = head.as_ref(); + while let Some(node) = curr { + len += 1; + curr = node.next.as_ref(); + } + if len < 3 { + return; + } + + let mut tail = { + let mut node = head.as_mut().unwrap(); + for _ in 0..(len - 1) / 2 { + node = node.next.as_mut().unwrap(); + } + node.next.take() + }; + + let mut reversed = None; + while let Some(mut n) = tail { + tail = n.next.take(); + n.next = reversed; + reversed = Some(n); + } + + let mut node = head.as_mut().unwrap(); + while let Some(mut r) = reversed { + reversed = r.next.take(); + r.next = node.next.take(); + node.next = Some(r); + if reversed.is_none() { + break; + } + node = node.next.as_mut().unwrap().next.as_mut().unwrap(); + } + } +} From 940fb79a839c222f50d8efb3680d1cb6718d3fcc Mon Sep 17 00:00:00 2001 From: "Wonbin Yoon (Robin)" <107087958+robinyoon-dev@users.noreply.github.com> Date: 2026年5月24日 03:50:27 +0900 Subject: [PATCH 501/526] [robinyoon-dev] WEEK 11 Solutions (#2598) * missing number solution * merge intervals solution --- merge-intervals/robinyoon-dev.js | 40 ++++++++++++++++++++++++++++++++ missing-number/robinyoon-dev.js | 17 ++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 merge-intervals/robinyoon-dev.js create mode 100644 missing-number/robinyoon-dev.js diff --git a/merge-intervals/robinyoon-dev.js b/merge-intervals/robinyoon-dev.js new file mode 100644 index 0000000000..f459c121d5 --- /dev/null +++ b/merge-intervals/robinyoon-dev.js @@ -0,0 +1,40 @@ +/** + * @param {number[][]} intervals + * @return {number[][]} + */ +var merge = function (intervals) { + + let result = []; + + let sortedIntervals = intervals.toSorted((a, b) => a[0] - b[0]); + + for (let interval of sortedIntervals) { + + if (result.length == 0) { + result.push(interval); + continue; + } + + let intervalStart = interval[0]; + let intervalEnd = interval[1]; + + let lastItemInResult = result[result.length - 1]; + + let start = lastItemInResult[0]; + let end = lastItemInResult[1]; + + let isIntervalStartInRange = intervalStart>= start && intervalStart <= end; + + if (isIntervalStartInRange) { + if (intervalEnd> end) { + result[result.length - 1][1] = intervalEnd; + } + } else { + result.push(interval); + } + + } + + return result; + +}; diff --git a/missing-number/robinyoon-dev.js b/missing-number/robinyoon-dev.js new file mode 100644 index 0000000000..ed68aaa5a2 --- /dev/null +++ b/missing-number/robinyoon-dev.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} nums + * @return {number} + */ +var missingNumber = function (nums) { + + let n = nums.length + 1; + let sortedNums = nums.sort((a, b) => a - b); + + for (let i = 0; i < n; i++) { + if (sortedNums[i] === i) { + continue; + } else { + return i; + } + } +}; From 98c14265b9681dc9ddd1748c9196fb3811a7e3d4 Mon Sep 17 00:00:00 2001 From: hui Date: 2026年5月24日 14:13:30 +0900 Subject: [PATCH 502/526] [juhui-jeong] WEEK 12 Solutions (#2606) * WEEK 12: Solutions * add: complexity * add:279 * add: 248 * add: 288 --- non-overlapping-intervals/juhui-jeong.java | 68 +++++++++++++------ .../juhui-jeong.java | 61 +++++++++++++---- same-tree/juhui-jeong.java | 30 ++++++++ .../juhui-jeong.java | 43 ++++++++++++ 4 files changed, 167 insertions(+), 35 deletions(-) create mode 100644 serialize-and-deserialize-binary-tree/juhui-jeong.java diff --git a/non-overlapping-intervals/juhui-jeong.java b/non-overlapping-intervals/juhui-jeong.java index 17f7cf9c9b..826f60f174 100644 --- a/non-overlapping-intervals/juhui-jeong.java +++ b/non-overlapping-intervals/juhui-jeong.java @@ -1,51 +1,79 @@ /* - * 끝나는 시간 오름차순 정렬 - */ +처음 풀이 +시작 시간 기준 정렬 class Solution { public int eraseOverlapIntervals(int[][] intervals) { - Arrays.sort(intervals, (a,b) -> Integer.compare(a[1], b[1])); + Arrays.sort(intervals, (a,b) -> { + if (a[0] != b[0]) return Integer.compare(a[0], b[0]); + return Integer.compare(a[1], b[1]); + }); int removeCntResult = 0; - int end = intervals[0][1]; + int[] cur = intervals[0]; for (int i = 1; i< intervals.length; i++) { - if (intervals[i][0] < end) { + int [] next = intervals[i]; + + if (cur[1]> next[0]) { removeCntResult += 1; + if (next[1] < cur[1]) { + cur = next; + } } else { - end = intervals[i][1]; + cur = next; } } return removeCntResult; } } + */ /* -처음 풀이 -시작 시간 기준 정렬 + * 끝나는 시간 오름차순 정렬 + class Solution { public int eraseOverlapIntervals(int[][] intervals) { - Arrays.sort(intervals, (a,b) -> { - if (a[0] != b[0]) return Integer.compare(a[0], b[0]); - return Integer.compare(a[1], b[1]); - }); + Arrays.sort(intervals, (a,b) -> Integer.compare(a[1], b[1])); int removeCntResult = 0; - int[] cur = intervals[0]; + int end = intervals[0][1]; for (int i = 1; i< intervals.length; i++) { - int [] next = intervals[i]; - - if (cur[1]> next[0]) { + if (intervals[i][0] < end) { removeCntResult += 1; - if (next[1] < cur[1]) { - cur = next; - } } else { - cur = next; + end = intervals[i][1]; } } return removeCntResult; } } */ + +/** + * 시간 복잡도: O(n log n) + * 공간 복잡도: O(n) + */ +class Solution { + public int eraseOverlapIntervals(int[][] intervals) { + Arrays.sort(intervals, (a,b) -> a[0] - b[0]); + int count = 0; + int prevEnd = intervals[0][1]; + + for (int i = 1; i < intervals.length; i++) { + int curStart = intervals[i][0]; + int curEnd = intervals[i][1]; + + if (prevEnd <= curStart) { + // 안겹치는 경우(변경 없이 다음 배열로) + prevEnd = curEnd; + } else { + // 겹치는 경우 + count++; + prevEnd = Math.min(prevEnd, curEnd); + } + } + return count; + } +} diff --git a/remove-nth-node-from-end-of-list/juhui-jeong.java b/remove-nth-node-from-end-of-list/juhui-jeong.java index 79b9a7836b..dc11670bb0 100644 --- a/remove-nth-node-from-end-of-list/juhui-jeong.java +++ b/remove-nth-node-from-end-of-list/juhui-jeong.java @@ -1,7 +1,32 @@ + +/* +첫 번째 풀이 +class Solution { + public ListNode removeNthFromEnd(ListNode head, int n) { + List list = new ArrayList(); + + while(head != null) { + list.add(head); + head = head.next; + } + + list.remove(list.size()-n); + if (list.isEmpty()) return null; + + for (int i = 0; i < list.size()-1; i++) { + list.get(i).next = list.get(i+1); + } + list.get(list.size()-1).next = null; + return list.get(0); + } +} +*/ + + /* 시간 복잡도: O(N) 공간 복잡도: O(1) -*/ + class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { ListNode dummy = new ListNode(0); @@ -24,26 +49,32 @@ public ListNode removeNthFromEnd(ListNode head, int n) { return dummy.next; } } +*/ -/* -첫 번째 풀이 +/** + * + * 시간 복잡도는 O(n) + * 공간 복잡도는 O(1) + */ class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { - List list = new ArrayList(); - - while(head != null) { - list.add(head); - head = head.next; + int length = 0; + ListNode curLenCheck = head; + + while(curLenCheck != null) { + length++; + curLenCheck = curLenCheck.next; } - list.remove(list.size()-n); - if (list.isEmpty()) return null; + int targetIndex = length - n; + if (targetIndex == 0) return head.next; - for (int i = 0; i < list.size()-1; i++) { - list.get(i).next = list.get(i+1); + ListNode targetPrev = head; + for (int i=0; i < targetIndex-1; i++) { + targetPrev = targetPrev.next; } - list.get(list.size()-1).next = null; - return list.get(0); + targetPrev.next = targetPrev.next.next; + + return head; } } -*/ diff --git a/same-tree/juhui-jeong.java b/same-tree/juhui-jeong.java index 27945a6363..00c6f36fad 100644 --- a/same-tree/juhui-jeong.java +++ b/same-tree/juhui-jeong.java @@ -10,3 +10,33 @@ public boolean isSameTree(TreeNode p, TreeNode q) { return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); } } + +/* + * 시간 복잡도: O(n) + * 공간 복잡도: O(n) + */ +class Solution { + public boolean isSameTree(TreeNode p, TreeNode q) { + Queue
queueP = new LinkedList(); + Queue
queueQ = new LinkedList(); + + queueP.offer(p); + queueQ.offer(q); + + while(!queueP.isEmpty() && !queueQ.isEmpty()) { + TreeNode curP = queueP.poll(); + TreeNode curQ = queueQ.poll(); + + if (curP == null && curQ == null) continue; + if (curP == null || curQ == null) return false; + + if (curP.val != curQ.val) return false; + + queueP.offer(curP.left); + queueQ.offer(curQ.left); + queueP.offer(curP.right); + queueQ.offer(curQ.right); + } + return true; + } +} diff --git a/serialize-and-deserialize-binary-tree/juhui-jeong.java b/serialize-and-deserialize-binary-tree/juhui-jeong.java new file mode 100644 index 0000000000..37e4e48a52 --- /dev/null +++ b/serialize-and-deserialize-binary-tree/juhui-jeong.java @@ -0,0 +1,43 @@ + +public class Codec { + private int index; + + // Encodes a tree to a single string.(직렬화) + public String serialize(TreeNode root) { + StringBuilder sb = new StringBuilder(); + dfsSerialize(root, sb); + return sb.toString(); + } + + private void dfsSerialize(TreeNode node, StringBuilder sb) { + if (node == null) { + sb.append("null").append(","); + return; + } + sb.append(node.val).append(","); + + dfsSerialize(node.left, sb); + dfsSerialize(node.right, sb); + } + + // Decodes your encoded data to tree.(역직렬화) + public TreeNode deserialize(String data) { + String[] arr = data.split(","); + index = 0; + return dfsDeserialize(arr); + } + + private TreeNode dfsDeserialize(String[] arr) { + String value = arr[index++]; + + if (value.equals("null")) { + return null; + } + + TreeNode node = new TreeNode(Integer.parseInt(value)); + + node.left = dfsDeserialize(arr); + node.right = dfsDeserialize(arr); + return node; + } +} From 7db507740069dbcdf410ffdad419f4b0c8e6bab4 Mon Sep 17 00:00:00 2001 From: yj Cho <57857367+cyjin-jani@users.noreply.github.com> Date: 2026年5月24日 14:52:27 +0900 Subject: [PATCH 503/526] add: sameTree solution (#2607) --- same-tree/Cyjin-jani.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 same-tree/Cyjin-jani.js diff --git a/same-tree/Cyjin-jani.js b/same-tree/Cyjin-jani.js new file mode 100644 index 0000000000..b1efa1bed9 --- /dev/null +++ b/same-tree/Cyjin-jani.js @@ -0,0 +1,20 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} p + * @param {TreeNode} q + * @return {boolean} + */ +const isSameTree = function (p, q) { + if (p === null && q === null) return true; + if (p === null || q === null) return false; + + if (p.val === q.val) return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); + return false; +}; From 1870c7b2e57361eabf2c2a55dfe2558e23082d4d Mon Sep 17 00:00:00 2001 From: Hyeri-Jung Date: 2026年5月24日 15:51:18 +0900 Subject: [PATCH 504/526] [hyeri0903] WEEK12 Solutions (#2614) * same-tree solutions * remove-nth-node-from-end-of-list * non overlapping intervals solutions --- non-overlapping-intervals/hyeri0903.java | 30 ++++++++++++ .../hyeri0903.java | 46 +++++++++++++++++++ same-tree/hyeri0903.java | 44 ++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 non-overlapping-intervals/hyeri0903.java create mode 100644 remove-nth-node-from-end-of-list/hyeri0903.java create mode 100644 same-tree/hyeri0903.java diff --git a/non-overlapping-intervals/hyeri0903.java b/non-overlapping-intervals/hyeri0903.java new file mode 100644 index 0000000000..ac8c8077b9 --- /dev/null +++ b/non-overlapping-intervals/hyeri0903.java @@ -0,0 +1,30 @@ +class Solution { + public int eraseOverlapIntervals(int[][] intervals) { + /** + 1.prob: 겹치지 않는 최소한의 non-oerlapping interval 제거 + 2.constraints + - inverval.lenght min=1, max = 100,000 + 3.solutions - Greedy + - end 기준 오름차순 정렬 + - 이전 interval end 저장 + - 다음 interval check, 안겹치면 -> 선택, 겹치면 count++ + Time: O(n logn), Space: O(1) + */ + int count = 0; + + //end 기준 ascending 정렬 + Arrays.sort(intervals, (a, b) -> a[1] - b[1]); + int end = intervals[0][1]; + + //겹치면 count++, 안겹치면 end update + for(int i = 1; i < intervals.length; i++) { + if(intervals[i][0] < end) { + count++; + } else { + end = intervals[i][1]; + } + } + + return count; + } +} diff --git a/remove-nth-node-from-end-of-list/hyeri0903.java b/remove-nth-node-from-end-of-list/hyeri0903.java new file mode 100644 index 0000000000..04644193ba --- /dev/null +++ b/remove-nth-node-from-end-of-list/hyeri0903.java @@ -0,0 +1,46 @@ +/** + * Definition for singly-linked list. + * public class ListNode { + * int val; + * ListNode next; + * ListNode() {} + * ListNode(int val) { this.val = val; } + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } + * } + */ +class Solution { + public ListNode removeNthFromEnd(ListNode head, int n) { + /** + 1.linked list 에서 뒤에서 n번째 node remove + 2.constraints: + node 개수(sz) min=1, max=30 + n값 min = 1, max= sz + 3.solutions: two pointers + - fast, slow pointer 2개의 간격 = n + - fast 가 끝지점에 도달하면 그때 slow.next 를 제거 + time: O(n), space: O(1) + */ + + ListNode dummy = new ListNode(0); + dummy.next = head; + + ListNode fast = dummy; + ListNode slow = dummy; + + //fast pointer n+1칸 이동, fast - slow = n + for(int i = 0; i <= n; i++) { + fast = fast.next; + } + + while(fast != null) { + fast = fast.next; + slow = slow.next; + } + + //slow pointer 의 다음 노드(slow.next) 제거 + slow.next = slow.next.next; + + return dummy.next; + + } +} diff --git a/same-tree/hyeri0903.java b/same-tree/hyeri0903.java new file mode 100644 index 0000000000..56a62885bd --- /dev/null +++ b/same-tree/hyeri0903.java @@ -0,0 +1,44 @@ +/** + * 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 isSameTree(TreeNode p, TreeNode q) { + /** + 1.problem: 2개의 bst 가 동일한지 체크 + 2.constraints - 구조와 노드가 동일해야된다 + 3.solution - DFS + 1) 두 트리의 노드가 모두 null -> true + 2) 둘중 하나만 null -> false + 3) 값이 다르면 false + 4)재귀로 트리의 구조가 동일한지 체크 + */ + + if(p == null && q == null) { + return true; + } + if(p == null || q == null) { + return false; + } + if(p.val != q.val) { + return false; + } + + if(isSameTree(p.left, q.left) && isSameTree(p.right, q.right)) { + return true; + } + return false; + } + +} From 01d46c6f9e80cfd653d81daf3b8236233589cf04 Mon Sep 17 00:00:00 2001 From: "E.M. Lee" <54928040+jamiebase@users.noreply.github.com> Date: 2026年5月26日 12:03:18 +0900 Subject: [PATCH 505/526] Add solution for checking if two binary trees are the same (#2610) --- same-tree/jamiebase.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 same-tree/jamiebase.py diff --git a/same-tree/jamiebase.py b/same-tree/jamiebase.py new file mode 100644 index 0000000000..08b0bd96e1 --- /dev/null +++ b/same-tree/jamiebase.py @@ -0,0 +1,26 @@ +""" +# Approach +재귀를 이용해서 왼쪽, 오른쪽 서브트리의 값을 비교합니다 + +# Complexity +- Time complexity: 노드 개수 N일 때, O(N) +- Space complexity: 트리 높이 H 일때, O(H) +""" + + +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool: + if not p and not q: + return True + if not p or not q: + return False + if p.val != q.val: + return False + + return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right) From 157db564266a2177bf3159b5b5e479a7ae2ea217 Mon Sep 17 00:00:00 2001 From: "Yunyoung Chung (Lizzie)" <52642281+liza0525@users.noreply.github.com> Date: 2026年5月30日 18:23:59 +0900 Subject: [PATCH 506/526] [liza0525] WEEK 13 Solutions (#2618) * [7th batch] week 13 - lowest common ancestor of a binary search tree * [7th batch] week 13 - kth smallest element in a bst * [7th batch] week 13 - insert interval * [7th batch] week 13 - find median from data stream * [7th batch] week 13 - meeting room --- find-median-from-data-stream/liza0525.py | 62 +++++++++++++++++++ insert-interval/liza0525.py | 34 ++++++++++ kth-smallest-element-in-a-bst/liza0525.py | 51 +++++++++++++++ .../liza0525.py | 37 +++++++++++ meeting-rooms/liza0525.py | 27 ++++++++ 5 files changed, 211 insertions(+) create mode 100644 find-median-from-data-stream/liza0525.py create mode 100644 insert-interval/liza0525.py create mode 100644 kth-smallest-element-in-a-bst/liza0525.py create mode 100644 lowest-common-ancestor-of-a-binary-search-tree/liza0525.py create mode 100644 meeting-rooms/liza0525.py diff --git a/find-median-from-data-stream/liza0525.py b/find-median-from-data-stream/liza0525.py new file mode 100644 index 0000000000..54a3b8995e --- /dev/null +++ b/find-median-from-data-stream/liza0525.py @@ -0,0 +1,62 @@ +import heapq + +# 7기 풀이 +class MedianFinder: + # 공간 복잡도: O(n) + # - 각각의 힙은 추가되는 수의 개수의 공간을 사용 + def __init__(self): + self.pre_list = [] # 앞쪽 구간, 최대 힙으로 + self.post_list = [] # 뒤쪽 구간, 최소 힙으로 + + # 시간 복잡도: O(log n) + # - 힙을 사용하여 앞쪽 구간 및 뒤쪽 구간에 새로운 원소를 넣기 때문에, 메소드 호출 때마다 각 배열의 크기에 시간 복잡도가 정해진다. + # 공간 복잡도: O(1) + # - 해당 메소드에서는 클래스 멤버 변수 사용하는 것 이외에는 몇 개의 변수만 이용 + def addNum(self, num: int) -> None: + if not self.pre_list or num < -self.pre_list[0]: + # 앞쪽 구간에 값을 넣을 경우 + # num이 pre_list의 최댓값보다 작을 때 pre_list에 heappush를 한다. + # 최대힙 구현을 하기 위해 마이너스 값으로 넣는다. + heapq.heappush(self.pre_list, -num) + else: + # 뒤쪽 구간에 값을 넣을 경우 + # num이 post_list의 최솟값보다 클 때 post_list에 heappush를 한다. + heapq.heappush(self.post_list, num) + + pre_len, post_len = len(self.pre_list), len(self.post_list) + + # 힙의 크기 차이가 2 이상 날 때는 중간값 조정을 해주기 위해 요소를 다른 쪽으로 옮겨준다. + if pre_len == post_len + 2: + # pre_list에 요소가 몰린 경우이므로, + # pre_list의 최댓값을 pop한 후 post_list의 최솟값으로 push한다. + heapq.heappush( + self.post_list, + -heapq.heappop(self.pre_list) + ) + elif post_len == pre_len + 2: + # post_list에 요소가 몰린 경우이므로, + # post_list의 최솟값을 pop한 후 pre_list의 최댓값으로 push한다. + heapq.heappush( + self.pre_list, + -heapq.heappop(self.post_list) + ) + + # 시간 복잡도: O(1) + # - 각 힙에서의 최솟값 또는 최대값에 접근하는 정도 + 간단한 중간값 계산 + # 공간 복잡도: O(1) + # - 해당 메소드에서는 클래스 멤버 변수 사용하는 것 이외에는 몇 개의 변수만 이용 + def findMedian(self) -> float: + pre_len, post_len = len(self.pre_list), len(self.post_list) + + if pre_len> post_len: + # pre_list의 길이가 더 큰 경우에는 중간값이 pre_list에 있으므로 + # pre_list의 최댓값을 return + return -self.pre_list[0] + elif pre_len < post_len: + # post_list의 길이가 더 큰 경우에는 중간값이 post_list에 있으므로 + # post_list의 최솟값을 return + return self.post_list[0] + else: + # 두 힙의 길이가 같은 경우에는 + # pre_list의 최댓값과 post_list의 최솟값의 평균값을 return + return (-self.pre_list[0] + self.post_list[0]) / 2 diff --git a/insert-interval/liza0525.py b/insert-interval/liza0525.py new file mode 100644 index 0000000000..44afeae444 --- /dev/null +++ b/insert-interval/liza0525.py @@ -0,0 +1,34 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - intervals의 모든 요소를 접근하므로 intervals의 길이(n)만큼 시간 소요 +# 공간 복잡도: O(1) +# - 결과 변수인 res를 제외하면, 몇 가지 변수 이외에 사용하지 않음 +class Solution: + def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]: + res = [newInterval] # newInterval을 맨 처음에 넣어줌 + + for curr_start, curr_end in intervals: # intervals를 돌며 현재의 구간을 curr_start, curr_end로 지정 + prev_start, prev_end = res[-1] # 이전 구간은 res의 마지막 요소인 prev_start, prev_end로 지정 + if curr_start <= prev_end: + # 1. curr_start가 prev_end와 작거나 같다는 것은 + # 다음의 두 케이스로 나뉘어진다.(자세한 설명은 각 조건 내에 상술) + if curr_end < prev_start: + # 1-1. curr 구간이 prev 구간보다 아예 앞서는 경우 + # 이 경우에는 구간의 순서를 변경해줘야 하므로 + # res[-1]을 curr 요소로 변경해준 후 + # prev 구간을 다시 append해준다. + res[-1][0], res[-1][1] = curr_start, curr_end + res.append([prev_start, prev_end]) + else: + # 1-2. curr 구간과 prev 구간이 겹치는 경우 + # 이 경우에는 start끼리 비교하여 작은 수를 res[-1]의 start로 + # end 끼리 비교하여 큰 수를 res[-1]의 end 값으로 재할당 + res[-1][0] = min(curr_start, prev_start) + res[-1][1] = max(curr_end, prev_end) + else: + # 2. curr_start가 prev_end보다 큰 경우에는 + # 구간의 순서를 바꾸거나 겹치는 구간을 merge할 필요가 없으므로 + # res에 현재 구간을 append해준다. + res.append([curr_start, curr_end]) + + return res diff --git a/kth-smallest-element-in-a-bst/liza0525.py b/kth-smallest-element-in-a-bst/liza0525.py new file mode 100644 index 0000000000..5e83ab238a --- /dev/null +++ b/kth-smallest-element-in-a-bst/liza0525.py @@ -0,0 +1,51 @@ +# 7기 풀이 +# 풀이 1, 2 모두 중위 순회를 하면 BST를 오름차순으로 순회할 수 있다는 특징을 이용해 풀이 +class Solution: + # 풀이 1 + # 시간 복잡도: O(n) + # - 최악의 경우에는 모든 노드를 탐색하는 경우이므로, 노드의 개수(n)만큼의 시간 소요 + # 공간 복잡도: O(h) + # - 재귀 스택에 트리의 깊이(h) 만큼 사용됨 + def kthSmallest(self, root: Optional[TreeNode], k: int) -> int: + res = -1 # 결과를 저장할 변수 + + def inorder(node): + # k와 res는 inorder 함수 외부의 변수들이므로, + # nonlocal 선언하여 접근할 수 있게 변경 + nonlocal k + nonlocal res + + if not node: + # 노드가 None인 경우는 재귀 탐색을 끝내고 return + return + + inorder(node.left) # 왼쪽 자식 노드를 재귀적으로 먼저 탐색 + k -= 1 # 현재 노드 탐색에서 k를 하나 줄임 + if k == 0: # k가 0이 되는 순간이 전체 노드 중에 k번째 값이 됨 + res = node.val # res에 node의 값을 할당 + return # 더이상 탐색할 필요가 없으므로 return + inorder(node.right) # 오른쪽 자식 노드를 재귀적으로 나중에 탐색 + + inorder(root) + return res + + # 풀이 2 + # 시간 복잡도: O(n) + # - 모든 노드를 탐색하기 때문에 노드의 개수(n)만큼의 시간 소요 + # 공간 복잡도: O(n) + # - 모든 노드의 값을 res_list에 저장하기 때문에 노드의 개수(n)만큼의 공간 차지 + def kthSmallest(self, root: Optional[TreeNode], k: int) -> int: + res_list = [] + + def inorder(node): + if not node: + # 노드가 없을 땐 return + return + + inorder(node.left) # 왼쪽 자식 노드를 재귀적으로 먼저 탐색 + res_list.append(node.val) # 현재 노드를 res_list에 삽입 + inorder(node.right) # 오른쪽 자식 노드를 재귀적으로 나중에 탐색 + + + inorder(root) # 중위 탐색 시작 + return res_list[k - 1] # 탐색한 결과 중 k번째 요소 return diff --git a/lowest-common-ancestor-of-a-binary-search-tree/liza0525.py b/lowest-common-ancestor-of-a-binary-search-tree/liza0525.py new file mode 100644 index 0000000000..e4d00346c4 --- /dev/null +++ b/lowest-common-ancestor-of-a-binary-search-tree/liza0525.py @@ -0,0 +1,37 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - balanced tree라면 O(log n)이 되지만, 편향 트리가 worst case이므로 +# - 이때는 모든 노드 탐색, 노드 개수(n)에 따라 시간 복잡도가 결정된다. +# - balanced tree의 경우: 매 노드 탐색 때마다 한 쪽 서브 트리를 선택해 탐색하므로 노드 개수(n)의 log 값만큼의 시간 소요 +# 공간 복잡도: O(h) +# - tree의 높이인 h만큼의 재귀 스택이 쌓임 +class Solution: + def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': + node1 = p if p.val < q.val else q # node1은 val이 작은 노드를 가르키게 설정 + node2 = q if p.val < q.val else p # node2은 val이 큰 노드를 가르키게 설정 + + def find_lca(node): + # BST 특징에 의해 + # 자기 자신 값은 왼쪽 서브트리 노드의 값들보다 무조건 크고 + # 오른쪽 서브트리 노드들의 값보다 무조건 작다. + # 따라서 node1.val <= node.val <= node2.val이면 + # p와 q가 현재 노드를 기준으로 양쪽에 갈라지는 순간으로 판단, + # 그 노드가 LCA가 된다. + if node1.val <= node.val <= node2.val: + # 사이에 들어온 경우는 node 그 자체를 return + # 등호도 같이 써준다. + return node + elif node.val> node1.val and node.val> node2.val: + # node의 값이 node1의 값과 node2의 값보다 큰 경우, + # LCA는 현재 노드의 left subtree에 존재한다는 의미이므로 + # 다음 탐색은 왼쪽 자식 노드 쪽으로 재귀 탐색 + return find_lca(node.left) + elif node.val < node1.val and node.val < node2.val: + # node의 값이 node1의 값과 node2의 값보다 작은 경우, + # LCA는 현재 노드의 right subtree에 존재한다는 의미이므로 + # 다음 탐색은 오른쪽 자식 노드 쪽으로 재귀 탐색 + return find_lca(node.right) + + # 세 케이스가 exhaustive하므로 else 없음 + + return find_lca(root) diff --git a/meeting-rooms/liza0525.py b/meeting-rooms/liza0525.py new file mode 100644 index 0000000000..8d0aebc667 --- /dev/null +++ b/meeting-rooms/liza0525.py @@ -0,0 +1,27 @@ +from typing import List + + +# class Interval(object): +# def __init__(self, start, end): +# self.start = start +# self.end = end + +# 7기 풀이 +# 시간 복잡도: O(n log n) +# - python sorting을 이용하여 정렬하기 때문에 +# 공간 복잡도: O(1) +# - 메서드 파라미터 이외에 사용하는 변수 없음 +class Solution: + def can_attend_meetings(self, intervals: List[Interval]) -> bool: + # intervals를 정렬, 이때 key는 각 요소의 start 시간을 기준으로 오름차순 해준다. + intervals.sort(key=lambda x: x.start) + + for i in range(1, len(intervals)): + # 현재 interval 시작 시간이 이전 interval 종료 시간보다 작으면 + # 두 구간은 겹치는 구간이므로, 문제 요건에 따라 False를 early return + if intervals[i].start < intervals[i - 1].end: + return False + + # 모든 interval 구간 확인 후 겹치지 않으며 + # True를 return + return True From d86bb373e2f32fbc497ac57f0a897ff8993886ec Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年5月30日 18:51:51 +0900 Subject: [PATCH 507/526] =?UTF-8?q?13=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=205=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#2620)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- find-median-from-data-stream/hwi-middle.cpp | 32 ++++++++++++++ insert-interval/hwi-middle.cpp | 30 +++++++++++++ kth-smallest-element-in-a-bst/hwi-middle.cpp | 44 +++++++++++++++++++ .../hwi-middle.cpp | 22 ++++++++++ meeting-rooms/hwi-middle.cpp | 20 +++++++++ 5 files changed, 148 insertions(+) create mode 100644 find-median-from-data-stream/hwi-middle.cpp create mode 100644 insert-interval/hwi-middle.cpp create mode 100644 kth-smallest-element-in-a-bst/hwi-middle.cpp create mode 100644 lowest-common-ancestor-of-a-binary-search-tree/hwi-middle.cpp create mode 100644 meeting-rooms/hwi-middle.cpp diff --git a/find-median-from-data-stream/hwi-middle.cpp b/find-median-from-data-stream/hwi-middle.cpp new file mode 100644 index 0000000000..bf6a9b7e34 --- /dev/null +++ b/find-median-from-data-stream/hwi-middle.cpp @@ -0,0 +1,32 @@ +class MedianFinder { +public: + MedianFinder() { + } + + void addNum(int num) { + maxHeap.push(num); + minHeap.push(maxHeap.top()); + maxHeap.pop(); + + if (maxHeap.size() < minHeap.size()) + { + maxHeap.push(minHeap.top()); + minHeap.pop(); + } + } + + double findMedian() { + return maxHeap.size()> minHeap.size() ? maxHeap.top() : ((double) maxHeap.top() + minHeap.top()) * 0.5; + } + +private: + priority_queue maxHeap; + priority_queue, greater> minHeap; +}; + +/** + * Your MedianFinder object will be instantiated and called as such: + * MedianFinder* obj = new MedianFinder(); + * obj->addNum(num); + * double param_2 = obj->findMedian(); + */ diff --git a/insert-interval/hwi-middle.cpp b/insert-interval/hwi-middle.cpp new file mode 100644 index 0000000000..e810a58d30 --- /dev/null +++ b/insert-interval/hwi-middle.cpp @@ -0,0 +1,30 @@ +class Solution { +public: + vector> insert(vector>& intervals, vector& newInterval) { + int n = intervals.size(); + vector> res; + + int i = 0; + while (i < n && intervals[i][1] < newInterval[0]) + { + res.push_back(intervals[i]); + i++; + } + + while (i < n && newInterval[1]>= intervals[i][0]) + { + newInterval[0] = min(newInterval[0], intervals[i][0]); + newInterval[1] = max(newInterval[1], intervals[i][1]); + i++; + } + res.push_back(newInterval); + + while (i < n) + { + res.push_back(intervals[i]); + i++; + } + + return res; + } +}; diff --git a/kth-smallest-element-in-a-bst/hwi-middle.cpp b/kth-smallest-element-in-a-bst/hwi-middle.cpp new file mode 100644 index 0000000000..ad0712fca5 --- /dev/null +++ b/kth-smallest-element-in-a-bst/hwi-middle.cpp @@ -0,0 +1,44 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + int kthSmallest(TreeNode* root, int k) { + int cur = 0; + return impl(root, k, cur); + } + + int impl(TreeNode* root, int k, int& cur) { + if (root == nullptr) + { + return -1; + } + + int l = impl(root->left, k, cur); + if (l != -1) + { + return l; + } + + if (++cur == k) + { + return root->val; + } + + int r = impl(root->right, k, cur); + if (r != -1) + { + return r; + } + + return -1; + } +}; diff --git a/lowest-common-ancestor-of-a-binary-search-tree/hwi-middle.cpp b/lowest-common-ancestor-of-a-binary-search-tree/hwi-middle.cpp new file mode 100644 index 0000000000..8654d0d33c --- /dev/null +++ b/lowest-common-ancestor-of-a-binary-search-tree/hwi-middle.cpp @@ -0,0 +1,22 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ + +class Solution { +public: + TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { + // p와 q가 root 기준 왼쪽과 오른쪽에 나뉘어 존재하면 root가 LCA + while ((root->val - p->val) * (long long)(root->val - q->val)> 0LL) + { + root = root->val> p->val ? root->left : root->right; + } + + return root; + } +}; diff --git a/meeting-rooms/hwi-middle.cpp b/meeting-rooms/hwi-middle.cpp new file mode 100644 index 0000000000..556db6b71c --- /dev/null +++ b/meeting-rooms/hwi-middle.cpp @@ -0,0 +1,20 @@ +class Solution { +public: + bool canAttendMeetings(vector>& intervals) { + sort(intervals.begin(), intervals.end(), [](vector& a, vector& b) + { + return a[0] < b[0]; + }); + + int n = intervals.size(); + for (int i = 0; i < n - 1; ++i) + { + if (intervals[i][1]> intervals[i + 1][0]) + { + return false; + } + } + + return true; + } +}; From 80399beac4ac615be0686982206391b5692935fa Mon Sep 17 00:00:00 2001 From: Reese Date: 2026年5月30日 21:06:02 +0700 Subject: [PATCH 508/526] week13: meeting-rooms (#2619) --- meeting-rooms/reeseo3o.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 meeting-rooms/reeseo3o.js diff --git a/meeting-rooms/reeseo3o.js b/meeting-rooms/reeseo3o.js new file mode 100644 index 0000000000..d657546fe1 --- /dev/null +++ b/meeting-rooms/reeseo3o.js @@ -0,0 +1,21 @@ +// Time Complexity: O(nlogn) +// Space Complexity: O(1) + +const canAttendMeetings = function (intervals) { + if (!intervals || intervals.length <= 1) { + return true; + } + + intervals.sort((a, b) => a[0] - b[0]); + + for (let i = 1; i < intervals.length; i++) { + const prevEnd = intervals[i - 1][1]; + const currStart = intervals[i][0]; + + if (currStart < prevEnd) { + return false; + } + } + + return true; +}; From 8a14654670d81bee06c5ee1b32c35a210005ffcd Mon Sep 17 00:00:00 2001 From: Ted Date: 2026年5月30日 16:14:19 -0400 Subject: [PATCH 509/526] add a solution (#2617) --- find-median-from-data-stream/tedkimdev.go | 82 +++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 find-median-from-data-stream/tedkimdev.go diff --git a/find-median-from-data-stream/tedkimdev.go b/find-median-from-data-stream/tedkimdev.go new file mode 100644 index 0000000000..e7fc7dda09 --- /dev/null +++ b/find-median-from-data-stream/tedkimdev.go @@ -0,0 +1,82 @@ +type MedianFinder struct { + small *MaxHeap // lower half + large *MinHeap // upper half +} + +func Constructor() MedianFinder { + small := &MaxHeap{} + large := &MinHeap{} + heap.Init(small) + heap.Init(large) + + return MedianFinder{ + small: small, + large: large, + } +} + +// SC: O(n) +// TC: O(m * log n) +func (this *MedianFinder) AddNum(num int) { + if this.small.Len() == 0 || num <= (*this.small)[0] { + heap.Push(this.small, num) + } else { + heap.Push(this.large, num) + } + + // rebalance + if this.small.Len()> this.large.Len()+1 { + v := heap.Pop(this.small).(int) + heap.Push(this.large, v) + } + + if this.large.Len()> this.small.Len() { + v := heap.Pop(this.large).(int) + heap.Push(this.small, v) + } +} + +// TC: O(m) +func (this *MedianFinder) FindMedian() float64 { + if this.small.Len()> this.large.Len() { + return float64((*this.small)[0]) + } + + return float64((*this.small)[0]+(*this.large)[0]) / 2.0 +} + +type MinHeap []int + +func (h MinHeap) Len() int { return len(h) } +func (h MinHeap) Less(i, j int) bool { return h[i] < h[j] } +func (h MinHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } + +func (h *MinHeap) Push(x interface{}) { + *h = append(*h, x.(int)) +} + +func (h *MinHeap) Pop() interface{} { + old := *h + n := len(old) + x := old[n-1] + *h = old[:n-1] + return x +} + +type MaxHeap []int + +func (h MaxHeap) Len() int { return len(h) } +func (h MaxHeap) Less(i, j int) bool { return h[i]> h[j] } // reverse +func (h MaxHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } + +func (h *MaxHeap) Push(x interface{}) { + *h = append(*h, x.(int)) +} + +func (h *MaxHeap) Pop() interface{} { + old := *h + n := len(old) + x := old[n-1] + *h = old[:n-1] + return x +} From 00fb2304229cc0bd67ceb8b15620edd805e4f77d Mon Sep 17 00:00:00 2001 From: Dale Seo <5466341+daleseo@users.noreply.github.com> Date: 2026年5月30日 18:04:18 -0400 Subject: [PATCH 510/526] same-tree (#2613) --- same-tree/DaleSeo.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 same-tree/DaleSeo.rs diff --git a/same-tree/DaleSeo.rs b/same-tree/DaleSeo.rs new file mode 100644 index 0000000000..804a94bf02 --- /dev/null +++ b/same-tree/DaleSeo.rs @@ -0,0 +1,23 @@ +// TC: O(n) +// SC: O(n) +use std::cell::RefCell; +use std::rc::Rc; + +impl Solution { + pub fn is_same_tree( + p: Option>>, + q: Option>>, + ) -> bool { + match (p, q) { + (None, None) => true, + (Some(a), Some(b)) => { + let a = a.borrow(); + let b = b.borrow(); + a.val == b.val + && Self::is_same_tree(a.left.clone(), b.left.clone()) + && Self::is_same_tree(a.right.clone(), b.right.clone()) + } + _ => false, + } + } +} From 3bcc7148b48609920a088b04f7f76b971b2ae036 Mon Sep 17 00:00:00 2001 From: Hyeri-Jung Date: 2026年5月31日 18:03:50 +0900 Subject: [PATCH 511/526] [hyeri0903] WEEK 13 Solutions (#2621) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * same-tree solutions * remove-nth-node-from-end-of-list * non overlapping intervals solutions * kth-smallest-element-in-a-bst solution * 주석 수정 Co-authored-by: Dale Seo <5466341+daleseo@users.noreply.github.com> * insert-interval solutions --------- Co-authored-by: Dale Seo <5466341+daleseo@users.noreply.github.com> --- insert-interval/hyeri0903.java | 41 +++++++++++++++++ kth-smallest-element-in-a-bst/hyeri0903.java | 48 ++++++++++++++++++++ same-tree/hyeri0903.java | 2 +- 3 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 insert-interval/hyeri0903.java create mode 100644 kth-smallest-element-in-a-bst/hyeri0903.java diff --git a/insert-interval/hyeri0903.java b/insert-interval/hyeri0903.java new file mode 100644 index 0000000000..b8dd3ef0ff --- /dev/null +++ b/insert-interval/hyeri0903.java @@ -0,0 +1,41 @@ +class Solution { + public int[][] insert(int[][] intervals, int[] newInterval) { + /** + 1.문제: newInterval 을 추가 후 intervals 오름차순 재정렬 + 2.constraints: start 기준으로 ascending order + 3.solutions + - newIntervals start 보다 앞에있는 것들은 merge 필요 없음 + - 즉 intervalse[i][1] < newInterval[0] 이면 merge X + - intervals[i][0] <= newInterval[1] 이면 merge + - 마지막에 겹치는 부분은 skip 후 intervals 재정렬 + time: O(n), space: O(1) + */ + + List result = new ArrayList(); + int i = 0; + int n = intervals.length; + + //1.newInterval 앞에 있는 값은 그대로 result add + while(i < n && intervals[i][1] < newInterval[0]) { + result.add(intervals[i]); + i += 1; + } + + //2.overlap 구간은 merge + while(i < n && intervals[i][0] <= newInterval[1]) { + newInterval[0] = Math.min(newInterval[0], intervals[i][0]); + newInterval[1] = Math.max(newInterval[1], intervals[i][1]); + i += 1; + } + result.add(newInterval); + + //3.나머지 result에 add + while(i < n) { + result.add(intervals[i]); + i++; + } + + return result.toArray(new int[result.size()][]); + + } +} diff --git a/kth-smallest-element-in-a-bst/hyeri0903.java b/kth-smallest-element-in-a-bst/hyeri0903.java new file mode 100644 index 0000000000..304804bd48 --- /dev/null +++ b/kth-smallest-element-in-a-bst/hyeri0903.java @@ -0,0 +1,48 @@ +/** + * 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 { + private int count = 0; + private int answer = 0; + public int kthSmallest(TreeNode root, int k) { + /** + 1.BST에서 K번째 가장 작은 값 찾기 + 2.constraints : node 개수 ᅳin = 0, max = 10000 + 3.solutions: + - k번째 방문한 노드가 k번째로 작은 값 (bst 이므로) + - dfs search (inorder traversal) + */ + + dfs(root, k); + return answer; + } + private void dfs(TreeNode node, int k) { + if(node == null) { + return; + } + + + dfs(node.left, k); + count++; + + if(count == k) { + answer = node.val; + return; + } + + dfs(node.right, k); + } + +} diff --git a/same-tree/hyeri0903.java b/same-tree/hyeri0903.java index 56a62885bd..0583b19c69 100644 --- a/same-tree/hyeri0903.java +++ b/same-tree/hyeri0903.java @@ -16,7 +16,7 @@ class Solution { public boolean isSameTree(TreeNode p, TreeNode q) { /** - 1.problem: 2개의 bst 가 동일한지 체크 + 1.problem: 2개의 binary tree 가 동일한지 체크 2.constraints - 구조와 노드가 동일해야된다 3.solution - DFS 1) 두 트리의 노드가 모두 null -> true From f66e7cf496f2c0247bde0621405724bbf5c74200 Mon Sep 17 00:00:00 2001 From: hui Date: 2026年5月31日 19:05:14 +0900 Subject: [PATCH 512/526] [juhui-jeong] WEEK 13 Solutions (#2616) * WEEK 12: Solutions * add: complexity * add:279 * add: 248 * add: 288 * WEEK 13: Solutions * add: 257 * add: 277 --- insert-interval/juhui-jeong.java | 38 +++++++++++++++++++ .../juhui-jeong.java | 19 ++++++++++ .../juhui-jeong.java | 19 +++++++++- 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 insert-interval/juhui-jeong.java create mode 100644 kth-smallest-element-in-a-bst/juhui-jeong.java diff --git a/insert-interval/juhui-jeong.java b/insert-interval/juhui-jeong.java new file mode 100644 index 0000000000..bd48d26f0a --- /dev/null +++ b/insert-interval/juhui-jeong.java @@ -0,0 +1,38 @@ +/** + * 시간 복잡도: O(n) + * 공간 복잡도: O(n) + */ +class Solution { + public int[][] insert(int[][] intervals, int[] newInterval) { + List result = new ArrayList(); + + int newStart = newInterval[0]; + int newEnd = newInterval[1]; + boolean inserted = false; + + for (int i = 0; i < intervals.length; i++) { + int curStart = intervals[i][0]; + int curEnd = intervals[i][1]; + + if (curEnd < newStart) { + // 1. newInterval 보다 왼쪽 + result.add(new int[]{curStart, curEnd}); + } else if (curStart> newEnd) { + // 2. newInterval 보다 오른쪽 + if (!inserted) { + result.add(new int[]{newStart, newEnd}); + inserted = true; + } + result.add(new int[]{curStart, curEnd}); + } else { + newStart = Math.min(newStart, curStart); + newEnd = Math.max(newEnd, curEnd); + } + } + + if (!inserted) { + result.add(new int[]{newStart, newEnd}); + } + return result.toArray(new int[result.size()][]); + } +} diff --git a/kth-smallest-element-in-a-bst/juhui-jeong.java b/kth-smallest-element-in-a-bst/juhui-jeong.java new file mode 100644 index 0000000000..b7e29a52fe --- /dev/null +++ b/kth-smallest-element-in-a-bst/juhui-jeong.java @@ -0,0 +1,19 @@ +/** + * 시간 복잡도: O(n) + * 공간 복잡도: O(n) + */ +class Solution { + public int kthSmallest(TreeNode root, int k) { + List list = new ArrayList(); + inorder(root, list); + + return list.get(k-1); + } + private void inorder(TreeNode node, Listlist) { + if (node == null) return; + + inorder(node.left, list); + list.add(node.val); + inorder(node.right, list); + } +} diff --git a/lowest-common-ancestor-of-a-binary-search-tree/juhui-jeong.java b/lowest-common-ancestor-of-a-binary-search-tree/juhui-jeong.java index 2b6df245ae..ff15be21b5 100644 --- a/lowest-common-ancestor-of-a-binary-search-tree/juhui-jeong.java +++ b/lowest-common-ancestor-of-a-binary-search-tree/juhui-jeong.java @@ -1,7 +1,8 @@ /* + 이전 풀이(반복문) 시간복잡도: O(log N) 공간복잡도: O(1) - */ + class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { while(root != null) { @@ -16,3 +17,19 @@ public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { return null; } } + */ + +/** + 시간복잡도: O(h) + 공간복잡도: O(h) + */ +class Solution { + public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { + if (p.val < root.val && q.val < root.val) { + return this.lowestCommonAncestor(root.left, p, q); + } else if (p.val> root.val && q.val> root.val) { + return this.lowestCommonAncestor(root.right, p, q); + } + return root; + } +} From 84274c0bc758b3bc8214702d06eda7637f541e67 Mon Sep 17 00:00:00 2001 From: "E.M. Lee" <54928040+jamiebase@users.noreply.github.com> Date: Mon, 1 Jun 2026 18:37:06 +0900 Subject: [PATCH 513/526] [jamiebase] WEEK 13 Solutions (#2615) --- .../jamiebase.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 lowest-common-ancestor-of-a-binary-search-tree/jamiebase.py diff --git a/lowest-common-ancestor-of-a-binary-search-tree/jamiebase.py b/lowest-common-ancestor-of-a-binary-search-tree/jamiebase.py new file mode 100644 index 0000000000..a91622b097 --- /dev/null +++ b/lowest-common-ancestor-of-a-binary-search-tree/jamiebase.py @@ -0,0 +1,22 @@ +""" +# Approach +BST 의 특징을 이용해서 값의 대소 비교로 공통 조상을 찾습니다. + +# Complexity +- Time complexity: 트리의 높이 H일때, O(H) +- Space complexity: O(1) +""" + + +class Solution: + def lowestCommonAncestor( + self, root: "TreeNode", p: "TreeNode", q: "TreeNode" + ) -> "TreeNode": + cur = root + while cur: + if p.val < cur.val and q.val < cur.val: + cur = cur.left + elif p.val> cur.val and q.val> cur.val: + cur = cur.right + else: + return cur From b56124ae2a73f48d8e8b52a2c972d29f001ba00a Mon Sep 17 00:00:00 2001 From: Dale Seo <5466341+daleseo@users.noreply.github.com> Date: Wed, 3 Jun 2026 20:32:02 -0400 Subject: [PATCH 514/526] lowest-common-ancestor-of-a-binary-search-tree (#2622) --- .../DaleSeo.rs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 lowest-common-ancestor-of-a-binary-search-tree/DaleSeo.rs diff --git a/lowest-common-ancestor-of-a-binary-search-tree/DaleSeo.rs b/lowest-common-ancestor-of-a-binary-search-tree/DaleSeo.rs new file mode 100644 index 0000000000..f6680d029d --- /dev/null +++ b/lowest-common-ancestor-of-a-binary-search-tree/DaleSeo.rs @@ -0,0 +1,30 @@ +// TC: O(h) +// SC: O(1) +use std::cell::RefCell; +use std::rc::Rc; + +impl Solution { + pub fn lowest_common_ancestor( + root: Option>>, + p: Option>>, + q: Option>>, + ) -> Option>> { + let p_val = p?.borrow().val; + let q_val = q?.borrow().val; + let mut current = root; + + while let Some(node) = current { + let node_ref = node.borrow(); + if p_val < node_ref.val && q_val < node_ref.val { + current = node_ref.left.clone(); + } else if p_val> node_ref.val && q_val> node_ref.val { + current = node_ref.right.clone(); + } else { + drop(node_ref); + return Some(node); + } + } + + None + } +} From a2abe12a7fe7a02c2c900e11b295000adc35f27f Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: Sat, 6 Jun 2026 18:56:42 +0900 Subject: [PATCH 515/526] =?UTF-8?q?14=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=205=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#2626)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hwi-middle.cpp | 51 ++++++ counting-bits/hwi-middle.cpp | 13 ++ house-robber-ii/hwi-middle.cpp | 25 +++ meeting-rooms-ii/hwi-middle.cpp | 39 +++++ word-search-ii/hwi-middle.cpp | 148 ++++++++++++++++++ 5 files changed, 276 insertions(+) create mode 100644 binary-tree-level-order-traversal/hwi-middle.cpp create mode 100644 counting-bits/hwi-middle.cpp create mode 100644 house-robber-ii/hwi-middle.cpp create mode 100644 meeting-rooms-ii/hwi-middle.cpp create mode 100644 word-search-ii/hwi-middle.cpp diff --git a/binary-tree-level-order-traversal/hwi-middle.cpp b/binary-tree-level-order-traversal/hwi-middle.cpp new file mode 100644 index 0000000000..2c2e0998dc --- /dev/null +++ b/binary-tree-level-order-traversal/hwi-middle.cpp @@ -0,0 +1,51 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + vector> levelOrder(TreeNode* root) { + vector> v; + if (root == nullptr) + { + return v; + } + + // BFS로 해결 + queue> q; + q.push({root, 0}); + while (!q.empty()) + { + TreeNode* cur; + int h; + tie(cur, h) = q.front(); + q.pop(); + + if (v.size() == h) + { + v.push_back(vector()); + } + + v[h].push_back(cur->val); + + if (cur->left != nullptr) + { + q.push({cur->left, h + 1}); + } + + if (cur->right != nullptr) + { + q.push({cur->right, h + 1}); + } + } + + return v; + } +}; diff --git a/counting-bits/hwi-middle.cpp b/counting-bits/hwi-middle.cpp new file mode 100644 index 0000000000..76081a4ae3 --- /dev/null +++ b/counting-bits/hwi-middle.cpp @@ -0,0 +1,13 @@ +class Solution { +public: + vector countBits(int n) { + // i & (i - 1)은 가장 오른쪽 비트 1을 지운다는 성질을 이용 + vector ans(n + 1); // ans[0]은 0으로 초기화 + for (int i = 1; i <= n; ++i) + { + ans[i] = ans[i & (i - 1)] + 1; + } + + return ans; + } +}; diff --git a/house-robber-ii/hwi-middle.cpp b/house-robber-ii/hwi-middle.cpp new file mode 100644 index 0000000000..6787db25aa --- /dev/null +++ b/house-robber-ii/hwi-middle.cpp @@ -0,0 +1,25 @@ +class Solution { +public: + int rob(vector& nums) { + if (nums.size() == 1) + { + return nums[0]; + } + + // 1번째 집과 n번째 집이 이웃하므로, [1, n)과 (1, n]에 대해 탐색 후 최댓값 반환 + return max(sol(span(nums).subspan(0, nums.size() - 1)), sol(span(nums).subspan(1))); + } + + int sol(span nums) { + int len = nums.size() + 1; + vector d(len); + d[0] = 0; + d[1] = nums[0]; + for(int i = 2; i < len; ++i) + { + d[i] = max(d[i - 1], d[i - 2] + nums[i - 1]); + } + + return d[len - 1]; + } +}; diff --git a/meeting-rooms-ii/hwi-middle.cpp b/meeting-rooms-ii/hwi-middle.cpp new file mode 100644 index 0000000000..a85b6251d2 --- /dev/null +++ b/meeting-rooms-ii/hwi-middle.cpp @@ -0,0 +1,39 @@ +class Solution { +public: + int minMeetingRooms(vector>& intervals) { + // 시작 시간이 빠른 순으로 정렬 + int n = intervals.size(); + sort(intervals.begin(), intervals.end(), [](vector& a, vector& b) + { + return a[0] < b[0]; + }); + + // 회의실이 부족할 때 마다 하나씩 추가 + // rooms에는 각 회의실을 마지막으로 이용한 회의의 종료 시간이 들어있음 + vector rooms; + rooms.push_back({intervals[0][1]}); + + for (int i = 1; i < n; ++i) + { + bool found = false; + for (auto& room : rooms) + { + // 빈 회의실을 찾은 경우 + if (room <= intervals[i][0]) + { + room = intervals[i][1]; + found = true; + break; + } + } + + // 빈 회의실을 찾지 못한 경우 + if (!found) + { + rooms.push_back(intervals[i][1]); + } + } + + return rooms.size(); + } +}; diff --git a/word-search-ii/hwi-middle.cpp b/word-search-ii/hwi-middle.cpp new file mode 100644 index 0000000000..8f3cbcf990 --- /dev/null +++ b/word-search-ii/hwi-middle.cpp @@ -0,0 +1,148 @@ +class Solution { +private: + // 트라이(Trie)를 활용 + struct Node + { + bool isWord = false; + Node* children[26]; + Node() : isWord(false) + { + fill(children, children + 26, nullptr); + } + + bool isEmpty() + { + for (int i = 0; i < 26; ++i) + { + if (children[i] != nullptr) + { + return false; + } + } + + return true; + } + }; + + // 각 노드는 배열로 관리 + static constexpr size_t POOL_SIZE = 300001; + Node pool[POOL_SIZE]; + int poolIdx = 0; + + Node* newNode() + { + pool[poolIdx] = Node(); + return &pool[poolIdx++]; + } + + Node* root; + vector ans; + int row; + int col; + +public: + vector findWords(vector>& board, vector& words) { + // 트라이 구성 시작 + poolIdx = 0; + ans.clear(); + root = newNode(); + for (auto& word : words) + { + Node* cur = root; + for (auto ch : word) + { + auto& child = cur->children[ch - 'a']; + if (child == nullptr) + { + child = newNode(); + } + + cur = child; + } + + cur->isWord = true; + } + + // 한 칸씩 탐색 시작 + row = board.size(); + col = board[0].size(); + for (int r = 0; r < row; ++r) + { + for (int c = 0; c < col; ++c) + { + string s = ""; + solve(board, root, s, r, c); + } + } + + return ans; + } + + void solve(vector>& board, Node*& node, string& s, int r, int c) + { + // 경로가 제거된 경우 + if (node == nullptr) + { + return; + } + + // 범위를 벗어난 경우 + if (r < 0 || r>= row || c < 0 || c>= col) + { + return; + } + + // 이미 방문한 경우 + char ch = board[r][c]; + if (ch == '?') + { + return; + } + + // 트라이에 이 문자가 없는 경우 (찾을 단어에 포함되지 않음) + if (node->children[ch - 'a'] == nullptr) + { + return; + } + + // 이 문자가 하나의 단어를 구성하는 경우 + if (node->children[ch - 'a']->isWord) + { + s.push_back(ch); + ans.push_back(s); + s.pop_back(); + node->children[ch - 'a']->isWord = false; // 중복 마킹 방지 + } + + board[r][c] = '?'; // 이미 방문한 곳으로 돌아오지 않도록 입력으로 들어오지 않는 문자로 치환 + + // 상하좌우 탐색 + static int dr[4] = { 1, 0, -1, 0 }; + static int dc[4] = { 0, 1, 0, -1 }; + + for (int dir = 0; dir < 4; ++dir) + { + int nr = r + dr[dir]; + int nc = c + dc[dir]; + s.push_back(ch); + solve(board, node->children[ch - 'a'], s, nr, nc); + s.pop_back(); + } + + board[r][c] = ch; // 원래 문자로 되돌리기 + + // 더 이상 탐색이 필요 없는 곳은 경로 자체를 제거 + // 일단 자식 먼저 판단 + Node*& child = node->children[ch - 'a']; + if (child != nullptr && !child->isWord && child->isEmpty()) + { + child = nullptr; + } + + // 자신도 지울 수 있으면 지움 + if (!node->isWord && node->isEmpty()) + { + node = nullptr; + } + } +}; From 67ccb1af5d84f6df5b14310aea765275fdcf5e39 Mon Sep 17 00:00:00 2001 From: Reese Date: Sat, 6 Jun 2026 22:31:27 +0900 Subject: [PATCH 516/526] [reeseo3o] WEEK 14 solutions (#2630) * week13: meeting-rooms * week14: counting-bits --- counting-bits/reeseo3o.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 counting-bits/reeseo3o.js diff --git a/counting-bits/reeseo3o.js b/counting-bits/reeseo3o.js new file mode 100644 index 0000000000..14006e50d2 --- /dev/null +++ b/counting-bits/reeseo3o.js @@ -0,0 +1,12 @@ +// Time Complexity: O(n) +// Space Complexity: O(n) + +const countBits = (n) => { + const ans = new Array(n + 1).fill(0); + + for (let i = 1; i <= n; i++) { + ans[i] = ans[i>> 1] + (i & 1); + } + + return ans; +}; From 3f27e991be16dd2b26155a6bd96f9ac39460e459 Mon Sep 17 00:00:00 2001 From: "Yunyoung Chung (Lizzie)" <52642281+liza0525@users.noreply.github.com> Date: Sun, 7 Jun 2026 14:23:39 +0900 Subject: [PATCH 517/526] [liza0525] WEEK 14 Solutions (#2629) * [7th batch] week - binary tree level order traversal * [7th batch] week 14 - counting bits --- binary-tree-level-order-traversal/liza0525.py | 56 +++++++++++++++++++ counting-bits/liza0525.py | 16 ++++++ 2 files changed, 72 insertions(+) create mode 100644 binary-tree-level-order-traversal/liza0525.py create mode 100644 counting-bits/liza0525.py diff --git a/binary-tree-level-order-traversal/liza0525.py b/binary-tree-level-order-traversal/liza0525.py new file mode 100644 index 0000000000..350a6c6e46 --- /dev/null +++ b/binary-tree-level-order-traversal/liza0525.py @@ -0,0 +1,56 @@ +# 7기 풀이 +class Solution: + # 풀이 1 - BFS + # 시간 복잡도: O(n) + # - 노드의 개수(n)만큼 모두 탐색하므로 + # 공간 복잡도: O(w) + # - 최악은 한 레벨의 최대 노드 수(w)만큼 queue에 쌓임 + def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: + res = [] + + nodes = deque() + if root: + nodes.appendleft(root) + + while nodes: + childs = deque() + sibling_vals = [] + while nodes: + node = nodes.pop() + if not node: + continue + + sibling_vals.append(node.val) + if node.left: + childs.appendleft(node.left) + if node.right: + childs.appendleft(node.right) + + res.append(sibling_vals) + nodes = childs + + return res + + # 풀이 2 - DFS + # 시간 복잡도: O(n) + # - 노드의 개수(n)만큼 모두 탐색하므로 + # 공간 복잡도: O(h) + # - 재귀 스택이 최대 나무의 높이(h)만큼 쌓임 + def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: + res = [] + + def dfs(node, depth): + if not node: + return + + if len(res) == depth: + res.append([node.val]) + else: + res[depth].append(node.val) + + dfs(node.left, depth + 1) + dfs(node.right, depth + 1) + + dfs(root, 0) + + return res diff --git a/counting-bits/liza0525.py b/counting-bits/liza0525.py new file mode 100644 index 0000000000..7e75f43b75 --- /dev/null +++ b/counting-bits/liza0525.py @@ -0,0 +1,16 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - n의 크기만큼 모든 수에 대한 dp 값을 찾음 +# 공간 복잡도: O(n) +# - n의 크기만큼 dp 어레이를 사용 +class Solution: + def countBits(self, n: int) -> List[int]: + dp = [0 for _ in range(n + 1)] + + for i in range(1, n + 1): + if i % 2 == 1: + dp[i] = dp[i - 1] + 1 + else: + dp[i] = dp[i // 2] + + return dp From 343229938551870e9714ef15e1336adab836f6b7 Mon Sep 17 00:00:00 2001 From: Dale Seo <5466341+daleseo@users.noreply.github.com> Date: Sun, 7 Jun 2026 10:00:10 -0400 Subject: [PATCH 518/526] leetcode-study (#2631) --- binary-tree-level-order-traversal/DaleSeo.rs | 31 ++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 binary-tree-level-order-traversal/DaleSeo.rs diff --git a/binary-tree-level-order-traversal/DaleSeo.rs b/binary-tree-level-order-traversal/DaleSeo.rs new file mode 100644 index 0000000000..a4163f14e7 --- /dev/null +++ b/binary-tree-level-order-traversal/DaleSeo.rs @@ -0,0 +1,31 @@ +// TC: O(n) +// SC: O(n) +use std::cell::RefCell; +use std::collections::VecDeque; +use std::rc::Rc; + +impl Solution { + pub fn level_order(root: Option>>) -> Vec> { + let mut output = Vec::new(); + let mut queue = VecDeque::new(); + if let Some(node) = root { + queue.push_back(node); + } + while !queue.is_empty() { + let mut values = Vec::with_capacity(queue.len()); + for _ in 0..queue.len() { + let node = queue.pop_front().unwrap(); + let node = node.borrow(); + values.push(node.val); + if let Some(left) = node.left.clone() { + queue.push_back(left); + } + if let Some(right) = node.right.clone() { + queue.push_back(right); + } + } + output.push(values); + } + output + } +} From 5f8bcfc4b42d8c3caf4c42cee581bedc608508c3 Mon Sep 17 00:00:00 2001 From: Hyeri-Jung Date: Tue, 9 Jun 2026 08:36:09 +0900 Subject: [PATCH 519/526] [hyeri0903] WEEK 14 Solutions (#2624) * binary-tree-level-order-traversal solution * counting-bits solutions * MedianFinder solutions * word search2 solution * house robber2 solutions * house robber2 solutions --- .../hyeri0903.java | 54 +++++++++++++ counting-bits/hyeri0903.java | 36 +++++++++ find-median-from-data-stream/hyeri0903.java | 40 ++++++++++ house-robber-ii/hyeri0903.java | 41 ++++++++++ word-search-ii/hyeri0903.java | 76 +++++++++++++++++++ 5 files changed, 247 insertions(+) create mode 100644 binary-tree-level-order-traversal/hyeri0903.java create mode 100644 counting-bits/hyeri0903.java create mode 100644 find-median-from-data-stream/hyeri0903.java create mode 100644 house-robber-ii/hyeri0903.java create mode 100644 word-search-ii/hyeri0903.java diff --git a/binary-tree-level-order-traversal/hyeri0903.java b/binary-tree-level-order-traversal/hyeri0903.java new file mode 100644 index 0000000000..962d93a47b --- /dev/null +++ b/binary-tree-level-order-traversal/hyeri0903.java @@ -0,0 +1,54 @@ +/** + * 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 List> levelOrder(TreeNode root) { + /** + 1.문제: 레벨순으로 왼쪽에서 오른쪽으로 노드 순회 + 2.constraints: num of nodes min = 0, max = 2000 + 3.solution: bfs, queue + -time complexity: O(n) - 노드 수 + -space complexity: O(n) - 전체 노드를 저장하므로 + */ + List> answer = new ArrayList(); + + if(root == null) { + return new ArrayList(); + } + + Queue
q = new LinkedList(); + q.offer(root); + + while(!q.isEmpty()) { + int size = q.size(); + //동일한 레벨 노드 값들을 담을 리스트 + List currentLevel = new ArrayList(); + + for(int i = 0; i < size; i++) { + TreeNode node = q.poll(); + currentLevel.add(node.val); + + if(node.left != null) { + q.offer(node.left); + } + if(node.right != null) { + q.offer(node.right); + } + } + answer.add(currentLevel); + } + return answer; + } +} diff --git a/counting-bits/hyeri0903.java b/counting-bits/hyeri0903.java new file mode 100644 index 0000000000..5664cb5a12 --- /dev/null +++ b/counting-bits/hyeri0903.java @@ -0,0 +1,36 @@ +class Solution { + public int[] countBits(int n) { + /** + 1.문제: n까지의 수를 2진수로 변경 후 1의 개수를 배열에 저장 + 2.constraints: 최소 O(n logn) 으로 풀 것 + 3.solutions: + - 0~n까지 for문 돌면서 2진수로 변환 -> 변환하면서 1개수 count -> 배열에 저장 + - time complexity: O(n log n) , space: O(n) + */ + + int[] answer = new int[n+1]; + + for(int i = 0; i <= n; i++) { + if(i == 0 || i == 1) { + answer[i] = i; + continue; + } + int count = getNumOfOne(i); + answer[i] = count; + } + return answer; + } + + int getNumOfOne(int n) { + int cnt = 0; + String binary = Integer.toBinaryString(n); + + for(char c: binary.toCharArray()) { + if(c == '1') { + cnt++; + } + } + return cnt; + } + +} diff --git a/find-median-from-data-stream/hyeri0903.java b/find-median-from-data-stream/hyeri0903.java new file mode 100644 index 0000000000..90bfe7f8bf --- /dev/null +++ b/find-median-from-data-stream/hyeri0903.java @@ -0,0 +1,40 @@ +class MedianFinder { + PriorityQueue left; + PriorityQueue right; + + public MedianFinder() { + /** + 리스트를 중간으로 나눠서 절반은 왼쪽, 오른쪽에 저장 + 왼쪽 리스트는 항상 큰 수가 가장 왼쪽(앞)에 오도록 + 오른쪽 리스트는 항상 작은 수가 가장 왼쪽(앞)에 오도록 저장한다. + + */ + left = new PriorityQueue(Collections.reverseOrder()); //max heap + right = new PriorityQueue(); //min heap + + } + + public void addNum(int num) { + left.add(num); + right.add(left.poll()); + + //총 원소 수가 홀수개이면 left size 더 크도록 유지 + if(right.size()> left.size()) { + left.add(right.poll()); + } + } + + public double findMedian() { + if(left.size()> right.size()) { + return left.peek(); + } + return (left.peek() + right.peek()) / 2.0; + } +} + +/** + * Your MedianFinder object will be instantiated and called as such: + * MedianFinder obj = new MedianFinder(); + * obj.addNum(num); + * double param_2 = obj.findMedian(); + */ diff --git a/house-robber-ii/hyeri0903.java b/house-robber-ii/hyeri0903.java new file mode 100644 index 0000000000..efe380be57 --- /dev/null +++ b/house-robber-ii/hyeri0903.java @@ -0,0 +1,41 @@ +class Solution { + public int rob(int[] nums) { + /** + 1.문제: 인접한 집을 털지않고 훔칠 수 있는 최대 금액 반환 + 2.constraints + - nums.length min = 1, max= 100 + - value min = 0, max = 1000 + - 집들은 circle 형태, 인접한 집을 털면 alerting (0번째, 마지막 집 동시에 털 수 없음) + 3.solution + - dp[i] = max(dp[i-1], dp[i-2] + nums[i]) -> 이전값 vs i 번째 털었을 경우 max 값 + - case는 2가지. 1)0집 포함, n-1불포함 2)0집 불포함, n-1 포함 + - time complexity: O(n), space complexity: O(1) + */ + int currentMax = 0; + int n = nums.length; + int[] dp = new int[n-1]; + int[] dp2 = new int[n]; + + if(n == 1) return nums[0]; + if(n == 2) return Math.max(nums[0], nums[1]); + + dp[0] = nums[0]; + dp[1] = Math.max(dp[0], nums[1]); + + //case 1) 0번집 포함, N-1 불포함 + for(int i = 2; i < n-1; i++) { + //i번째 털기 or i번째 안 털기 + dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i]); + } + + dp2[0] = 0; + dp2[1] = nums[1]; + //case 2) 0번집 불포함, N-1 포함 + for(int i = 2; i < n; i++) { + //i번째 털기 or i번째 안 털기 + dp2[i] = Math.max(dp2[i-1], dp2[i-2] + nums[i]); + } + int answer = Math.max(dp[n-2], dp2[n-1]); + return answer; + } +} diff --git a/word-search-ii/hyeri0903.java b/word-search-ii/hyeri0903.java new file mode 100644 index 0000000000..7f562d5840 --- /dev/null +++ b/word-search-ii/hyeri0903.java @@ -0,0 +1,76 @@ +class Solution { + /** + * 너무 어려워서 풀이 봤어요 ᅲᅲ + */ + class TrieNode { + TrieNode[] children = new TrieNode[26]; + String word; + } + + List result = new ArrayList(); + int m, n; + char[][] board; + + public List findWords(char[][] board, String[] words) { + this.board = board; + this.m = board.length; + this.n = board[0].length; + + TrieNode root = buildTrie(words); + + for(int i = 0; i < m; i++) { + for(int j = 0; j < n; j++) { + dfs(i, j, root); + } + } + return result; + } + private TrieNode buildTrie(String[] words) { + TrieNode root = new TrieNode(); + + for(String word : words) { + TrieNode curr = root; + + for(char ch : word.toCharArray()) { + int idx = ch - 'a'; + + if(curr.children[idx] == null) { + curr.children[idx] = new TrieNode(); + } + + curr = curr.children[idx]; + } + + curr.word = word; + } + + return root; + } + void dfs(int i, int j, TrieNode node) { + //boundary check + if(i < 0 || i>= m || j < 0 || j>= n) return; + //이미 방문했으면 return + if(board[i][j] == '#') return; + + char ch = board[i][j]; + if(node.children[ch - 'a'] == null) return; + + node = node.children[ch - 'a']; + + if(node.word != null) { + result.add(node.word); + node.word = null; //중복방지 체크 + } + + board[i][j] = '#'; //방문 체크 + + dfs(i+1, j, node); + dfs(i-1, j, node); + dfs(i, j+1, node); + dfs(i, j-1, node); + + //backtracking + board[i][j] = ch; + } + +} From c6a6faef076191c4905ab6f4bc84f6044b054b2b Mon Sep 17 00:00:00 2001 From: Ju Hwijung Date: 2026年6月12日 22:04:08 +0900 Subject: [PATCH 520/526] =?UTF-8?q?15=EC=A3=BC=EC=B0=A8=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=92=80=EC=9D=B4=205=EA=B0=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20(#2636)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- alien-dictionary/hwi-middle.cpp | 95 +++++++++++++++++++ .../hwi-middle.cpp | 44 +++++++++ longest-palindromic-substring/hwi-middle.cpp | 57 +++++++++++ rotate-image/hwi-middle.cpp | 19 ++++ subtree-of-another-tree/hwi-middle.cpp | 44 +++++++++ 5 files changed, 259 insertions(+) create mode 100644 alien-dictionary/hwi-middle.cpp create mode 100644 construct-binary-tree-from-preorder-and-inorder-traversal/hwi-middle.cpp create mode 100644 longest-palindromic-substring/hwi-middle.cpp create mode 100644 rotate-image/hwi-middle.cpp create mode 100644 subtree-of-another-tree/hwi-middle.cpp diff --git a/alien-dictionary/hwi-middle.cpp b/alien-dictionary/hwi-middle.cpp new file mode 100644 index 0000000000..f5c6d20085 --- /dev/null +++ b/alien-dictionary/hwi-middle.cpp @@ -0,0 +1,95 @@ +class Solution +{ +public: + string alienOrder(vector& words) + { + unordered_map> graph; // 해당 문자 뒤에 와야하는 문자들 + unordered_map state; // DFS 방문 상태: 0(방문 안함), 1(방문 중), 2(방문 완료) + + // 모든 문자를 그래프에 넣음 + for (const auto& word : words) + { + for (char c : word) + { + graph[c]; + } + } + + // 인접한 문자 비교 + for (int i = 0; i < words.size() - 1; ++i) + { + string& a = words[i]; + string& b = words[i + 1]; + + int len = min(a.size(), b.size()); + + int j = 0; + while (j < len && a[j] == b[j]) + { + ++j; + } + + // 마지막까지 동일한 경우 + if (j == len) + { + // 사전순인데 앞 단어가 더 길면 규칙 위반 + if (a.size()> b.size()) + { + return ""; + } + + // 정상이지만 정보가 없음 + continue; + } + + // 다른 문자를 찾은 경우 (그 부분만 의미있음) + graph[a[j]].insert(b[j]); + } + + string result; + + // 이제 위상정렬 -> 후위순회 dfs 후 순서 뒤집기 + function dfs = [&](char node) + { + if (state[node] == 1) + { + return false; // 사이클 + } + + if (state[node] == 2) + { + return true; + } + + state[node] = 1; + + for (char next : graph[node]) + { + if (!dfs(next)) + { + return false; + } + } + + state[node] = 2; + result.push_back(node); + + return true; + }; + + for (auto& [node, _] : graph) + { + if (state[node] == 0) + { + if (!dfs(node)) + { + return ""; + } + } + } + + reverse(result.begin(), result.end()); + + return result; + } +}; diff --git a/construct-binary-tree-from-preorder-and-inorder-traversal/hwi-middle.cpp b/construct-binary-tree-from-preorder-and-inorder-traversal/hwi-middle.cpp new file mode 100644 index 0000000000..71716d98f6 --- /dev/null +++ b/construct-binary-tree-from-preorder-and-inorder-traversal/hwi-middle.cpp @@ -0,0 +1,44 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ + + // 전위 순회의 첫 번째로 나오는 노드가 루트라는 성질을 활용 + // 중위 순회에서 루트를 찾아 좌우 구분 가능 +class Solution { +public: + TreeNode* buildTree(vector& preorder, vector& inorder) { + return buildTreeWithSpan(span(preorder), span(inorder)); + } + + TreeNode* buildTreeWithSpan(span preorder, span inorder) + { + if (preorder.size() == 0) + { + return nullptr; + } + + int rootVal = preorder[0]; + TreeNode* rootNode = new TreeNode(rootVal); + if (preorder.size() == 1) + { + return rootNode; + } + int leftSubtreeSize = find(inorder.begin(), inorder.end(), rootVal) - inorder.begin(); + int n = inorder.size(); + span leftPreorder = preorder.subspan(1, leftSubtreeSize); + span leftInorder = inorder.subspan(0, leftSubtreeSize); + span rightPreorder = preorder.subspan(leftSubtreeSize + 1, n - leftSubtreeSize - 1); + span rightInorder = inorder.subspan(leftSubtreeSize + 1, n - leftSubtreeSize - 1); + rootNode->left = buildTreeWithSpan(leftPreorder, leftInorder); + rootNode->right = buildTreeWithSpan(rightPreorder, rightInorder); + return rootNode; + } +}; diff --git a/longest-palindromic-substring/hwi-middle.cpp b/longest-palindromic-substring/hwi-middle.cpp new file mode 100644 index 0000000000..00728824aa --- /dev/null +++ b/longest-palindromic-substring/hwi-middle.cpp @@ -0,0 +1,57 @@ +// Editorial 참고 - 마나커 알고리즘 +class Solution { +public: + string longestPalindrome(string s) { + string s_prime = "#"; + for (char c : s) + { + s_prime += c; + s_prime += "#"; + } + + int n = s_prime.length(); + vector palindrome_radii(n, 0); + int center = 0; + int radius = 0; + + for (int i = 0; i < n; i++) + { + int mirror = 2 * center - i; + + if (i < radius) + { + palindrome_radii[i] = min(radius - i, palindrome_radii[mirror]); + } + + while (i + 1 + palindrome_radii[i] < n && + i - 1 - palindrome_radii[i]>= 0 && + s_prime[i + 1 + palindrome_radii[i]] == s_prime[i - 1 - palindrome_radii[i]] + ) + { + palindrome_radii[i]++; + } + + if (i + palindrome_radii[i]> radius) + { + center = i; + radius = i + palindrome_radii[i]; + } + } + + int max_length = 0; + int center_index = 0; + for (int i = 0; i < n; i++) + { + if (palindrome_radii[i]> max_length) + { + max_length = palindrome_radii[i]; + center_index = i; + } + } + + int start_index = (center_index - max_length) / 2; + string longest_palindrome = s.substr(start_index, max_length); + + return longest_palindrome; + } +}; diff --git a/rotate-image/hwi-middle.cpp b/rotate-image/hwi-middle.cpp new file mode 100644 index 0000000000..720ef661e6 --- /dev/null +++ b/rotate-image/hwi-middle.cpp @@ -0,0 +1,19 @@ +class Solution { +public: + void rotate(vector>& matrix) { + int n = matrix.size(); + // transpose 후 뒤집으면 90도 회전 + for (int i = 0; i < n; ++i) + { + for (int j = i; j < n; ++j) + { + swap(matrix[i][j], matrix[j][i]); + } + } + + for (int i = 0; i < n; ++i) + { + reverse(matrix[i].begin(), matrix[i].end()); + } + } +}; diff --git a/subtree-of-another-tree/hwi-middle.cpp b/subtree-of-another-tree/hwi-middle.cpp new file mode 100644 index 0000000000..a9dcb841c5 --- /dev/null +++ b/subtree-of-another-tree/hwi-middle.cpp @@ -0,0 +1,44 @@ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode() : val(0), left(nullptr), right(nullptr) {} + * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} + * }; + */ +class Solution { +public: + bool isSubtree(TreeNode* root, TreeNode* subRoot) { + if (root == nullptr || subRoot == nullptr) + { + return root == subRoot; + } + + if (isSameTree(root, subRoot)) + { + return true; + } + + return isSubtree(root->left, subRoot) + || isSubtree(root->right, subRoot); + } + + bool isSameTree(TreeNode* a, TreeNode* b) + { + if (a == nullptr || b == nullptr) + { + return a == b; + } + + if (a->val != b->val) + { + return false; + } + + return isSameTree(a->left, b->left) + && isSameTree(a->right, b->right); + } +}; From 726313cea18f1278ac6099e2db9a8f6fbb3cb9de Mon Sep 17 00:00:00 2001 From: "Yunyoung Chung (Lizzie)" <52642281+liza0525@users.noreply.github.com> Date: 2026年6月13日 09:04:25 +0900 Subject: [PATCH 521/526] [liza0525] WEEK 15 Solutions (#2637) * [7th batch] week 15 - subtree of another tree * [7th batch] week 15 - constract binary tree from preorder and inorder traversla * [7th batch] week 15 - longest palindromic substring * [7th batch] week 15 - rotate image * [7th batch] week 14 - house robber ii --- .../liza0525.py | 29 +++++++++++++++++ house-robber-ii/liza0525.py | 23 +++++++++++++ longest-palindromic-substring/liza0525.py | 31 ++++++++++++++++++ rotate-image/liza0525.py | 21 ++++++++++++ subtree-of-another-tree/liza0525.py | 32 +++++++++++++++++++ 5 files changed, 136 insertions(+) create mode 100644 construct-binary-tree-from-preorder-and-inorder-traversal/liza0525.py create mode 100644 house-robber-ii/liza0525.py create mode 100644 longest-palindromic-substring/liza0525.py create mode 100644 rotate-image/liza0525.py create mode 100644 subtree-of-another-tree/liza0525.py diff --git a/construct-binary-tree-from-preorder-and-inorder-traversal/liza0525.py b/construct-binary-tree-from-preorder-and-inorder-traversal/liza0525.py new file mode 100644 index 0000000000..274a20c11b --- /dev/null +++ b/construct-binary-tree-from-preorder-and-inorder-traversal/liza0525.py @@ -0,0 +1,29 @@ +class Solution: + def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]: + inorder_idx_map = { + val: idx + for idx, val in enumerate(inorder) + } + + def dfs(pre_start, pre_end, in_start, in_end): + if pre_start> pre_end or in_start> in_end: + return None + + node = TreeNode() + node.val = preorder[pre_start] + + in_idx = inorder_idx_map[node.val] + left_size = in_idx - in_start + + node.left = dfs( + pre_start + 1, pre_start + left_size, + in_start, in_idx - 1, + ) + node.right = dfs( + pre_start + left_size + 1, pre_end, + in_idx + 1, in_end, + ) + + return node + + return dfs(0, len(preorder) - 1, 0, len(inorder) - 1) diff --git a/house-robber-ii/liza0525.py b/house-robber-ii/liza0525.py new file mode 100644 index 0000000000..37ac284015 --- /dev/null +++ b/house-robber-ii/liza0525.py @@ -0,0 +1,23 @@ +class Solution: + def rob(self, nums: List[int]) -> int: + if len(nums) == 1: + return nums[0] + + dp1 = [0 for _ in range(len(nums))] + dp2 = [0 for _ in range(len(nums))] + + for i in range(len(nums)): + if i == 0 or i == 1: + dp1[i] = nums[i] + else: + dp1[i] = nums[i] + max(dp1[:i - 1]) + + nums = nums[1:] + [nums[0]] + + for i in range(len(nums)): + if i == 0 or i == 1: + dp2[i] = nums[i] + else: + dp2[i] = nums[i] + max(dp2[:i - 1]) + + return max(dp1[:-1] + dp2[:-1]) diff --git a/longest-palindromic-substring/liza0525.py b/longest-palindromic-substring/liza0525.py new file mode 100644 index 0000000000..701b7b008d --- /dev/null +++ b/longest-palindromic-substring/liza0525.py @@ -0,0 +1,31 @@ +class Solution: + def longestPalindrome(self, s: str) -> str: + res = "" + len_res = 0 + len_s = len(s) + + for i in range(len_s): + left, right = i, i + while 0 <= left and right < len_s: + if s[left] == s[right]: + if right - left + 1> len_res: + res = s[left:right + 1] + len_res = right - left + 1 + left -= 1 + right += 1 + else: + break + + for i in range(len_s - 1): + left, right = i, i + 1 + while 0 <= left and right < len_s: + if s[left] == s[right]: + if right - left + 1> len_res: + res = s[left:right + 1] + len_res = right - left + 1 + left -= 1 + right += 1 + else: + break + + return res diff --git a/rotate-image/liza0525.py b/rotate-image/liza0525.py new file mode 100644 index 0000000000..5c7c839b48 --- /dev/null +++ b/rotate-image/liza0525.py @@ -0,0 +1,21 @@ +class Solution: + def rotate(self, matrix: List[List[int]]) -> None: + """ + Do not return anything, modify matrix in-place instead. + """ + len_matrix = len(matrix) + + + for i in range(len_matrix // 2): + for j in range(i, len_matrix - i - 1): + ( + matrix[i][j], + matrix[j][len_matrix - i - 1], + matrix[len_matrix - i - 1][len_matrix - j - 1], + matrix[len_matrix - j - 1][i], + ) = ( + matrix[len_matrix - j - 1][i], + matrix[i][j], + matrix[j][len_matrix - i - 1], + matrix[len_matrix - i - 1][len_matrix - j - 1], + ) diff --git a/subtree-of-another-tree/liza0525.py b/subtree-of-another-tree/liza0525.py new file mode 100644 index 0000000000..22309c55b4 --- /dev/null +++ b/subtree-of-another-tree/liza0525.py @@ -0,0 +1,32 @@ +# Definition for a binary tree node. +# class TreeNode: +# def __init__(self, val=0, left=None, right=None): +# self.val = val +# self.left = left +# self.right = right +class Solution: + def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool: + def check_same(node, subnode): + if not node and not subnode: + return True + elif node and subnode: + + if node.val != subnode.val: + return False + + return ( + check_same(node.left, subnode.left) + and check_same(node.right, subnode.right) + ) + return False + + def dfs(node): + if not node: + return False + + if node.val == subRoot.val and check_same(node, subRoot): + return True + + return dfs(node.left) or dfs(node.right) + + return dfs(root) From 756d27d7a8148253f35bb5a8c48f1d31ab44bab7 Mon Sep 17 00:00:00 2001 From: Hyeri-Jung Date: 2026年6月13日 16:45:40 +0900 Subject: [PATCH 522/526] [hyeri0903] WEEK 15 Solutions (#2635) * subtree of another tree solution * longest-palindromic-substring solutions * construct-binary-tree-from-preorder-and-inorder-traversal solution * rotate image solution --- .../hyeri0903.java | 60 +++++++++++++++++++ longest-palindromic-substring/hyeri0903.java | 44 ++++++++++++++ rotate-image/hyeri0903.java | 42 +++++++++++++ subtree-of-another-tree/hyeri0903.java | 46 ++++++++++++++ 4 files changed, 192 insertions(+) create mode 100644 construct-binary-tree-from-preorder-and-inorder-traversal/hyeri0903.java create mode 100644 longest-palindromic-substring/hyeri0903.java create mode 100644 rotate-image/hyeri0903.java create mode 100644 subtree-of-another-tree/hyeri0903.java diff --git a/construct-binary-tree-from-preorder-and-inorder-traversal/hyeri0903.java b/construct-binary-tree-from-preorder-and-inorder-traversal/hyeri0903.java new file mode 100644 index 0000000000..873918c06f --- /dev/null +++ b/construct-binary-tree-from-preorder-and-inorder-traversal/hyeri0903.java @@ -0,0 +1,60 @@ +/** + * 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 TreeNode buildTree(int[] preorder, int[] inorder) { + /** + 1.preorder, inorder array를 기반으로 binary tree return + 2.constraints + - 모두 unique values + - length min = 1, max = 3000 + 3.solutions + - Root node = preorder[0] + - inorder 에서 root node 위치 찾기 -> root node 위치 left/right node + - inorder 에서 구한 left/right node 수로 preorder array 에서 left/right 나눔 + + */ + + return buildTree(preorder, 0, preorder.length - 1, + inorder, 0, inorder.length - 1); + + } + private TreeNode buildTree(int[] preorder, int preStart, int preEnd, + int[] inorder, int inStart, int inEnd) { + if(preStart> preEnd || inStart> inEnd) return null; + + //preorder 첫번째 값 = root node value + int rootVal = preorder[preStart]; + TreeNode root = new TreeNode(rootVal); + + //inorder 에서 root 찾기 + int rootIndex = 0; + for(int i = 0; i TLE 발생 + - expand around center (각 중심에서 양쪽으로 확장하여 체크) + - 길이 = 1 이면 바로 return + Palindrome은 substring 기준이라 전체 문자열 길이와 무관하게 홀수/짝수 케이스가 모두 존재할 수 있기 때문에, 두 경우를 모두 확인해야 합니다. + + Time: O(n2) -> palindrome method 에서 최대 n 번 돌 수 있으므로 + Space: O(1) + */ + + int n = s.length(); + if(n == 1) return s; + //가운데 문자에서 시작 e.g "babad" n = 5, answer = "b" + String answer = ""; + + for(int i = 0; i < n; i++) { + //홀수 e.g "b". 중심이 1개 + String odd = palindrome(s, i, i); + //짝수 e.g. "ab". 중심이 2개 + String even = palindrome(s, i, i + 1); + + String longer = odd.length()> even.length() ? odd : even; + if(longer.length()> answer.length()) { + answer = longer; + } + } + return answer; + } + String palindrome(String s, int start, int end) { + while(start>= 0 && end < s.length() && s.charAt(start) == s.charAt(end)) { + start--; + end++; + } + return s.substring(start+1, end); + } +} diff --git a/rotate-image/hyeri0903.java b/rotate-image/hyeri0903.java new file mode 100644 index 0000000000..00f8eeac05 --- /dev/null +++ b/rotate-image/hyeri0903.java @@ -0,0 +1,42 @@ +class Solution { + public void rotate(int[][] matrix) { + /** + 1.90도 시계방향으로 회전한 matrix return + 2.constraints : in-place 로 rotate 할 것 + 3.solution: 2단계 처리 + 1) 대각선 기준 뒤집기 transpose, matrix[i][j] => matrix[j][i] + 2) 각 행 reverse + time complexity : O(n^2), space: O(1) + */ + + int n = matrix.length; + + //1.transpose + for(int i = 0; i < n; i++) { + for(int j = i+1; j < n; j++) { + int tmp = matrix[i][j]; + matrix[i][j] = matrix[j][i]; + matrix[j][i] = tmp; + } + } + + //2.reverse each row + for(int i = 0; i < n; i++) { + reverse(matrix[i]); + } + } + + void reverse(int[] row) { + int left = 0; + int right = row.length - 1; + + while(left < right) { + int tmp = row[left]; + row[left] = row[right]; + row[right] = tmp; + + left++; + right--; + } + } +} diff --git a/subtree-of-another-tree/hyeri0903.java b/subtree-of-another-tree/hyeri0903.java new file mode 100644 index 0000000000..f91e00d1bb --- /dev/null +++ b/subtree-of-another-tree/hyeri0903.java @@ -0,0 +1,46 @@ +/** + * 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 isSubtree(TreeNode root, TreeNode subRoot) { + /** + 1.root 트리의 subtree가 subRoot tree 이면 true 아니면 false return + 2.constraints + - subRoot tree 가 존재하는데 거기에 자식 노드가 추가로 있으면 안됨 + - 자기 자신 root tree = subRoot tree 일수도 있음 + 3.solution + - 재귀함수로 subTree 찾고 subRoot 의 트리와 동일한지 검사 + - root 트리 노드 수 : n, subRoot 트리 노드 수 : m + - timeComplexity : O(nm) + */ + if(root == null) return false; + + //먼저 트리가 동일한지 체크 -> left subTree check -> right subTree check + return isSameTree(root, subRoot) + || isSubtree(root.left, subRoot) + || isSubtree(root.right, subRoot); + + } + private boolean isSameTree(TreeNode a, TreeNode b) { + //둘 다 null + if (a == null && b == null) return true; + //둘중 하나만 null + if (a == null || b == null) return false; + //값이 다른 경우 + if(a.val != b.val) return false; + //현재 값이 다르면 왼쪽끼리, 오른쪽끼리 비교, 모두 같아야 true return + return isSameTree(a.left, b.left) && isSameTree(a.right, b.right); + } +} From 8790d506c88add354719ba3fdcbb47ca270d9927 Mon Sep 17 00:00:00 2001 From: hui Date: 2026年6月15日 10:17:03 +0900 Subject: [PATCH 523/526] [juhui-jeong] WEEK 14 (#2623) * WEEK 12: Solutions * add: complexity * add:279 * add: 248 * add: 288 * WEEK 13: Solutions * add: 257 * add: 277 * WEEK 14: Solutions --- counting-bits/juhui-jeong.java | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/counting-bits/juhui-jeong.java b/counting-bits/juhui-jeong.java index 8f6a875c6f..04fccd8fe5 100644 --- a/counting-bits/juhui-jeong.java +++ b/counting-bits/juhui-jeong.java @@ -1,5 +1,6 @@ - +/* +이전 풀이 class Solution { public int[] countBits(int n) { ArrayList list = new ArrayList(); @@ -22,3 +23,32 @@ public int[] countBits(int n) { return ans; } } +*/ +/* +시간 복잡도: O(n log n) +공간 복잡도: O(n) + */ +class Solution { + public int[] countBits(int n) { + // 0부터 n까지의 이진수를 만든다. + // 이진수로 변환된 수에서 1의 갯수를 카운팅한다. + // 0부터 n까지 1의 갯수를 카운팅한 것을 배열로 만들어 반환한다. 이때 배열의 길이는 n+1. + int[] result = new int[n+1]; + + for (int i = 0; i <= n; i++) { + int num = divideTwo(i, 0); + result[i] = num; + } + return result; + } + + private int divideTwo(int n, int remainderCnt) { + int divideNum = n/2; + int remainder = n%2; + + int calcualteReminderNum = remainder + remainderCnt; + if (divideNum == 0) return calcualteReminderNum; + + return divideTwo(divideNum, calcualteReminderNum); + } +} From bcaa485156fd00eec7c99ca3f0e77288c91e9084 Mon Sep 17 00:00:00 2001 From: "E.M. Lee" <54928040+jamiebase@users.noreply.github.com> Date: 2026年6月15日 10:17:28 +0900 Subject: [PATCH 524/526] [jamiebase] WEEK 14 Solutions (#2632) * Add solution for checking if two binary trees are the same * add: implement lowest common ancestor for binary search tree * Implement solution for House Robber II problem * Implement solution for Subtree of Another Tree problem --- house-robber-ii/jamiebase.py | 32 ++++++++++++++++++++++++++++ subtree-of-another-tree/jamiebase.py | 28 ++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 house-robber-ii/jamiebase.py create mode 100644 subtree-of-another-tree/jamiebase.py diff --git a/house-robber-ii/jamiebase.py b/house-robber-ii/jamiebase.py new file mode 100644 index 0000000000..131e38d31f --- /dev/null +++ b/house-robber-ii/jamiebase.py @@ -0,0 +1,32 @@ +""" +# Intuition +집이 원형으로 놓여있기 때문에 첫 번째 집을 터는 경우, 안 터는 경우일 때로 나누어 해를 구하고, +두 경우에서 최댓값 해를 구한다. + +# Complexity +n은 nums의 길이라고 할 때, +- Time complexity: O(N) +- Space complexity: O(N) + +""" + + +class Solution: + def rob(self, nums: list[int]) -> int: + n = len(nums) + if n == 1: + return nums[0] + + # 첫 번째 집을 터는 경우 + dp1 = [0] * n + dp1[0] = dp1[1] = nums[0] + for i in range(2, n - 1): + dp1[i] = max(dp1[i - 2] + nums[i], dp1[i - 1]) + + # 첫 번째 집을 안 터는 경우 + dp2 = [0] * n + dp2[1] = nums[1] + for j in range(2, n): + dp2[j] = max(dp2[j - 2] + nums[j], dp2[j - 1]) + + return max(max(dp1), max(dp2)) diff --git a/subtree-of-another-tree/jamiebase.py b/subtree-of-another-tree/jamiebase.py new file mode 100644 index 0000000000..6a764abc17 --- /dev/null +++ b/subtree-of-another-tree/jamiebase.py @@ -0,0 +1,28 @@ +""" +# Approach +매 노드마다 같은 Tree인지 비교합니다. + +# Complexity +- Time complexity: 양 트리의 노드를 하나씩 다 비교해야 하므로 최악의 경우 O(N*M) +- Space complexity: root 트리 높이가 H라고 할 때 O(H)만큼 재귀 스택이 쌓임 +""" + + +class Solution: + def isSameTree(self, a, b): + if not a and not b: + return True + if not a or not b: + return False + if a.val != b.val: + return False + return self.isSameTree(a.left, b.left) and self.isSameTree(a.right, b.right) + + def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool: + if not root: + return False + + if self.isSameTree(root, subRoot): + return True + + return self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot) From 84fbff4ef38f0e3f95b2ebb72d10fce21736569d Mon Sep 17 00:00:00 2001 From: Reese Date: 2026年6月15日 10:18:02 +0900 Subject: [PATCH 525/526] [reeseo3o] WEEK 15 Solutions (#2638) * week15: subtree-of-another-tree * style: fix lint in subtree-of-another-tree --- subtree-of-another-tree/reeseo3o.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 subtree-of-another-tree/reeseo3o.js diff --git a/subtree-of-another-tree/reeseo3o.js b/subtree-of-another-tree/reeseo3o.js new file mode 100644 index 0000000000..c66a406708 --- /dev/null +++ b/subtree-of-another-tree/reeseo3o.js @@ -0,0 +1,18 @@ +// Time Complexity: O(n*m) +// Space Complexity: O(n+m) + +const isSubtree = (root, subRoot) => { + const isSame = (a, b) => { + if (!a && !b) return true; + if (!a || !b) return false; + if (a.val !== b.val) return false; + return isSame(a.left, b.left) && isSame(a.right, b.right); + }; + + if (!root) return false; + return ( + isSame(root, subRoot) || + isSubtree(root.left, subRoot) || + isSubtree(root.right, subRoot) + ); +}; From 4b7a233740c2a8b3fcba127ddb8057a55801cb99 Mon Sep 17 00:00:00 2001 From: Dale Seo <5466341+daleseo@users.noreply.github.com> Date: 2026年6月14日 21:18:26 -0400 Subject: [PATCH 526/526] rotate-image (#2639) --- rotate-image/DaleSeo.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 rotate-image/DaleSeo.rs diff --git a/rotate-image/DaleSeo.rs b/rotate-image/DaleSeo.rs new file mode 100644 index 0000000000..cf52350312 --- /dev/null +++ b/rotate-image/DaleSeo.rs @@ -0,0 +1,19 @@ +// TC: O(n^2) +// SC: O(1) +impl Solution { + pub fn rotate(matrix: &mut Vec>) { + let n = matrix.len(); + + for i in 0..n { + for j in (i + 1)..n { + let tmp = matrix[i][j]; + matrix[i][j] = matrix[j][i]; + matrix[j][i] = tmp; + } + } + + for row in matrix.iter_mut() { + row.reverse(); + } + } +}

AltStyle によって変換されたページ (->オリジナル) /