Skip to content

Commit ecdad54

Browse files
authored
Merge pull request #1272 from shinsj4653/main
[shinsj4653] Week 03 Solutions
2 parents bd05427 + c16c8b3 commit ecdad54

File tree

6 files changed

+448
-2
lines changed

6 files changed

+448
-2
lines changed

combination-sum/shinsj4653.py

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
"""
2+
[문제풀이]
3+
# Inputs
4+
서로 다른 정수 배열 candidates
5+
타겟 정수 target
6+
# Outputs
7+
서로 다른 숫자 조합들(리스트) 담은 리스트
8+
# Constraints
9+
unique combinations 개수: 150 이하
10+
1 <= candidates.length <= 30
11+
2 <= candidates[i] <= 40
12+
All elements of candidates are distinct.
13+
1 <= target <= 40
14+
15+
# Ideas
16+
같은 숫자가 여러번 선택될 수 있음
17+
[2,3,6,7] -> target = 7
18+
몇 개의 숫자로 구성되는지를 기준으로?
19+
최소 숫자 : 2, target max : 40 -> 한 조합 당 최대 20개 숫자
20+
21+
한 개로 구성:
22+
7
23+
24+
두 개
25+
5 2
26+
4 3
27+
28+
세 개
29+
2 2 3
30+
31+
32+
2 3 5 -> 8
33+
34+
8 0
35+
7 1
36+
6 2
37+
5 3
38+
4 4
39+
40+
1. 한 개인 경우랑 두 개인 경우만 카운트
41+
재귀 돌면서 후보에 있다면 그 후보 담은 리스트 반환
42+
점점 올라가면서 return 된 리스트들 더해서 반환
43+
44+
근데 구현 방법이 쉽게 떠오르지 않음..
45+
46+
결국 어찌저찌 최종 리스트들이 반환되게끔 구현하긴 했지만, dp의 장점도 못살리고, set으로 tuple중복 없애려는 구현방법도 실패..
47+
48+
정답 참고
49+
50+
[회고]
51+
52+
다시 풀면서 막힌 포인트
53+
54+
1. 재귀
55+
→ dfs(i, total + num)
56+
57+
나는 dfs(start, sum(nums)) 로 해버렸다
58+
59+
- sum 대신 total + num 으로 지금까지의 합을 갱신하면 더 효율적!
60+
- start를 넣으면 중복 가짓수 발생.. i를 넣어야 중복 없이 카운트 가능
61+
62+
⇒ 재귀 풀 때 어떤 값을 인자값으로 넣어야 하는지를 설정하는게 가장 어려운듯..연습 많이 해야할듯..
63+
64+
65+
2. DP
66+
다시 풀면서 막힌 포인트
67+
68+
→ dp[num].append(combination + [candidate])
69+
70+
나는 dp[num].append(combination + [num]) 을 해버렸다
71+
72+
따라서, 후보군들로 이뤄진 후보가 아니라,
73+
74+
누적된 합이 적용된 리스트들이 후보로 인식되어 최종 반환 리스트에 들어가졌다.
75+
어떤 변수를 어디에 넣어야 할지, 구현 로직(흐름)을 다시 정리! 복습!
76+
"""
77+
78+
# 1번째 코드
79+
# from collections import defaultdict
80+
#
81+
#
82+
# class Solution:
83+
# def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
84+
# ret = []
85+
#
86+
# if target == 1:
87+
# return ret
88+
#
89+
# elif target == 2:
90+
# if target in candidates:
91+
# ret.append([target])
92+
# return ret
93+
#
94+
# dp = defaultdict(set)
95+
#
96+
# for num in candidates:
97+
# if num == target:
98+
# ret.append([num])
99+
#
100+
# candidates = set(candidates)
101+
#
102+
# def dfs(num):
103+
# if num < 2:
104+
# return
105+
#
106+
# if num < 4:
107+
# if num in candidates:
108+
# return [num]
109+
#
110+
# else:
111+
# for i in range(2, num // 2 + 1):
112+
# # dp[num].add(dfs(target - num) + dfs(num))
113+
# return dfs(num - i) + dfs(i)
114+
#
115+
# for num in range(2, target // 2 + 1):
116+
# print(dfs(target - num) + dfs(num))
117+
# dp[num].add(tuple(dfs(target - num) + dfs(num)))
118+
#
119+
# temp = set()
120+
# for value in dp.values():
121+
# print(value)
122+
# # temp.add(value)
123+
#
124+
# for t in temp:
125+
# ret.append(list(t))
126+
#
127+
# return ret
128+
129+
# 2번째 코드 : dp 활용
130+
class Solution:
131+
def combinationSum(candidates, target):
132+
dp = [[] for _ in range(target + 1)]
133+
dp[0] = [[]]
134+
for candidate in candidates:
135+
for num in range(candidate, target + 1):
136+
for combination in dp[num - candidate]:
137+
dp[num].append(combination + [candidate])
138+
return dp[target]
139+
140+
combinationSum([2, 3, 5], 8)
141+
142+
# 3번째 코드 : 재귀 활용
143+
class Solution:
144+
def combinationSum(candidates, target):
145+
output, nums = [], []
146+
147+
def dfs(start, total):
148+
if total > target:
149+
return
150+
if total == target:
151+
return output.append(nums[:])
152+
for i in range(start, len(candidates)):
153+
num = candidates[i]
154+
nums.append(num)
155+
dfs(i, total + num)
156+
nums.pop()
157+
158+
dfs(0, 0)
159+
return output
160+
combinationSum([2, 3, 5, 7], 7)
161+
162+

