1. 題目描述
統計一個數字在排序數組中出現的次數。
2. 題目分析
- 題主一開始的方法:看見有序,使用二分,查找到target,向前向後分別遍歷到不等於target的數字,因爲數組中的target出現的次數是不確定的,所以,可能查找到n次,相當於O(n);
- 面試中,這種寫法會被paas掉,所以我們需要用二分查找找到第一次出現target的下標,最後一次出現target的下標,
- 對於target出現的第一次下標,採用以下方式
當mid == 0的時候,也就是證明當前的數是從下標0開始的,則直接返回0(mid)
爲了防止數組的越界,我們需要使當前的mid>0且array[mid-1]!=key
對於:right = mid - 1;我們可以理解成當前的key是位於中間的那一個,所以我們需要減少範圍,也就是縮小right的值,讓mid向前遍歷。
if (array[mid] == key) {
if ((mid == 0) || (mid > 0 && array[mid - 1] != key)) {
return mid;
} else {
right = mid - 1;
}
}
- 對於target出現的最後一次下標,採取以下方式
當mid == array.lenth - 1的時候,也就是證明當前的數一直到最後。則直接返回mid
爲了防止數組的越界,我們需要使當前的mid<array.lenth - 1且array[mid+1]!=key
對於:i = mid + 1;我們可以理解成當前的key是位於中間的那一個,所以我們需要減少範圍,也就是擴大left的值,讓mid向後遍歷。
if (array[mid] == key) {
if (mid == array.length - 1 || mid < array.length - 1 && array[mid + 1] != key) {
return mid;
} else {
left = mid + 1;
}
}
- 最後,我們返回(第二次出現的下標 - 第一次出現的下標 + 1)
3. 題目代碼
class Solution {
public int search(int[] nums, int target) {
int num1 = erfenFirst(nums, 0, nums.length - 1, target);
int num2 = erfenSecond(nums, 0, nums.length - 1, target);
return num2 - num1 + 1;
}
public static int erfenFirst(int[] array, int left, int right, int key) {
int mid = 0;
while (left <= right) {
mid = (left + right) / 2;
if (array[mid] == key) {
if ((mid == 0) || (mid > 0 && array[mid - 1] != key)) {
return mid;
} else {
right = mid - 1;
}
} else if (array[mid] > key) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return 1;
}
public static int erfenSecond(int[] array, int left, int right, int key) {
int i = left;
int j = right;
while (i <= j) {
int mid = (i + j) / 2;
if (array[mid] == key) {
if (mid == array.length - 1 || mid < array.length - 1 && array[mid + 1] != key) {
System.out.println(mid);
return mid;
} else {
i = mid + 1;
}
} else if (array[mid] > key) {
j = mid - 1;
} else {
i = mid + 1;
}
}
return 0;
}
}