[分析]
思路1: 伪二分查找。若中间元素正好是target时,分四种小情况:1)左右边界也等于target时,当前这段就是要找的范围,可直接返回;2)只有左边界等于target,则右边界往左靠近一步;3)只有右边界等于target,则左边界往右靠近一步;4)左右边界均不等于target,则左右均往里逼近一步。容易看出在中间元素恰好是target时,算法退化为O(N)的。
思路2: 二分法依次查找target第一次出现和最后一次出现的位置。
[ref]
二分查找(Binary Search) 常见问题解决方法总结
[url]http://blog.youkuaiyun.com/daniel_ustc/article/details/17307937[/url]
[url]http://bangbingsyb.blogspot.com/2014/11/leetcode-search-for-range.html[/url]
思路1: 伪二分查找。若中间元素正好是target时,分四种小情况:1)左右边界也等于target时,当前这段就是要找的范围,可直接返回;2)只有左边界等于target,则右边界往左靠近一步;3)只有右边界等于target,则左边界往右靠近一步;4)左右边界均不等于target,则左右均往里逼近一步。容易看出在中间元素恰好是target时,算法退化为O(N)的。
思路2: 二分法依次查找target第一次出现和最后一次出现的位置。
[ref]
二分查找(Binary Search) 常见问题解决方法总结
[url]http://blog.youkuaiyun.com/daniel_ustc/article/details/17307937[/url]
[url]http://bangbingsyb.blogspot.com/2014/11/leetcode-search-for-range.html[/url]
public class Solution {
// Method 2: O(logN)
public int[] searchRange(int[] nums, int target) {
int[] result = {-1, -1};
if (nums == null || nums.length == 0)
return result;
result[0] = binarySearchFirst(nums, target);
if (result[0] != -1) {
result[1] = binarySearchLast(nums, target);
}
return result;
}
// 查找target在nums[]中第一次出现的下标,若找不到返回-1
public int binarySearchFirst(int[] nums, int target) {
if (nums == null || nums.length == 0)
return -1;
int left = 0, right = nums.length - 1;
int mid = 0;
while (left < right) { // 此处不能有等号,否则可能在right=mid处死循环,考虑case:[1], 1
mid = left + ((right - left) >> 1);
if (target > nums[mid])
left = mid + 1;
else
right = mid;
}
if (nums[left] == target)
return left;
return -1;
}
// 查找target在nums[]中最后一次出现的下标,若找不到返回-1
public int binarySearchLast(int[] nums, int target) {
if (nums == null || nums.length == 0)
return -1;
int left = 0, right = nums.length - 1;
int mid = 0;
while (left + 1 < right) { // 循环只处理元素个数大于两个的情况,两个以下元素时可能在left=mid处死循环(两个元素时left==mid),考虑case:[1,1],1
mid = left + ((right - left) >> 1);
if (target < nums[mid])
right = mid - 1;
else
left = mid;
}
if (nums[right] == target)
return right;
else if(nums[left] == target)
return left;
return -1;
}
// Method 1
public int[] searchRange1(int[] nums, int target) {
int[] result = {-1, -1};
if (nums == null || nums.length == 0)
return result;
int left = 0, right = nums.length - 1;
int mid = 0;
while (left <= right) {
mid = left + (right - left) / 2;
if (nums[mid] > target)
right = mid - 1;
else if (nums[mid] < target)
left = mid + 1;
else {
if (nums[left] == nums[mid] && nums[mid] == nums[right]) {
result[0] = left;
result[1] = right;
return result;
} else if (nums[left] == nums[mid]) {
right--;
} else if (nums[right] == nums[mid]) {
left++;
} else {
left++;
right--;
}
}
}
return result;
}
}