decode-ways/shinsj4653.py

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
"""
2+
[문제풀이]
3+
# Inputs
4+
숫자로 구성된 문자열 s
5+
# Outputs
6+
decode 가능한 경우의 수
7+
# Constraints
8+
1 <= s.length <= 100
9+
s contains only digits and may contain leading zero(s).
10+
# Ideas
11+
모든 경우의 수 -> 1. 우선 완탐
12+
13+
11106 -> 1 1 10 6
14+
가능한 숫자들 : 1~26
15+
11 10 6
16+
17+
진짜 완탐만 가능하지 않나?
18+
1 1 1 0 6 (x)
19+
1 1 1 06 (x)
20+
1 1 10 6 (o)
21+
1 1 106 (x)
22+
11 1 0 6 (x)
23+
10 1 06 (x)
24+
25+
재귀로 구현하면 될듯
26+
27+
n = len(s)
28+
ans = 0
29+
30+
def decode(start_idx):
31+
global ans
32+
if start_idx >= n :
33+
return
34+
for i in range(1, 2):
35+
num = int(s[start_idx:start_idx + i]
36+
if i == 1:
37+
if num != 0:
38+
ans += 1
39+
decode(start_idx + 1)
40+
elif i == 2 :
41+
if s[start_idx:start_idx+i][0] != 0 and 10 <= num <= 26:
42+
ans += 1
43+
decode(start_idx + 1)
44+
45+
46+
2. 완탐 코드 시간 초과
47+
근데 이거 climbing stairs랑 유사한 문제 아닌가?
48+
1과 2로 오를 수 있는 경우의 수 -> 하지만, 숫자 형태 조건이 걸려있어서 씁..
49+
50+
2
51+
2
52+
11
53+
10240
54+
55+
3
56+
57+
58+
59+
[회고]
60+
첫 제출 코드는 시간초과 발생
61+
메모이제이션으로 코드 개선 가능
62+
"""
63+
64+
## 첫 제출 코드
65+
class Solution:
66+
def numDecodings(self, s: str) -> int:
67+
n = len(s)
68+
69+
# ans를 변수로 두고 반환 방식으로 처리
70+
def decode(start_idx):
71+
if start_idx >= n:
72+
return 1 # 끝에 도달하면 1을 반환 (끝까지 도달하면 유효한 디코딩 방법임)
73+
74+
ans = 0
75+
for i in range(1, 3): # 1자리 또는 2자리 숫자를 확인
76+
if start_idx + i <= n: # 인덱스 범위 확인
77+
num = int(s[start_idx:start_idx + i])
78+
if i == 1:
79+
if num != 0: # 1자리 숫자가 0이 아니면 진행
80+
ans += decode(start_idx + 1)
81+
else:
82+
if 10 <= num <= 26: # 2자리 숫자가 10에서 26 사이일 때 진행
83+
ans += decode(start_idx + 2)
84+
85+
return ans
86+
87+
return decode(0) # 0부터 시작
88+
89+
# 두번째 제출 코드
90+
91+
class Solution:
92+
def numDecodings(self, s: str) -> int:
93+
memo = {len(s): 1}
94+
n = len(s)
95+
96+
# ans를 변수로 두고 반환 방식으로 처리
97+
def dfs(start):
98+
if start in memo:
99+
return memo[start]
100+
101+
if s[start] == "0":
102+
memo[start] = 0
103+
elif start + 1 < n and int(s[start:start + 2]) < 27:
104+
memo[start] = dfs(start + 1) + dfs(start + 2)
105+
else:
106+
memo[start] = dfs(start + 1)
107+
108+
return memo[start]
109+
110+
return dfs(0) # 0부터 시작
111+
112+
# 해설의 Bottom-up 방식이 이해가 안가 디버깅 시도
113+
class Solution:
114+
def numDecodings(s):
115+
dp = [0] * len(s) + [1]
116+
for start in reversed(range(len(s))):
117+
if s[start] == "0":
118+
dp[start] = 0
119+
elif start + 1 < len(s) and int(s[start : start + 2]) < 27:
120+
dp[start] = dp[start + 1] + dp[start + 2]
121+
else:
122+
dp[start] = dp[start + 1]
123+
return dp[0]
124+
125+
numDecodings("2266")
126+
127+

