算法通关村第9关【青铜】| 二分查找

news/2024/11/28 17:52:49/

一、基本查找

递增数组,从头往尾查找,O(n)的时间即可找到

public static int find(int[] nums,int target){for(int i = 0;i<nums.length;i++){if(nums[i] == target){return nums[i];}}return -1;
}

二、二分查找与分治

有序的数组从头到尾找效率未免太低,就像给一本电话簿查找指定电话肯定不会从第一页开始翻

二分查找是一种高效的查找算法,通常用于在有序数组或列表中查找特定元素的位置。它的基本思想是将待查找区间不断缩小为两部分,然后比较中间元素与目标元素的大小,从而决定继续查找的方向。如果中间元素等于目标元素,则找到了;如果中间元素大于目标元素,则在左半部分继续查找;如果中间元素小于目标元素,则在右半部分继续查找。通过每次排除一半的元素,二分查找的时间复杂度为 O(log n)。

分治是一种算法设计策略,它将问题分解为多个子问题,然后递归地解决这些子问题,最后将子问题的解组合起来得到原问题的解。分治通常包括三个步骤:分解、解决和合并。在分解阶段,原问题被划分为一系列子问题;在解决阶段,对每个子问题进行递归求解;在合并阶段,将子问题的解合并成原问题的解。分治的经典应用包括归并排序和快速排序等。

在某些情况下,二分查找和分治可以结合使用。例如,在分治算法中,当问题的规模缩小到一定程度时,可以使用二分查找来解决子问题。这种结合能够充分利用二分查找的高效性质,并且在解决复杂问题时保持分治的思想。

1.循环的方式

需要注意的细节有循环继续条件是小于等于,有可能数组长度为1就一个元素并且满足目标

还有就是left + right可能超过大小,改除法为位运算会快很多

class Solution {public int search(int[] nums, int target) {int left = 0;int right = nums.length - 1;while(left <= right){int mid = left + ((right - left) >> 1);if(nums[mid] == target){return mid;}else if(nums[mid]>target){right = mid - 1;}else{left = mid + 1;}}return -1;}}

2.递归的方式

class Solution {public int search(int[] nums, int target) {return trace(nums,0,nums.length -1 ,target);}public int trace(int[] nums,int left,int right,int target){if(left <= right){int mid = left + ((right - left) >> 1);if(nums[mid] == target){return mid;}else if(nums[mid]>target){return trace(nums,left,mid-1,target);}else{return trace(nums,mid + 1,right,target);}}return -1;}}

3.元素中有重复的二分查找

如果是非递减的有重复元素的数组,找到最左侧的第一个

private static int binSearch(int[] nums, int target, int left, int right){if(left <= right){int mid = left + ((right - left)>>1);if(nums[mid] == target){while(nums[mid] == target){mid--;}return mid + 1;}else if(nums[mid] < target){binSearch(nums,target,mid + 1,right);}else {binSearch(nums,target,left,mid -1);}}return -1;}

当重复的元素很多的时候也可以采用二分法

private static int binSearch(int[] nums, int target, int left, int right){if(left <= right){int mid = left + ((right - left)>>1);if (nums[left] == target){return left;}if(nums[mid] == target){return binSearch(nums,target,left,mid);}else if(nums[mid] < target){return binSearch(nums,target,mid + 1,right);}else {return binSearch(nums,target,left,mid -1);}}return -1;}

递归三部曲:

第一步:确定参数和返回值

第二步:确定终止条件

当left>right时说明不符合条件终止

当nums[left]=target说明找到目标返回left ,left代表范围内的最左端

if (nums[left] == target){return left;
}

第三步:确定单层逻辑

二分查找逻辑,左闭右闭

相等的时候让最右端的right指向mid,二分向左缩小每次只移动右指针

只有nums[mid]小于target才移动left,这样就能保证left一定是范围内的最左端

if(nums[mid] == target){return binSearch(nums,target,left,mid);
}


http://www.ppmy.cn/news/1078732.html

相关文章

《C和指针》笔记18:前缀++ 和后缀++

C 语言里有前缀 和后缀&#xff0c;使用还是有点不同的。对应的还有--操作符&#xff0c;但它们的工作原理与此相同&#xff0c;只是它所执行的是减值操作而不是增值操作。我们只要掌握的原理&#xff0c;--的原理也就知道了。 在这里我们把符号叫做操作符&#xff0c;把它操作…

Docker consul 容器服务自动发现和更新

目录 一、什么是服务注册与发现 二、Docker-consul集群 1.Docker-consul consul提供的一些关键特性 2.registrator 3.Consul-template 三、Docker-consul实现过程 以配置nginx负载均衡为例 先配置consul-agent &#xff0c;有两种模式server和client 四、Docker-cons…

百万级并发IM即时消息系统(2)

1.用户model type UserBasic struct {gorm.ModelName stringPassWord stringPhone string valid:"matches(^1[3-9]{1}\\d{9}$)"Email string valid:"email"Avatar string //头像Identity stringClientIp s…

文心一言接入Promptulate,开发复杂LLM应用程序

简介 最近在尝试将文心一言的LLM能力接入Promptulate&#xff0c;故写了一篇博客记录一下&#xff0c;Promptulate 是 Promptulate AI 旗下的大语言模型自动化与应用开发框架&#xff0c;旨在帮助开发者通过更小的成本构建行业级的大模型应用&#xff0c;其包含了LLM领域应用层…

Python中 re.compile 函数的使用

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 以下介绍在python的re模块中怎样应用正则表达式 &#x1f447; &#x1f447; &#x1f447; 更多精彩机密、教程&#xff0c;尽在下方&#xff0c;赶紧点击了解吧~ python源码、视频教程、插件安装教程、资料我都准备…

AI助乡行——点燃乡村振兴新引擎

随着数字化浪潮的袭来&#xff0c;乡村振兴战略的推进离不开数字化、智慧化等现代化治理能力和方式&#xff0c;人工智能等高新技术正不断与农村经济、社会、治理等加速融合。在智慧农业的背景下&#xff0c;我们可以解决一系列困扰农民的问题&#xff0c;包括如何增加经济作物…

游戏服务器成DDoS最大攻击重灾区

游戏产业的迅猛发展也让游戏产业成为被黑客攻击的重灾区。什么原因让游戏行业成为DDoS的攻击重点。总结有如下原因和主要手段&#xff1a; 1.游戏行业的攻击成本较低&#xff0c;攻防成本1&#xff1a;N。随着DDoS攻击的打法越来越复杂&#xff0c;攻击点更是越来越多&#xff…

Effective STL 1.仔细选择你的容器

Effective STL 1.仔细选择你的容器 文章目录 Effective STL 1.仔细选择你的容器迭代器容器分类连续内存容器和基于节点的容器的区别 如何选择容器结语>>>>> 欢迎关注公众号【三戒纪元】 <<<<< 标准序列容器 vector、string、deque 和 list 标准…