目录
题目
统计一个数字在排序数组中出现的次数。
示例 1:
输入: nums = [5,7,7,8,8,10], target = 8
输出: 2
示例 2:
输入: nums = [5,7,7,8,8,10], target = 6
输出: 0
提示:
0 <= nums.length <=
- <= nums[i] <=
nums 是一个非递减数组
- <= target <=
解题思路1——暴力破解
既然需要在一个数组中统计某一个数出现的次数,那么将数组中的每一个元素都和该数进行比较,如果相等则出现的次数增加1,如果不相等则直接比较下一个元素。这是一定可以得到正确答案的做法。
解题思路2——浅浅的运用一下二分查找的思想
很有意思的是,提示中指明了给定的数组是一个非递减数组,那么,给定的这个数组必定是有序的,对有序数组进行查找,时间复杂度为对数阶的二分查找(折半查找)算得上是一个活跃分子。
但是,二分查找的特点是只对目标值命中一次或者零次,如果要用来统计出现的次数,好像有些不太容易。
那么,有一种简单的想法就是:使用二分查找找到目标值所在的位置,如果不命中,那么出现的次数为0;如果命中,由于目标值在数组中会出现若干次,那么便可以以找到的位置为起点,向两侧查找,找到和目标值不相等的元素值便停止查找,这样一来,便可以比暴力破解少进行一些比较。
解题思路3——纯二分查找的递归
使用二分查找找到目标值的位置,之后在该位置的基础上向两侧进行查找这样的思路中,向两侧进行查找时使用的是顺序比较的方式进行的,那么既然是查找,除了顺序比较的方式,也可以使用二分查找的方式进行查找,这样一来便纯粹地使用二分查找进行统计了。
但是这三种思路的时间开销来看,还真没有什么差别。
那么,纯粹使用二分查找,便可以使用递归的形式来进行,递归的示意图如下:
那么,便可以得到这样一个结论:
题解1——暴力破解
class Solution {
public int search(int[] nums, int target) {
int count = 0;
for(int i=0;i<nums.length;i++){
if(nums[i] == target){
count++;
}
}
return count;
}
}
题解2——二分查找+顺序查找
class Solution {
public int search(int[] nums, int target) {
//如果数组为空,那必然是找不到的
if(nums.length == 0){
return 0;
}
//如果数组只有一个元素,那么只判断这个元素就行
if(nums.length == 1){
if(nums[0] == target){
return 1;
}else{
return 0;
}
}
int left = 0; //左界
int right = nums.length-1; //右界
int mid = right/2; //中间
int count = 0; //统计出现次数
while(left<=right){
mid = (right - left)/2 + left;
if(nums[mid] < target){
left = mid + 1;
}
if(nums[mid] > target){
right = mid - 1;
}
if(nums[mid] == target){
break;
}
}
for(int i=mid;i>=0;i--){
//统计左侧区域的次数
if(nums[i] == target){
count++;
}else{
break;
}
}
for(int i=mid;i<=right;i++){
//统计右侧区域的次数
if(nums[i] == target){
count++;
}else{
break;
}
}
if(count == 0){
return 0;
}
return count - 1;
}
}
题解3——递归+二分查找
class Solution {
static int count = 0;
public int search(int[] nums, int target) {
count = 0;
binarySearch(nums,0,nums.length-1,target);
return count;
}
//二分查找
public static void binarySearch(int[] nums,int left,int right,int target){
if(left <= right){
int mid = (right - left)/2 + left;
if(nums[mid] == target){
count++;
binarySearch(nums,left,mid-1,target);
binarySearch(nums,mid+1,right,target);
}
if(nums[mid] > target){
binarySearch(nums,left,mid-1,target);
}
if(nums[mid] < target){
binarySearch(nums,mid+1,right,target);
}
}
}
}
总结
三种解题方法在时间开销上没什么差别,但是在空间的开销上有些差别。