-
-
Notifications
You must be signed in to change notification settings - Fork 195
[shinsj4653] Week 03 Solutions #1272
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
04d4401
feat: review "validate-binary-search-tree"
shinsj4653 e89b1a7
feat: add Week 03 problems
shinsj4653 ef67ff9
feat: add maximum-subarray solution
shinsj4653 31235d2
feat: add decode-ways solution
shinsj4653 cd066f6
feat: add combination-sum solution
shinsj4653 8e3b29e
fix: modify code for linelint check
shinsj4653 eedb8e6
feat: add valid-palindrome solution
shinsj4653 c16c8b3
feat: add number-of-1-bits solution
shinsj4653 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
""" | ||
[문제풀이] | ||
# 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중복 없애려는 구현방법도 실패.. | ||
|
||
정답 참고 | ||
|
||
[회고] | ||
|
||
다시 풀면서 막힌 포인트 | ||
|
||
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) | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
""" | ||
[문제풀이] | ||
# 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] | ||
|
||
numDecodings("2266") | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
""" | ||
[문제풀이] | ||
# 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] | ||
|
||
return max(nums) | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +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 | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing closing parenthesis in the int conversion. Consider updating the line to 'num = int(s[start_idx:start_idx + i])'.
Copilot uses AI. Check for mistakes.