-
-
Notifications
You must be signed in to change notification settings - Fork 247
[yhkee0404] WEEK 03 solutions #1792
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
Conversation
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.
공유해주신 풀이 방법이군요 :) 덕분에 배웠습니다!
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.
3주차 문제 풀이 고생하셨습니다!
러스트는 제가 잘 모르지만 핵심 자체는 매우 잘 파악이 된 것 같습니다.
여유가 있으시다면 시간, 공간 복잡도도 분석해 주시면 리뷰에 더욱 도움이 될 것 같습니다.
4주차 문제 풀이도 파이팅입니다!
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.
Top-Down DP 풀이인데 최악의 시간 복잡도와 공간 복잡도는 Bottom-UP 풀이와 같습니다: DaleSeo/AlgoDale#29
Top-Down DP 풀이는 부분 해를 완전히 전처리한 뒤 참조하므로 중복 원소 제거를 위해 부등식 검사가 추가로 필요했어요: https://github.com/yhkee0404/leetcode-study/blob/87da9b6db48f37cd4bda21c8b29d88a0d1b79419/combination-sum/yhkee0404.ts#L16
반면에 위와 같이 부분 해가 완성되기 전에 참조하는 경우는 처음 봐서 신기합니다! 덕분에 중복 원소가 제거되네요.
한편 재귀 호출 시 Default Argument인 dp
를 전달하지 않으면 40배 정도 느려졌으니 참고해 주세요.
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.
Kadane's Algorithm의 선형 풀이 대신 문제의 Follow Up
에서 요구한 대로 분할 정복으로 풀어 봤습니다.
@lru_cache | ||
def hammingWeight(self, n: int) -> int: | ||
return 1 + self.hammingWeight(n - (n & - n)) if n else 0 |
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.
@lru_cache | |
def hammingWeight(self, n: int) -> int: | |
return 1 + self.hammingWeight(n - (n & - n)) if n else 0 | |
def __init__(self, bucket_mask_size = 6) -> int: | |
self.bucket_mask_size = bucket_mask_size | |
self.bucket_mask = (1 << bucket_mask_size) - 1 | |
self.dp = [0] * (self.bucket_mask + 1) | |
for i in range(len(self.dp)): | |
j = i | |
while j: | |
self.dp[i] += 1 | |
j -= j & - j | |
def hammingWeight(self, n: int) -> int: | |
ans = 0 | |
while n: | |
ans += self.dp[n & self.bucket_mask] | |
n >>= self.bucket_mask_size | |
return ans |
이 문제의 Follow Up
도 최적화를 요구하는데 댓글에서 또다른 방법을 찾아서 공유합니다: https://leetcode.com/problems/number-of-1-bits/description/comments/1882536/?parent=1568380
저는 잘 몰라서 대충 @lru_cache
만 적어뒀었는데 더 효과적인 방법인 것 같아요.
0부터 63까지 2^6=64
개에 대한 정답을 전처리해 두면 그만큼 희생한 공간에 대한 Trade-Off로 시간이 6배 줄어듭니다. 2^m개에 대해서는 m배입니다.
즉 0b000000
부터 0b111111
까지의 정답을 상수 시간에 구할 수 있게 되므로 n >> 1
연산을 logn
번 수행하며 1의 개수를 세는 대신에 n >> 6
연산을 ceil(logn / 6)
번만 수행하면서 각 Bucket의 부분 해를 더해도 정답을 알 수 있습니다.
logn <= 32
비트 수에 대한 Square Root Decomposition은 sqrt(logn) < 6
이므로 2^6=64
개만 전처리해도 O(logn)
에서 O(sqrt(logn))
으로 거의 제곱만큼 시간을 줄이는 효과가 생깁니다.
나아가 저장 공간을 2배씩 더 소모하는 만큼 연산 시간의 분모에는 1씩 더하는 효과가 있네요.
O(hammingWeight(n))
은 최대 32번 수행할 수도 있는 반면에 O(sqrt(logn))
만 해도 최대 6번밖에 수행하지 않으므로 전처리를 전제한다면 최악의 시간 복잡도에서 더 유리한 Bucket 알고리즘이 되네요.
답안 제출 문제
작성자 체크 리스트
In Review
로 설정해주세요.검토자 체크 리스트
Important
본인 답안 제출 뿐만 아니라 다른 분 PR 하나 이상을 반드시 검토를 해주셔야 합니다!