문제
https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/
Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value. Your algorithm's runtime complexity must be in the order of \(O(\log n)\). If the target is not found in the array, return [-1, -1].
Example 1:
Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]
Example 2:
Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]
풀이
주어진 배열에서 특정값을 가지는 주소를 \(O(\log n)\)에 찾는다고 했으니 당연히 binary search를 제일 먼저 떠올려야 한다. Binary search를 사용하기로 작정하고 문제를 살펴보면, 두 번의 전형적인 binary search 알고리즘으로 답을 구할 수 있다는 것을 알게 될 것이다. Starting position을 찾기 위해 1번, ending position을 찾기 위해 1번이 필요하다. 시간 복잡도는 \(O(\log n)\)이고, 공간 복잡도는 \(O(1)\)이다.
좀 더 알고리즘을 개선할 여지가 없는지 고민해보자. 두 번의 binary search에서 중복된 작업이 수행된다. 수행 시작부터 주어진 target value를 처음 찾을 때까지 작업이 이에 해당한다. 따라서 이 작업을 한 번만 하도록 알고리즘을 수정하면 수행 시간이 줄어들 것이다.
알고리즘을 크게 보면 다음 세 부분으로 나눌 수 있다.
- Binary search를 수행하며 target value를 가지는 index를 찾는다. 만약 없으면 [-1, -1]을 리턴한다.
- 1번에서 남아있는 왼쪽 구역에 대해 binary search를 계속 수행하여 starting position을 찾는다.
- 1번에서 남아있는 오른쪽 구역에 대해서도 binary search를 수행하여 ending position을 찾는다.
코드 (C++)
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> ret;
int left = 0;
int right = nums.size() - 1;
int mid;
/* Step 1 */
while (left <= right) {
mid = (left + right) / 2;
if (nums[mid] == target) {
break;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
if (left > right) {
ret.push_back(-1);
ret.push_back(-1);
return ret;
}
/* Step 2 */
int start_left = left;
int start_right = mid;
while (start_left < start_right) {
int start_mid = (start_left + start_right) / 2;
if (nums[start_mid] < target) {
start_left = start_mid + 1;
} else {
start_right = start_mid;
}
}
/* Step 3 */
int end_left = mid;
int end_right = right;
while (end_left < end_right) {
int end_mid = (end_left - end_right) / 2 + end_right;
if (nums[end_mid] > target) {
end_right = end_mid - 1;
} else {
end_left = end_mid;
}
}
ret.push_back(start_left);
ret.push_back(end_left);
return ret;
}
'알고리즘 문제 해결 > 문제 풀이' 카테고리의 다른 글
자료구조와 알고리즘 Problem Set 공유 (0) | 2019.06.29 |
---|