方法一:暴力遍历
遍历输入的数组,使用一个计数器变量count统计目标元素target出现的次数。
时间复杂度:O(n) 这里n为数组长度
空间复杂度:O(1) 只用到常数个临时变量
var search = function(nums, target) {
var count=0;
for(var i=0; i<nums.length; i++){
if(nums[i]==target){
count++;
}
}
return count;
}
注意声明变量的位置、==的用法、以及++的用法,记得赋初值0
方法二:二分查找
因为是排序数组,所以可以用二分查找。
时间复杂度:O(logn) 这里n为数组长度
空间复杂度:O(1) 只用到常数个临时变量
var search = function(nums, target) {
//数组为空
if(nums.length==0){
return 0;
}
//二分查找定位大致位置
var l=0;
var r=nums.length-1;
while(l<=r){
var mid=Math.floor((l+r)/2);
if(nums[mid]==target){
l=r=mid;
break; //记录位置跳出循环
}else if(nums[mid]>target){
r=mid-1;
}else{
l=mid+1;
}
}
while(nums[l-1]==target||nums[r+1]==target){
if(nums[l-1]==target){
l--;
}
if(nums[r+1]==target){
r++;
}
}
return r-l+1;
}
【对二分查找的补充】
写二分法,区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)。边界条件不同,写法不同。
第一种写法,我们定义target是在一个左闭右闭的区间里,也就是[left, right] (这个很重要非常重要)。区间的定义决定了二分法的代码应该如何写,因为定义target在[left, right]区间,所以有如下两点:
- while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
- if (nums[mid] > target) right 要赋值为 mid - 1,因为当前这个nums[mid]一定不是target,那么接下来要查找的左区间结束下标位置就是 mid - 1
第二种写法,如果说定义 target 是在一个在左闭右开的区间里,也就是[left, right) ,那么二分法的边界处理方式则截然不同。有如下两点:
- while (left < right),这里使用 <,因为left == right在区间[left, right)是没有意义的
- if (nums[mid] > target) right 更新为 mid,因为当前nums[mid]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为mid,即:下一个查询区间不会去比较nums[mid]
注意
var mid=left+(right-left)>>1
var mid=left+(right-left)/2