Conversation
| ''' | ||
| 문제: 배열의 중복을 찾는 문제 | ||
| 풀이: 정렬 후 인접한 원소끼리 비교하여 중복 여부 확인 중복이 없다면 False 반환 | ||
|
|
||
| 시간복잡도: O(n log n) | ||
| sort()의 시간복잡도는 O(n log n)이고, for문은 O(n)이므로, | ||
| 전체 시간복잡도는 O(n log n) | ||
|
|
||
| 공간복잡도: O(1) | ||
| nums.sort()는 제자리 정렬이므로, 추가적인 공간을 사용하지 않는다. | ||
| 또한 num 변수를 하나만 사용하므로, 전체 공간복잡도는 O(1) | ||
|
|
||
| 사용한 자료구조: 리스트 | ||
|
|
||
| 만약 파이썬의 딕테이션과 같이 조회 시 O(1)인 자료구조를 사용한다면, | ||
| 시간복잡도를 O(n)으로 줄일 수 있다. | ||
| ''' |
There was a problem hiding this comment.
와.. 이렇게 정리하시면서 문제를 푸시는게 되게 도움이 많이 될거 같아요! 👍
| def containsDuplicate(self, nums: List[int]) -> bool: | ||
| nums.sort() | ||
| num = nums[0] | ||
| for i in range(1, len(nums)): | ||
| if num == nums[i]: | ||
| return True | ||
| num = nums[i] | ||
| return False |
There was a problem hiding this comment.
정렬을 하시고, 비교하면서 판단하는 방법이군요!
저는 집합을 이용해서 크기를 비교하는 방식으로 접근했는데요!
다른 접근법도 생각해볼 수 있어서 좋았던 것 같습니다 :)
There was a problem hiding this comment.
자바스크립트의 Set을 쓰시는 군요! 프로필 살짝 보긴했는데, 저도 프론트엔도 공부하고 있습니다
다만 알고리즘 한정으로는 파이썬이 더 익숙해서 쓰긴하는데, Set은 잊고 있었네요..
| for i in range(len(nums)): | ||
| if nums[i] not in d: | ||
| d[nums[i]] = [i] | ||
| else: | ||
| d[nums[i]] += [i] | ||
| print(d) | ||
| for i in d.keys(): | ||
| if target-i in d and len(d[target-i]) == 1 and target != i*2: | ||
| answ = [d[target-i][0], d[i][0]] | ||
| return answ | ||
| if target-i in d and len(d[target-i]) >= 2 and target == i*2: | ||
| answ = [d[target-i][0], d[i][1]] |
There was a problem hiding this comment.
O(N)으로 딕셔너리를 활용해 잘 해결하신 것 같아요!
혹시 for 문을 한 번만 사용하는 방식은 어떨까요?
맵을 먼저 다 채우는 대신, 순회하면서
(1) 짝이 있는지 먼저 확인하고 (2) 나를 맵에 등록하는 방식이에요.
이렇게 하면 target == i*2 같은 엣지 케이스를 위한 별도 분기문 없이도 코드가 조금 더 간결해질 수 있을 것 같아서 참고차 의견 드립니다! 🫡
++ 추가로 해당 파일은 하단에 개행문자가 필요없는지 궁금합니다..!
다른 파일들과 달리 없는 것 같아서 확인차 전달드려요!
There was a problem hiding this comment.
이게 예전에 알고리즘 수업을 듣다가 문득 for문을 여러 번 돌려도 상수배니까 상관없나..?라는 생각이 들어서
일단 수행시간에 문제가 없다면 그냥 제 관점에서 나름대로 역할을 분리하여 작성하곤 했는데, 그냥 for문 안에 붙여도 되겠구나 싶네요 공유해주셔서 감사합니다!
코드는 그래서 이렇게 바꿔봤습니다. 이 코드도 정답으로 나옵니다.
for i in range(len(nums)):
if target - nums[i] in d:
return [d[target-nums[i]][0], i]
if nums[i] not in d:
d[nums[i]] = [i]
else:
d[nums[i]] += [i]확실히 먼저 저장하기 전에 확인하고 리턴하는게 더 간결해지네요! 다시한번 감사합니다
마지막으로 개행문자가 깃허브에서 있다고 판단한건지 해당 파일에 -표시가 없어서 그냥 내버려 뒀는데, 혹시 모르니까 새로 코드 추가해서 개행문자 추가 후 커밋하겠습니다
There was a problem hiding this comment.
헉.. 빠르게 시도해보셨군요! 고생하셨습니다!! 👍
순회하는 배열의 길이나 for문을 돌리는 횟수에 따라서 다르겠지만,
돌리는 횟수가 많아지면 많아질수록 아무래도 시간복잡도에 영향을 미칠 수 밖에 없다고 생각합니다.
그래서 저도 습관처럼 위에 작업해주신 방법대로 적게 돌려보려고 합니다 :)
저도 빠르게 다른 문제들도 풀고 리뷰드리도록 하겠습니다 😊
피드백 받은 코드 기존 파일에 주석으로 추가
prgmr99
left a comment
There was a problem hiding this comment.
top k frequent element를 풀어서 바로 리뷰 드렸습니다..!!
고생하셨습니다 :)
| else: | ||
| arr[i] = 1 | ||
|
|
||
| a = sorted(arr.items(), key=lambda x:x[1], reverse=True) |
There was a problem hiding this comment.
되게 간결해보이네요..!!
key=lambda x:x[1], 요 코드는 어떤 역할을 하는건가요??a는 정렬한 배열을 나타는 것으로 이해했는데 변수명을 명확하게 해주시면 더 좋을 것 같습니다!
There was a problem hiding this comment.
딕셔너리가 키:밸류로 이루어져 있는데, 이를 정렬하기 위해 아이템을 기준으로 정렬한다는 의미입니다!
다만 파이썬이 딕셔너리를 2차원 리스트로 인식하는지, key=lambda x:x[1]로 작성해야 1번째 인덱스인 밸류값을 기준으로 오름차순/내림차순 정렬을 합니다.
아무래도 빈도수를 기준으로 내림차순해야하기 때문에, 빈도수(밸류)가 높은 순으로 해당 빈도수를 가진 키 값을 정답 코드로 작성했습니다.
그리고 a는 임시 리스트로 arr을 더 줄인 변수명이였는데, 시간이 없다고 생각하고 굉장히 직관적으로 작성하다보니 나온 변수명입니다. 나중에 명확하게 작성해보겠습니다.
| dp[0], dp[1], dp[2] = nums[0], nums[1], nums[0]+nums[2] | ||
|
|
||
| for i in range(3, len(nums)): | ||
| dp[i] = max(dp[i-2], dp[i-3]) + nums[i] |
There was a problem hiding this comment.
이런 방향으로 접근하실 수 있다는 점에서 새로운 시각을 배울 수 있었습니다.
dp[i]의 값을 i번째 집을 반드시 털었을 때, 0번째 집부터 i번째 집까지 털 수 있는 최대 금액으로 설정하신 것 같은데요..!
도움이 되실지는 모르겠지만,,, 리뷰를 작성해보겠습니다..!
dp[i]를 i번째 집까지 털었을 때의 최대 금액으로 정의하면 어떨까요?
이렇게 하면 i번째 집에서 선택은 딱 두 가지가 되어요
-
i번째 집을 턴다 (i-1은 못 텀)
-> nums[i] + dp[i-2] -
i번째 집을 안 턴다 (i-1까지 턴 값)
-> dp[i-1]
그럼 점화식이 dp[i] = max(nums[i] + dp[i-2], dp[i-1])로 될 것 같습니다.
There was a problem hiding this comment.
반드시 턴다는 것이 아닌 털 수도 있고, 아니면 바로 이전 값을 가져올 수도 있게 하는 것이군요!
이러면 확실히 초반 식이 덜 복잡해지겠습니다
기존 코드는 -3부터니까요
전체 리뷰 감사합니다!
이 pr은 병합할게요!
답안 제출 문제
작성자 체크 리스트
In Review로 설정해주세요.검토자 체크 리스트
Important
본인 답안 제출 뿐만 아니라 다른 분 PR 하나 이상을 반드시 검토를 해주셔야 합니다!