Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Tags
- two pointers
- Array
- Binary
- math
- dfs
- binary search
- sorting
- leetcode
- 중간
- linked list
- tree
- 미디움
- string
- 이진트리
- 문자열
- 리트코드
- 재귀
- Medium
- easy
- HashTable
- DP
- binary tree
- backtracking
- 쉬움
- Python
- Depth-first Search
- hash table
- recursive
- matrix
- list
Archives
- Today
- Total
부부의 코딩 성장 일기
LeetCode 81(Search in Rotated Sorted Array II, Python) 본문
1. 문제 링크
Search in Rotated Sorted Array II - LeetCode
Can you solve this real interview question? Search in Rotated Sorted Array II - There is an integer array nums sorted in non-decreasing order (not necessarily with distinct values). Before being passed to your function, nums is rotated at an unknown pivot
leetcode.com
2. 문제 설명
- 오름차순으로 정렬된 리스트가 한번 회전 되어 주어졌을 때 특정 값이 포함되어 있는 지 조사하여 True or False를 반환하는 문제
- 예시) 리스트 [0,0,1,2,2,5,6]를 한번 회전하여 nums = [2,5,6,0,0,1,2], target = 0이 주어졌을 때 0이 포함되므로 True 반환
3. 처음 풀이
- return target in nums 하면 런타임 자체는 좋게 나오지만 시간 복잡도가 O(n)으로 의도한 풀이가 아닐 것.
- 중간에 한 번 회전된 것, 중복값이 있음을 고려하여 이진 검색을 하면 된다.
- 중간 지점을 정하면 왼쪽 또는 오른쪽 중 한 쪽은 오름차순 정렬이 되어 있다.
- 내가 찾는 값이 정렬된 곳에 있을 것으로 기대되면 거기에서 일반적인 이진 검색을 시행하면 되고, 정렬되지 않은 곳에 있을 것으로 기대되면 그 곳을 또 반으로 쪼개어 반복한다.
- 그리고 중복 값이 있으면 포인터를 옮기도록 하자.
class Solution:
def search(self, nums: List[int], target: int) -> bool:
left, right = 0 , len(nums) - 1
while left <= right:
if nums[left] == target or nums[right] == target:
return True
while left < len(nums) - 1 and nums[left] == nums[left + 1]: #이 부분이 느림. 필요할 때만 이 작업을 해야함.
left += 1
while right > 0 and nums[right] == nums[right - 1]: #이 부분이 느림. 필요할 때만 이 작업을 해야함.
right -= 1
mid = (left + right) // 2
if nums[mid] == target:
return True
elif nums[mid] < nums[right]:
if nums[mid] < target < nums[right]:
left = mid + 1
else:
right = mid - 1
else:
if nums[left] < target < nums[mid]:
right = mid - 1
else:
left = mid + 1
return False
4. 다른 풀이
- 중복 값을 생략하기 위해 포인터를 한 칸씩 옮겨주는 건 어느 쪽이 정렬되었는 지 모를 때만 하면 된다.
class Solution:
def search(self, nums: List[int], target: int) -> bool:
begin = 0
end = len(nums) - 1
while begin <= end:
mid = (begin + end)//2
if nums[mid] == target:
return True
if nums[mid] == nums[end]: # 중앙과 오른쪽 끝이 같다면 어느 쪽이 정렬되어 있는 지 모름
end -= 1 # 오른쪽 끝을 한 칸 앞으로, 최악의 경우 O(n)
elif nums[mid] > nums[end]: # 중앙이 오른쪽보다 크다면 왼쪽이 오름차순 정렬됨.
if nums[begin] <= target and target < nums[mid]: # 왼쪽 끝 <= target < 중앙 이면왼쪽에서 찾기
end = mid - 1
else: # 그렇지 않다면 오른쪽에서 찾기
begin = mid + 1
else: # 오른쪽이 오름차순 정렬됨.
if nums[mid] < target and target <= nums[end]: # 중앙 < target <= 오른쪽 끝이면 오른쪽에서 찾기
begin = mid + 1
else: # 그렇지 않다면 왼쪽에서 찾기
end = mid - 1
return False
5. 배운 점
- 중복 값 처리할 때 너무 아무 생각 없이 했는데 최적화에서 꽤 차이가 났다.
'Algorithm > LeetCode' 카테고리의 다른 글
LeetCode 86(Partition List, Python) (0) | 2024.01.30 |
---|---|
LeetCode 82(Remove Duplicates from Sorted List II) (0) | 2024.01.29 |
LeetCode 80(Remove Duplicates from Sorted Array II) (2) | 2024.01.27 |
LeetCode 79(Word Search, Python) (1) | 2024.01.26 |
LeetCode 78(Subsets, Python) (0) | 2024.01.25 |