二分查找算法

现在有一个从小到大排序的数组,给你一个目标值target,现在请你找到这个值在数组中的对应下标,如果没有,请返回-1:
`int search(int* nums, int numsSize, int target){
//请实现查找算法
}

int main() {
int arr[] = {1, 3, 4, 6, 7,8, 10, 11, 13, 15}, target = 3;
printf("%d", search(arr, 10, target));
}
`
此时,最简单的方法就是将数组中的元素一个一个进行遍历,总有一个是,如果遍历完后一个都没有,那么就结束:

int search(int* nums, int numsSize, int target){
for (int i = 0; i < len; ++i) {
if(nums[i] == target) return i; //循环n次,直到找到为止
}
return -1;
}

虽然这样的算法简单粗暴,但是并不是最好的,我们需要遍历n次才能得到结果,时间复杂度为O ( n ),我们可以尝试将其优化到更低的时间复杂度。这里我们利用它有序的特性,实际上当我们查找到大于目标target的数时,就没必要继续寻找了:

int search(int* nums, int numsSize, int target){
for (int i = 0; i < len; ++i) {
if(nums[i] == target) return i;
if(nums[i] > target) break;
}
return -1;
}
这样循环进行的次数也许就会减小了,但是如果我们要寻找的目标target刚好是最后几个元素呢?这时时间复杂度又来到到了O ( n )

那我们可以对半查找,如果中间数比要目标大,对半选左边部分,如果中间数target比目标小,对半选右边部分。
然后继续在另一部分中再次随机找一个数,这样每次都能将范围缩小,直到找到为止(其思想就比较类似于牛顿迭代法,再次强调数学的重要性)



我们采用递归分治算法:
代码如下:
int a(int* nums,int target,int left,int right){
if(left > right) return -1;
int mid = (left + right) / 2;
if(nums[mid] == target) return mid;
if(nums[mid] > target)
return a(nums,target,left,mid - 1);
else
return a(nums,target,mid + 1,right);
}
int search(int* nums,int numsSize,int target)
{
return a(nums,target,0,numsSize - 1);
}

posted @   傲骨风寒  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示