maximum-subarray/shinsj4653.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"""
2+
[문제풀이]
3+
# Inputs
4+
- 정수형 nums
5+
# Outputs
6+
- 부분 배열 중 합이 가장 큰 배열의 합
7+
# Constraints
8+
- 1 <= nums.length <= 10^5
9+
- 10^4 <= nums[i] <= 10^4
10+
# Ideas
11+
가장 큰 합을 구하는 방법
12+
정렬은 당연히 X
13+
10^5가 최대라 O(n) 고려 필요
14+
-2 1 -3 4 -1 2 1 -5 4
15+
l, r = 0, 0 -> 움직이면서
16+
r = 1
17+
-2 < 1 -> -1
18+
19+
-2 -1 -4 0 -1 1 2 -3 1
20+
1. 누적합?
21+
22+
-2 1 -2 4 3 5 6 1 5
23+
24+
5 4 -1 7 8
25+
5 9 8 15 23
26+
27+
지금까지의 합 보다 다음 원소가 크면 그대로 두고, 아니면 합으로 대체
28+
=> TC: O(n), SC: O(1)
29+
30+
[회고]
31+
먼가..때려 맞춘 느낌이라 해설 참고
32+
->
33+
"""
34+
35+
class Solution:
36+
def maxSubArray(self, nums: List[int]) -> int:
37+
if len(nums) == 1:
38+
return nums[0]
39+
40+
memo = nums[0]
41+
42+
for i in range(1, len(nums)):
43+
if nums[i] < nums[i - 1] + nums[i]:
44+
nums[i] += nums[i - 1]
45+
46+
return max(nums)
47+
48+

number-of-1-bits/shinsj4653.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""
2+
[문제풀이]
3+
# Inputs
4+
- 양인 정수 n
5+
# Outputs
6+
- number of set bits => 이진수 값의 1 개수
7+
# Constraints
8+
- 1 <= n <= 2^31 - 1
9+
# Ideas
10+
1. 반복문
11+
2로 나눠서 몫 나머지 -> 나머지가 1인지 0인지 체크
12+
그 몫을 또 2로 나눠서 몫, 나머지 ->
13+
14+
15+
11
16+
2-> 5, 1
17+
2-> 2, 1
18+
2-> 1, 0
19+
2-> 0, 1
20+
21+
몫이 0이 될 때 까지 반복
22+
23+
TC: log2N? SC: 1
24+
25+
[회고]
26+
시간 복잡도가 log2N인가?
27+
-> O
28+
29+
해설은 어떤지 궁금
30+
->
31+
32+
"""
33+
34+
class Solution:
35+
def hammingWeight(self, n: int) -> int:
36+
ret = 0
37+
while n > 0:
38+
n, bit = n // 2, n % 2
39+
if bit == 1:
40+
ret += 1
41+
42+
return ret
43+
44+
# 해설
45+
46+
class Solution:
47+
def hammingWeight(self, n: int) -> int:
48+
cnt = 0
49+
while n:
50+
cnt += n & 1
51+
n >>= 1
52+
return cnt
53+

0 commit comments

Comments
 (0)