题目中的信息有:
- 排序
- 数组
- 数组长度
0<=n<=50000
1. 从前往后顺序遍历
从前往后顺序遍历,当target==nums[i]时,次数+1,直到碰到第一个比target大的数为止,返回次数。
- 时间复杂度O(n);空间复杂度O(1)
class Solution {
public int search(int[] nums,int target) {
int length = nums.length;
int n=0,i=0;
while(i<length) {
if(nums[i]<target) i++;
else if(nums[i]==target) {
n++;
i++;
}
else break;
}
return n;
}
}
2. index方法
想着利用List的indexOf
和lastIndexOf
方法计算得n
- 时间复杂度O(n);空间复杂度O(n)。但执行结果显示执行用时反而更大,问题出现在哪里呢?还麻烦了解的同学帮忙解答一下。(是否是因为:List的
indexOf
方法实质是从前往后顺序查找,而lastIndexOf
方法是从后往前顺序查找,表面上是O(1)的复杂度,其实是O(n)?) - 本方法不可取,时间复杂度没减少,反而增加了空间复杂度
public int search(int[] nums,int target) {
int length = nums.length;
List<Integer> list = new ArrayList<Integer>();
int n=0,i=0;
if(length>0) {
for(i=0;i<length;i++) {
list.add(nums[i]);
}
int index =list.indexOf(target);
int lastIndex = list.lastIndexOf(target);
if(index>=0) {
n = lastIndex - index + 1;
return n;
}
else return 0; //index=-1
}
return 0;
}
3. 二分查找
一开始的思路是利用二分查找找到一个位置,从该位置向左边遍历找到左边界,向右遍历找到右边界,从而计算得到最终值,如下代码,运行结果是双100%。
public int search(int[] nums,int target) {
int length = nums.length;
int i = 0, count = 0, pos = -1;
int low = 0, high = length-1, mid;
// 二分查找找到target出现的某个位置pos(数组下标)
while(low<=high) {
mid = (low+high)/2;
if(target<nums[mid]) high = mid-1;
else if(target>nums[mid]) low=mid+1;
else {
pos = mid;
break;
}
}
if(pos!=-1) {
count = 1;
//向左遍历count++
i = pos-1;
while(i>=0) {
if(nums[i]==target) {
count++;
i--;
}
else break;
}
//向右遍历count++
i = pos+1;
while(i<length) {
if(nums[i]==target) {
count++;
i++;
}else break;
}
return count;
}
else return 0;
}
评论区有和此方法思路一致的代码,看着更为简洁,贴上来。还有利用多次二分查找的方法找左右边界的尚未搞特别清楚,等我搞明白了再来。
class Solution {
public int search(int[] nums, int target) {
int left =0,right = nums.length-1;
int count = 0;
while(left<right){
int mid = (left+right)/2;
if(nums[mid]>=target)
right=mid;
if(nums[mid]<target)
left = mid+1;
}
while(left<nums.length&&nums[left++]==target)
count++;
return count;
}
}
class Solution {
public int search(int[] nums, int target) {
int l = 0;
int r = nums.length-1;
int ans=0;
while(l<=r){
int b = (l+r)>>1;
if(nums[b]<target)
l=b+1;
else if(nums[b]>target)
r=b-1;
else{
for(int i=b;i>=0&&nums[i]==target;i--,ans++);
for(int i=b+1;i<nums.length&&nums[i]==target;i++,ans++);
break;
}
}
return ans;
}
}