LeetCode [ 162 | Python ] Find Peak Element
업데이트:
문제
주어진 배열 nums
에서 가장 큰 값을 찾아내야 하는 최대값 문제.
풀이
시도 1
실행시간 : 28ms
메모리 : 13.5MB
nums
의 길이가 길지 않아서 혹시 싶어 시도해 보았던 코드.
의외로 통과가 됐다.(O(log n) 안에 끝내야 한댔는데..)
파이썬의 max
는 선형 탐색을 수행하기 때문에 최악의 경우 O(n**2)의 시간 복잡도가 걸리는 코드이다.
정말 직관적으로 함수만 사용한 코드이기 때문에, 더 효율적으로 큰 값을 찾아내고자 했다.
class Solution(object):
def findPeakElement(self, nums):
return nums.index(max(nums))
개선
실행시간 : 23ms
메모리 : 13.2MB
O(log n) 이라는 시간 복잡도를 맞춰야하기 때문에 떠올랐던 건 이분탐색이었다.
이분 탐색은 정렬되어 있는 배열에서만 사용해야한다고 알고 있었지만, 중간값과 그 주위의 값을 이용하면 충분히 이용가능하다는 것을 깨달았다.
peak
라는 단어를 통해 힌트를 얻었다.
- 이분탐색을 수행하기 위한 변수
l
(범위 시작 값),r
(범위 끝 값)을 초기화한다. - 이분탐색을 수행한다.
- 중간값을 기준으로 수행한다.
- 중간 값과 그 오른쪽에 있는 값을 비교한다.
- 중간값이 오른쪽에 있는 값 보다 큰 경우
r
값을m
값으로 범위를 축소시킨다. - 이외의 경우
l
값을m + 1
값으로 확장시킨다.
- 중간값이 오른쪽에 있는 값 보다 큰 경우
- 탐색을 마치고 난
l
을 반환한다.
class Solution(object):
def findPeakElement(self, nums):
l, r = 0, len(nums) - 1
while l < r:
m = (l + r) // 2
if nums[m] > nums[m + 1]:
r = m
else:
l = m + 1
return l
생각 & 정리
분명 이분탐색은 정렬되어 있는 배열에서만 사용가능하다고
알고있었는데 특정 값이 아닌 가장 작은 값, 가장 큰 값을 찾기에는 크게 무리가 없었다.
그 이유로는 기준으로 삼는 m
값과 그 근처의 값을 사용했기 때문인데,
정석적인 이분탐색으로는 l
과 m
, m
과 r
사이가 작은값, 큰값들로만 이뤄져있다는 것을 약속하고 있기 때문에 풀이하기 어려웠을 것이다.
다른 문제들도 그렇지만, 이분 탐색은 특히 익숙치 않아서인지 유연한 생각이 필요한 것 같다.
어떤 값을 기준으로 삼을지, 얼마만큼 값을 감소시키고 증가시킬지 고려해야하는 점이 다소 까다롭게 느껴진다.
댓글남기기