Given an array of integers 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].
For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].
JAVA
方法一
由于数组有序,因此使用二分查找。首先找到一个target,然后对其左侧循环进行二分查找,但是只保留最后找到的那个,再对其右侧循环进行二分查找,同样只保留最后找到的那一个。时间效率排在4/5左右。
public class Solution {
public int[] searchRange(int[] nums, int target) {
int [] result = {-1,-1};
int mid = -1;
int left = 0;
int right = nums.length - 1;
boolean findTarget = false;
while(left <= right){
mid = (left + right) / 2;
if(target == nums[mid]){
result[0] = mid;
result[1] = mid;
break;
}else if(target > nums[mid]){
left = mid + 1;
}else{
right = mid - 1;
}
}
findTarget = true;
while(findTarget && result[0] != -1){
left = 0;
right = result[0] - 1;
findTarget = false;
while(left <= right){
mid = (left + right) / 2;
if(target == nums[mid]){
result[0] = mid;
findTarget = true;
break;
}else if(target > nums[mid]){
left = mid + 1;
}else{
right = mid - 1;
}
}
}
findTarget = true;
while(findTarget && result[1] != -1){
left = result[1] + 1;
right = nums.length - 1;
findTarget = false;
while(left <= right){
mid = (left + right) / 2;
if(target == nums[mid]){
result[1] = mid;
findTarget = true;
break;
}else if(target > nums[mid]){
left = mid + 1;
}else{
right = mid - 1;
}
}
}
return result;
}
}
方法二
由于觉得方法一的效率不应该那么差,毕竟达到了O(log2N),于是重新查看寻找优化的方法。后来发现,由于在循环查找左侧的target时,由于已经找到了一个target在当前查找范围的右侧,而数组是升序的,所以不可能出现找到的数比target大的情况,因此去掉else部分;同理,在循环查找右侧target时,也不会出现小于target的情况,同样去掉else部分。虽然去掉的都是永远不会执行的语句,但是时间快了2ms,效率达到前1/4。
同样的代码再次执行时,时间比方法一快了1ms,效率达到前2/3。。。可见效率好坏还是要看服务器的。。。
public class Solution {
public int[] searchRange(int[] nums, int target) {
int [] result = {-1,-1};
int mid = -1;
int left = 0;
int right = nums.length - 1;
boolean findTarget = false;
while(left <= right){
mid = (left + right) / 2;
if(target == nums[mid]){
result[0] = mid;
result[1] = mid;
break;
}else if(target > nums[mid]){
left = mid + 1;
}else{
right = mid - 1;
}
}
findTarget = true;
while(findTarget && result[0] != -1){
left = 0;
right = result[0] - 1;
findTarget = false;
while(left <= right){
mid = (left + right) / 2;
if(target == nums[mid]){
result[0] = mid;
findTarget = true;
break;
}else if(target > nums[mid]){
left = mid + 1;
}
}
}
findTarget = true;
while(findTarget && result[1] != -1){
left = result[1] + 1;
right = nums.length - 1;
findTarget = false;
while(left <= right){
mid = (left + right) / 2;
if(target == nums[mid]){
result[1] = mid;
findTarget = true;
break;
}else if(target < nums[mid]){
right = mid - 1;
}
}
}
return result;
}
}