給定一個按照升序排列的整數數組 nums,和一個目標值 target。找出給定目標值在數組中的開始位置和結束位置。
你的算法時間複雜度必須是 O(log n) 級別。
如果數組中不存在目標值,返回 [-1, -1]。
示例 1:
輸入: nums = [5,7,7,8,8,10], target = 8 輸出: [3,4] 示例 2:
輸入: nums = [5,7,7,8,8,10], target = 6 輸出: [-1,-1]
/**
* 如果只是找到一個,那麼直接用二分查找即可
* 要找到最左邊和最右邊符合條件的,那麼需要在找到符合條件的之後,再分別往左或者往右找
* 使用遞歸往左/右找的時候,有可能在上一次遞歸找到了,在下一次遞歸沒有找到,因此需要在遞歸的時候記錄一下上次找到的位置
* */
public static int[] searchRange(int[] nums, int target) {
int pos = searchLeft(nums, 0, nums.length - 1, target);
int rightPos = searchRight(nums, 0, nums.length - 1, target);
if (pos == -1 || rightPos == -1) {
return new int[]{-1, -1};
}
return new int[]{pos, rightPos};
}
public static int searchLeft(int[] nums, int left, int right, int target) {
//二分查找
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
//找到之後繼續往左找
int leftPos = searchLeft(nums, left, mid - 1, target);
//如果遞歸返回-1,那麼本次返回找到的mid
if (leftPos == -1) {
return mid;
}
//否則返回leftPos
return leftPos;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
public static int searchRight(int[] nums, int left, int right, int target) {
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
int rightPos = searchRight(nums, mid + 1, right, target);
if (rightPos == -1) {
return mid;
}
return rightPos;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}