From 04d4401bc6d6b0b8ff92211e2ce3738c7610df1a Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Sat, 12 Apr 2025 23:21:17 +0900 Subject: [PATCH 1/8] feat: review "validate-binary-search-tree" --- valid-palindrome/shinsj4653.py | 13 +++++++++++++ validate-binary-search-tree/shinsj4653.py | 3 +-- 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 valid-palindrome/shinsj4653.py diff --git a/valid-palindrome/shinsj4653.py b/valid-palindrome/shinsj4653.py new file mode 100644 index 000000000..f1a7915b4 --- /dev/null +++ b/valid-palindrome/shinsj4653.py @@ -0,0 +1,13 @@ +""" +[문제풀이] +# Inputs + +# Outputs + +# Constraints + +# Ideas + +[회고] + +""" \ No newline at end of file diff --git a/validate-binary-search-tree/shinsj4653.py b/validate-binary-search-tree/shinsj4653.py index 070c63a0a..b44ecb08e 100644 --- a/validate-binary-search-tree/shinsj4653.py +++ b/validate-binary-search-tree/shinsj4653.py @@ -73,8 +73,7 @@ def isValidBST(self, root: Optional[TreeNode]) -> bool: 결국 풀이 참고 [회고] - - +상한값, 하한값 까지 넘기는 사고 장착하기! 복습 또 복습! """ # Definition for a binary tree node. From e89b1a7802dbe095aad4e1f0084c347843256a3c Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Sat, 12 Apr 2025 23:23:28 +0900 Subject: [PATCH 2/8] feat: add Week 03 problems --- combination-sum/shinsj4653.py | 13 +++++++++++++ decode-ways/shinsj4653.py | 13 +++++++++++++ maximum-subarray/shinsj4653.py | 13 +++++++++++++ number-of-1-bits/shinsj4653.py | 13 +++++++++++++ 4 files changed, 52 insertions(+) create mode 100644 combination-sum/shinsj4653.py create mode 100644 decode-ways/shinsj4653.py create mode 100644 maximum-subarray/shinsj4653.py create mode 100644 number-of-1-bits/shinsj4653.py diff --git a/combination-sum/shinsj4653.py b/combination-sum/shinsj4653.py new file mode 100644 index 000000000..f1a7915b4 --- /dev/null +++ b/combination-sum/shinsj4653.py @@ -0,0 +1,13 @@ +""" +[문제풀이] +# Inputs + +# Outputs + +# Constraints + +# Ideas + +[회고] + +""" \ No newline at end of file diff --git a/decode-ways/shinsj4653.py b/decode-ways/shinsj4653.py new file mode 100644 index 000000000..f1a7915b4 --- /dev/null +++ b/decode-ways/shinsj4653.py @@ -0,0 +1,13 @@ +""" +[문제풀이] +# Inputs + +# Outputs + +# Constraints + +# Ideas + +[회고] + +""" \ No newline at end of file diff --git a/maximum-subarray/shinsj4653.py b/maximum-subarray/shinsj4653.py new file mode 100644 index 000000000..f1a7915b4 --- /dev/null +++ b/maximum-subarray/shinsj4653.py @@ -0,0 +1,13 @@ +""" +[문제풀이] +# Inputs + +# Outputs + +# Constraints + +# Ideas + +[회고] + +""" \ No newline at end of file diff --git a/number-of-1-bits/shinsj4653.py b/number-of-1-bits/shinsj4653.py new file mode 100644 index 000000000..f1a7915b4 --- /dev/null +++ b/number-of-1-bits/shinsj4653.py @@ -0,0 +1,13 @@ +""" +[문제풀이] +# Inputs + +# Outputs + +# Constraints + +# Ideas + +[회고] + +""" \ No newline at end of file From ef67ff958af2c937ccfcb7049c7bf5caafb46c97 Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Fri, 18 Apr 2025 19:52:07 +0900 Subject: [PATCH 3/8] feat: add maximum-subarray solution --- maximum-subarray/shinsj4653.py | 41 ++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/maximum-subarray/shinsj4653.py b/maximum-subarray/shinsj4653.py index f1a7915b4..9bd39b685 100644 --- a/maximum-subarray/shinsj4653.py +++ b/maximum-subarray/shinsj4653.py @@ -1,13 +1,46 @@ """ [문제풀이] # Inputs - +- 정수형 nums # Outputs - +- 부분 배열 중 합이 가장 큰 배열의 합 # Constraints - +- 1 <= nums.length <= 10^5 +- 10^4 <= nums[i] <= 10^4 # Ideas +가장 큰 합을 구하는 방법 +정렬은 당연히 X +10^5가 최대라 O(n) 고려 필요 +-2 1 -3 4 -1 2 1 -5 4 +l, r = 0, 0 -> 움직이면서 + r = 1 +-2 < 1 -> -1 + +-2 -1 -4 0 -1 1 2 -3 1 +1. 누적합? + +-2 1 -2 4 3 5 6 1 5 + +5 4 -1 7 8 +5 9 8 15 23 + +지금까지의 합 보다 다음 원소가 크면 그대로 두고, 아니면 합으로 대체 +=> TC: O(n), SC: O(1) [회고] +먼가..때려 맞춘 느낌이라 해설 참고 +-> +""" + +class Solution: + def maxSubArray(self, nums: List[int]) -> int: + if len(nums) == 1: + return nums[0] + + memo = nums[0] + + for i in range(1, len(nums)): + if nums[i] < nums[i - 1] + nums[i]: + nums[i] += nums[i - 1] -""" \ No newline at end of file + return max(nums) From 31235d2e1624da2110fcf7d62c9f899ccb5e77d3 Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Fri, 18 Apr 2025 21:10:22 +0900 Subject: [PATCH 4/8] feat: add decode-ways solution --- decode-ways/shinsj4653.py | 120 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 116 insertions(+), 4 deletions(-) diff --git a/decode-ways/shinsj4653.py b/decode-ways/shinsj4653.py index f1a7915b4..a8f6539b9 100644 --- a/decode-ways/shinsj4653.py +++ b/decode-ways/shinsj4653.py @@ -1,13 +1,125 @@ """ [문제풀이] # Inputs - +숫자로 구성된 문자열 s # Outputs - +decode 가능한 경우의 수 # Constraints - +1 <= s.length <= 100 +s contains only digits and may contain leading zero(s). # Ideas +모든 경우의 수 -> 1. 우선 완탐 + +11106 -> 1 1 10 6 +가능한 숫자들 : 1~26 +11 10 6 + +진짜 완탐만 가능하지 않나? +1 1 1 0 6 (x) +1 1 1 06 (x) +1 1 10 6 (o) +1 1 106 (x) +11 1 0 6 (x) +10 1 06 (x) + +재귀로 구현하면 될듯 + +n = len(s) +ans = 0 + +def decode(start_idx): + global ans + if start_idx >= n : + return +for i in range(1, 2): + num = int(s[start_idx:start_idx + i] + if i == 1: + if num != 0: + ans += 1 + decode(start_idx + 1) + elif i == 2 : + if s[start_idx:start_idx+i][0] != 0 and 10 <= num <= 26: + ans += 1 + decode(start_idx + 1) + + +2. 완탐 코드 시간 초과 +근데 이거 climbing stairs랑 유사한 문제 아닌가? +1과 2로 오를 수 있는 경우의 수 -> 하지만, 숫자 형태 조건이 걸려있어서 씁.. + +2 +2 +11 +10240 + +3 + + [회고] +첫 제출 코드는 시간초과 발생 +메모이제이션으로 코드 개선 가능 +""" + +## 첫 제출 코드 +class Solution: + def numDecodings(self, s: str) -> int: + n = len(s) + + # ans를 변수로 두고 반환 방식으로 처리 + def decode(start_idx): + if start_idx >= n: + return 1 # 끝에 도달하면 1을 반환 (끝까지 도달하면 유효한 디코딩 방법임) + + ans = 0 + for i in range(1, 3): # 1자리 또는 2자리 숫자를 확인 + if start_idx + i <= n: # 인덱스 범위 확인 + num = int(s[start_idx:start_idx + i]) + if i == 1: + if num != 0: # 1자리 숫자가 0이 아니면 진행 + ans += decode(start_idx + 1) + else: + if 10 <= num <= 26: # 2자리 숫자가 10에서 26 사이일 때 진행 + ans += decode(start_idx + 2) + + return ans + + return decode(0) # 0부터 시작 + +# 두번째 제출 코드 + +class Solution: + def numDecodings(self, s: str) -> int: + memo = {len(s): 1} + n = len(s) + + # ans를 변수로 두고 반환 방식으로 처리 + def dfs(start): + if start in memo: + return memo[start] + + if s[start] == "0": + memo[start] = 0 + elif start + 1 < n and int(s[start:start + 2]) < 27: + memo[start] = dfs(start + 1) + dfs(start + 2) + else: + memo[start] = dfs(start + 1) + + return memo[start] + + return dfs(0) # 0부터 시작 + +# 해설의 Bottom-up 방식이 이해가 안가 디버깅 시도 +class Solution: + def numDecodings(s): + dp = [0] * len(s) + [1] + for start in reversed(range(len(s))): + if s[start] == "0": + dp[start] = 0 + elif start + 1 < len(s) and int(s[start : start + 2]) < 27: + dp[start] = dp[start + 1] + dp[start + 2] + else: + dp[start] = dp[start + 1] + return dp[0] -""" \ No newline at end of file + numDecodings("2266") From cd066f6a163427bd3f2e0d5e13d1dec9092699a3 Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Fri, 18 Apr 2025 23:40:56 +0900 Subject: [PATCH 5/8] feat: add combination-sum solution --- combination-sum/shinsj4653.py | 153 +++++++++++++++++++++++++++++++++- 1 file changed, 150 insertions(+), 3 deletions(-) diff --git a/combination-sum/shinsj4653.py b/combination-sum/shinsj4653.py index f1a7915b4..4fdfc8711 100644 --- a/combination-sum/shinsj4653.py +++ b/combination-sum/shinsj4653.py @@ -1,13 +1,160 @@ """ [문제풀이] # Inputs - +서로 다른 정수 배열 candidates +타겟 정수 target # Outputs - +서로 다른 숫자 조합들(리스트) 담은 리스트 # Constraints +unique combinations 개수: 150 이하 +1 <= candidates.length <= 30 +2 <= candidates[i] <= 40 +All elements of candidates are distinct. +1 <= target <= 40 # Ideas +같은 숫자가 여러번 선택될 수 있음 +[2,3,6,7] -> target = 7 +몇 개의 숫자로 구성되는지를 기준으로? +최소 숫자 : 2, target max : 40 -> 한 조합 당 최대 20개 숫자 + +한 개로 구성: +7 + +두 개 +5 2 +4 3 + +세 개 +2 2 3 + + +2 3 5 -> 8 + +8 0 +7 1 +6 2 +5 3 +4 4 + +1. 한 개인 경우랑 두 개인 경우만 카운트 +재귀 돌면서 후보에 있다면 그 후보 담은 리스트 반환 +점점 올라가면서 return 된 리스트들 더해서 반환 + +근데 구현 방법이 쉽게 떠오르지 않음.. + +결국 어찌저찌 최종 리스트들이 반환되게끔 구현하긴 했지만, dp의 장점도 못살리고, set으로 tuple중복 없애려는 구현방법도 실패.. + +정답 참고 [회고] -""" \ No newline at end of file +다시 풀면서 막힌 포인트 + +1. 재귀 +→ dfs(i, total + num) + +나는 dfs(start, sum(nums)) 로 해버렸다 + +- sum 대신 total + num 으로 지금까지의 합을 갱신하면 더 효율적! +- start를 넣으면 중복 가짓수 발생.. i를 넣어야 중복 없이 카운트 가능 + +⇒ 재귀 풀 때 어떤 값을 인자값으로 넣어야 하는지를 설정하는게 가장 어려운듯..연습 많이 해야할듯.. + + +2. DP +다시 풀면서 막힌 포인트 + +→ dp[num].append(combination + [candidate]) + +나는 dp[num].append(combination + [num]) 을 해버렸다 + +따라서, 후보군들로 이뤄진 후보가 아니라, + +누적된 합이 적용된 리스트들이 후보로 인식되어 최종 반환 리스트에 들어가졌다. +어떤 변수를 어디에 넣어야 할지, 구현 로직(흐름)을 다시 정리! 복습! +""" + +# 1번째 코드 +# from collections import defaultdict +# +# +# class Solution: +# def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: +# ret = [] +# +# if target == 1: +# return ret +# +# elif target == 2: +# if target in candidates: +# ret.append([target]) +# return ret +# +# dp = defaultdict(set) +# +# for num in candidates: +# if num == target: +# ret.append([num]) +# +# candidates = set(candidates) +# +# def dfs(num): +# if num < 2: +# return +# +# if num < 4: +# if num in candidates: +# return [num] +# +# else: +# for i in range(2, num // 2 + 1): +# # dp[num].add(dfs(target - num) + dfs(num)) +# return dfs(num - i) + dfs(i) +# +# for num in range(2, target // 2 + 1): +# print(dfs(target - num) + dfs(num)) +# dp[num].add(tuple(dfs(target - num) + dfs(num))) +# +# temp = set() +# for value in dp.values(): +# print(value) +# # temp.add(value) +# +# for t in temp: +# ret.append(list(t)) +# +# return ret + +# 2번째 코드 : dp 활용 +class Solution: + def combinationSum(candidates, target): + dp = [[] for _ in range(target + 1)] + dp[0] = [[]] + for candidate in candidates: + for num in range(candidate, target + 1): + for combination in dp[num - candidate]: + dp[num].append(combination + [candidate]) + return dp[target] + + combinationSum([2, 3, 5], 8) + +# 3번째 코드 : 재귀 활용 +class Solution: + def combinationSum(candidates, target): + output, nums = [], [] + + def dfs(start, total): + if total > target: + return + if total == target: + return output.append(nums[:]) + for i in range(start, len(candidates)): + num = candidates[i] + nums.append(num) + dfs(i, total + num) + nums.pop() + + dfs(0, 0) + return output + combinationSum([2, 3, 5, 7], 7) From 8e3b29e7decf03e4ce69a9992aa34e09f46b6063 Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Sat, 19 Apr 2025 22:36:41 +0900 Subject: [PATCH 6/8] fix: modify code for linelint check --- combination-sum/shinsj4653.py | 2 ++ decode-ways/shinsj4653.py | 2 ++ maximum-subarray/shinsj4653.py | 2 ++ 3 files changed, 6 insertions(+) diff --git a/combination-sum/shinsj4653.py b/combination-sum/shinsj4653.py index 4fdfc8711..caa5f2861 100644 --- a/combination-sum/shinsj4653.py +++ b/combination-sum/shinsj4653.py @@ -158,3 +158,5 @@ def dfs(start, total): dfs(0, 0) return output combinationSum([2, 3, 5, 7], 7) + + diff --git a/decode-ways/shinsj4653.py b/decode-ways/shinsj4653.py index a8f6539b9..90277d4fe 100644 --- a/decode-ways/shinsj4653.py +++ b/decode-ways/shinsj4653.py @@ -123,3 +123,5 @@ def numDecodings(s): return dp[0] numDecodings("2266") + + diff --git a/maximum-subarray/shinsj4653.py b/maximum-subarray/shinsj4653.py index 9bd39b685..1e6b55db1 100644 --- a/maximum-subarray/shinsj4653.py +++ b/maximum-subarray/shinsj4653.py @@ -44,3 +44,5 @@ def maxSubArray(self, nums: List[int]) -> int: nums[i] += nums[i - 1] return max(nums) + + From eedb8e611eaadccff21be102dd7662dd1339a246 Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Sat, 19 Apr 2025 22:56:30 +0900 Subject: [PATCH 7/8] feat: add valid-palindrome solution --- valid-palindrome/shinsj4653.py | 52 +++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/valid-palindrome/shinsj4653.py b/valid-palindrome/shinsj4653.py index f1a7915b4..df1fb5f75 100644 --- a/valid-palindrome/shinsj4653.py +++ b/valid-palindrome/shinsj4653.py @@ -1,13 +1,57 @@ """ [문제풀이] # Inputs - +- string s # Outputs - +- palindrome 인지에 대한 true, false 여부 # Constraints - +- 1 <= s.length <= 2 * 10^5 +- s consists only of printable ASCII characters. # Ideas +문자열 최대 길이 10^5 -> 2중 for문 불가능 + +우선 s를 순회하며, +- isalpha인 요소라면 lower 화 시켜서 새로운 문자열 p 에 붙이기 +- 그리고 그 p가 p == p[::-1] 이면 true, 아니면 false + +TC: O(n), SC: O(n) [회고] +문제 조건에 all non-alphanumeric characters를 제외한 문자열을 기준으로 +-> 즉, numeric도 고려해야한다! + +너무 쉬운 해결방법인 [::-1]를 쓴 것 같아서, +해설 참고 +-> 투 포인터 + +""" + +class Solution: + def isPalindrome(self, s: str) -> bool: + t = "" + + for c in s: + if c.isalpha(): + t += c.lower() + elif c.isalnum(): + t += c + + return t == t[::-1] + +# 해설: 투 포인터 풀이 +class Solution: + def isPalindrome(s): + low, high = 0, len(s) - 1 + while low < high: + while low < high and not s[low].isalnum(): + low += 1 + while low < high and not s[high].isalnum(): + high -= 1 + if s[low].lower() != s[high].lower(): + return False + low, high = low + 1, high - 1 + return True + + isPalindrome("A man, a plan, a canal: Panama") + -""" \ No newline at end of file From c16c8b396a4fc3bfe3a92ef0cce44ea7e2bef700 Mon Sep 17 00:00:00 2001 From: SEONG JUN SHIN Date: Sat, 19 Apr 2025 23:15:08 +0900 Subject: [PATCH 8/8] feat: add number-of-1-bits solution --- number-of-1-bits/shinsj4653.py | 48 +++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/number-of-1-bits/shinsj4653.py b/number-of-1-bits/shinsj4653.py index f1a7915b4..def9001d0 100644 --- a/number-of-1-bits/shinsj4653.py +++ b/number-of-1-bits/shinsj4653.py @@ -1,13 +1,53 @@ """ [문제풀이] # Inputs - +- 양인 정수 n # Outputs - +- number of set bits => 이진수 값의 1 개수 # Constraints - +- 1 <= n <= 2^31 - 1 # Ideas +1. 반복문 +2로 나눠서 몫 나머지 -> 나머지가 1인지 0인지 체크 +그 몫을 또 2로 나눠서 몫, 나머지 -> + + +11 +2-> 5, 1 +2-> 2, 1 +2-> 1, 0 +2-> 0, 1 + +몫이 0이 될 때 까지 반복 + +TC: log2N? SC: 1 [회고] +시간 복잡도가 log2N인가? +-> O + +해설은 어떤지 궁금 +-> + +""" + +class Solution: + def hammingWeight(self, n: int) -> int: + ret = 0 + while n > 0: + n, bit = n // 2, n % 2 + if bit == 1: + ret += 1 + + return ret + +# 해설 + +class Solution: + def hammingWeight(self, n: int) -> int: + cnt = 0 + while n: + cnt += n & 1 + n >>= 1 + return cnt -""" \ No newline at end of file