前情提要:在养成写一些博客的习惯,同时练习英文表述和分析问题的能力,所以内容均为英文。
Problem Statement (leetcode704):
Given an array of integers nums
which is sorted in ascending order, and an integer target
, write a function to search target
in nums
. If target
exists, then returns its index. Otherwise, return -1
.
You must write an algorithm with O(log n)
runtime complexity.
Example 1:
Input: nums = [-1,0,3,5,9,12], target = 9 Output: 4 Explanation: 9 exists in nums and its index is 4
Example 2:
Input: nums = [-1,0,3,5,9,12], target = 2 Output: -1 Explanation: 2 does not exist in nums so return -1
Possible solutions:
1. The most trivial solution is to use brute force to iterate through the array/vector with O(n).
2. According to the requirement, it requires an algorithm with O(logn) to solve the problem, so we can implement binary search to solve this problem.
Binary Search:
Binary searach is a classic divided and conquer algorithm. It keeps diveuntild array into smaller sub-arrays recursively and collect the results.
Pros and Cons for Binary Search:
Pros: High efficiency, with O(log(n)) time complexity
Cons: Array must be pre-sorted, binary search also can only be applied in data structure that supports random access.
Handling Boundary Conditions and Exceptional Situations:
1. empty vector:
if (nums.size() == 0) return -1;
2. Target Value Not Found:
In the recursive version, the base case for the recursive calls is when start > end.
In the iterative version, the while
loop continues as long as start <= end
.
3. Integer Overflow:
When calculating the middle index mid
, instead of using (start + end) / 2
, we use start + (end - start) / 2
to avoid potential integer overflow.
Solution_Recusrion Version:
class Solution {
public:
int search(vector<int>& nums, int target) {
if (nums.size() == 0) return -1;//empty vector
int start = 0;
int end = nums.size() - 1;
int sol = helper_binaryserach(nums, target, start, end);
return sol;
}
int helper_binaryserach(vector<int>& nums, int target, int start, int end) {
//logic behind the target not in the vector is that the start and end will cross each other
if (start > end) return -1;
int mid = (start + end) / 2;
if (nums[mid] == target) return mid;
if (nums[mid] > target) return helper_binaryserach(nums, target, start, mid - 1);
if (nums[mid] < target) return helper_binaryserach(nums, target, mid + 1, end);
}
};
Solution_while loop:
class Solution {
public:
int search(vector<int>& nums, int target) {
int start{ 0 }, end{ nums.size() - 1 };
while ( start <= end) {
int mid = start + (end - start) / 2;
if (nums[mid] == target) return mid;
else if (nums[mid] < target) start = mid + 1;
else {
end = mid - 1;
}
}
return -1;
}
};