【題目】34. 在排序數組中查找元素的第一個和最後一個位置
給定一個按照升序排列的整數數組 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]
【解題思路1】線性查找
class Solution {
public int[] searchRange(int[] nums, int target) {
int[] targetRange = {-1, -1};
for (int i = 0; i < nums.length; i++) {
if (nums[i] == target) {
targetRange[0] = i;
break;
}
}
if (targetRange[0] == -1) {
return targetRange;
}
for (int j = nums.length-1; j >= 0; j--) {
if (nums[j] == target) {
targetRange[1] = j;
break;
}
}
return targetRange;
}
}
【解題思路2】二分法
找到 target的左邊起始點,和 target + 1的起始點,這樣二分法就統一成一個函數了
class Solution {
public int[] searchRange(int[] nums, int target) {
int a = search(nums,target);
int b = search(nums,target+1);
if(a==nums.length||nums[a]!=target) //這表明數組中不存在target
return new int[]{-1,-1};
return new int[]{a,b-1}; //否則數組中存在target,則b-1是最後一個target的元素索引
}
//該二分查找nums中第一個>=t的元素位置
int search(int[] nums, int t) {
int l = 0,r = nums.length;
while(l<r){
int m = (l+r)>>>1;
if(nums[m]<t)
l = m+1;
else
r = m;
}
return l;
}
}
拆開來寫,找target的左端,再找target右端
class Solution {
public int[] searchRange(int[] nums, int target) {
int right = lower_bound(nums, target);
int left = higher_bound(nums, target);
return new int[]{left, right};
}
private int lower_bound(int[] a, int v){
int l = 0;
int r = a.length - 1;
int res = -1;
while(l <= r){
int mid = l + ((r-l)>>1);
if(a[mid] < v){
l = mid + 1;
}else if(a[mid] > v){
r = mid - 1;
}else{
res = mid;
l = mid + 1;
}
}
return res;
}
private int higher_bound(int[] a, int v){
int l = 0;
int r = a.length - 1;
int res = -1;
while(l <= r){
int mid = l + ((r-l)>>1);
if(a[mid] > v){
r = mid - 1;
}else if(a[mid] < v){
l = mid + 1;
}else{
res = mid;
r = mid - 1;
}
}
return res;
}
}
【題目】劍指 Offer 53 - I. 在排序數組中查找數字 I
統計一個數字在排序數組中出現的次數。
示例 1:
輸入: nums = [5,7,7,8,8,10], target = 8
輸出: 2
示例 2:
輸入: nums = [5,7,7,8,8,10], target = 6
輸出: 0
限制:
0 <= 數組長度 <= 50000
注意:本題與主站 34 題相同(僅返回值不同)