二分查找

查找算法--二分查找

北慕城南 提交于 2019-12-02 11:34:01
1、什么是二分查找 二分查找又称为 折半查找, 首先是从 有序数组(必须是有序数组) 的中间元素开始查找,如果中间元素是查找数,就返回; 如果中间元素大于或者小于查找数,就从大于或小于查找数的一方继续执行二分查找;没找到就返回空,二分查找和传统查找的差别可以看上图 2、二分查找代码思路: 确定该数组的中间下标mid mid=(left+right)/2 让待查找数target和arr[mid]比较 当target>arr[mid]时,说明查找数在mid右边,继续向右边递归查找 当target<arr[mid]时,说明查找数在mid左边,继续向左边递归查找 当target==arr[mid]时,说明查找数已经找到,返回 比较完后找不到,设置递归退出条件:left>right 3、代码实现: static List Index=new ArrayList(); //后面查找元素是多个时使用 public static void main(String[] args) { int arr[]={1,3,5,7,11,11,11,13,17,19,23,29,31,37,41}; Search(arr,0,arr.length-1,11); System.out.println(Index); }  当查找数是单个时: public static int Search(int[] arr

用递归算法进行二分查找

陌路散爱 提交于 2019-12-02 06:21:32
用递归进行二分查找(C语言) #include<stdio.h> #include<stdlib.h> #define N 100 /*递归二分查找*/ int compare(const void *value1, const void *value2) { // 升序 return (*(int*)value1 - *(int*)value2); } int f(int a[], int p, int x,int y){ while( y > x){ int mid = (y - x)/2 +x; if(p == a[mid] ) return mid; if(p>a[mid]) return f(a,p,x+1,y); else return f(a,p,x,y-1); } return -1; } int main(){ int a[N],p,m; printf("你想输入几个数:"); scanf("%d", &m); printf("请输入数组里面的数: \n"); for(int i = 0; i<m; i++){ scanf("%d", &a[i]); } qsort(a, m, sizeof(int), compare); printf("排序后的数:\n"); for(int j = 0; j< m; j++) { printf("%d ", a[j]); }

二分查找——校招题

余生长醉 提交于 2019-12-02 05:52:53
一、二分查找的介绍   二分查找:就是在有序的序列当中进行快速查找你想要的数据,通过不断从中间分割查找,达到查找目的   算法思想:假如我现在有一个有序的序列,我需要查找数字 x ,但是如果我从第一个慢慢比较的话,那就太慢了一点,万一我需要的数据再很后面,那就会很影响效率了,那么不如咱们从中间开始找如何?如果序列中间的数恰好是我们想要的数字,那么就查找成功,如果中间的数字比我们所想的数字大,那么就从左边的数组继续二分查找,反之右边也一样。   所以咱们现在有如下规定:      low 代表数组的最左边下标, hight 代表数组的最右边下标, mid 代表数组的中间下标   接着咱们有如下步骤:     1、如果 arr[mid] == target ,那么就直接返回,查找成功啦!     2、如果 arr[mid] > target ,那么就令 hight = mid - 1     3、如果 arr[mid] < target ,那么就令 low = mid     4、每次改变 low ,hight 都要修改 mid = (low + hight)/ 2      5、直 到 最后 low >= hight , 如果此时还没有找到咱们的数据,那就只能告辞了,这个数组没有咱们想要的 二、相关题目   看完了二分查找的介绍,是时候来个题目练练手了!   题目很简单

动态顺序表的基本操作

你离开我真会死。 提交于 2019-12-02 05:15:52
顺序表   顾名思义,就是用一段连续的存储单元依次存储数据元素的线性结构 。 顺序表又分为静态顺序表和动态顺序表。   静态顺序表的基本操作: https://blog.csdn.net/zhao_miao/article/details/81145855 下面我们来分析动态顺序表的基本操作: 我们要完成的基本操作是: 初始化 打印 尾部插入 尾部删除 头部插入 头部删除 查找指定元素 指定位置插入 删除指定位置元素 删除指定元素 删除所有的指定元素 返回顺序表的大小 判断顺序表是否为空 冒泡排序 选择排序 选择排序的优化 二分查找 二分查找递归写法 首先定义一个结构体   与静态顺序表不同,动态顺序表没有最大容量的限制,可以边使用边开辟,节省空间。 # define DataType int typedef struct SeqList { DataType *data; //存放的数据 int sz; //有效元素的个数 int capacity; //容量 }SeqList,*qSeqL   由于顺序表里存放的元素的类型是未知的,所以将int重命名为DataType,若想在顺序表中存储其他类型的数据,只需将int修改为对应的类型即可。 初始化函数   初始化sz,capacity,以及指针data void InitSeqList (qSeqList seq) {

[总结]二分法(二分查找)

青春壹個敷衍的年華 提交于 2019-12-02 03:54:37
[总结]二分法(二分查找) 一、关于二分法 二分法是一种很平常却又很重要的算法。二分法能为我们解题时提供很大的帮助。 1. 使用前提 二分法的适用条件是序列具有 二分性 ,也就是单调性。当序列具有二分性,这时我们不断枚举区间中点才能判断这个值是否题设条件。 当题目中出现诸如 最大值的最小 , 最小值的最大 的问题时,答案具有二分性。 2. 分类 从二分的对象来分类,我们既可以二分最终的答案,我们也可以二分进行判断。 从二分的类型来分类,可以分为 整数域上的二分 ,以及 实数域上的二分 。 3. 易错点 二分法简单易写,但是却很容易写错。我们有很多方法实现二分,而其中的细节地方需要仔细考虑。 对于整数域上的二分: 我们需要注意终止条件,左右区间位置的变化,避免错过答案或造成死循环。 对于实数域上的二分: 我们需要注意精度的控制。 建议自己形成固定的代码模型,避免造成不必要的错误。 4. 二分法的延伸 C++ STL中的 lower_bound , upper_bound 也可以解决实现在一个序列中二分查找某个整数 k 的后继。 二分法能够解决单调问题,进一步地,我们可以扩展二分法至 三分法 。此时三分法可以解决单峰函数的极值问题。 二、整数域上的二分 1. 模板 在这里给出一种常见的模板: while(l<=r){ int mid=(l+r)>>1; if(check(mid)){

第81题:搜索旋转排序数组II

戏子无情 提交于 2019-12-02 02:12:14
一. 问题描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转。 ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。 编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。 示例 1: 输入: nums = [2,5,6,0,0,1,2], target = 0 输出: true 示例 2: 输入: nums = [2,5,6,0,0,1,2], target = 3 输出: false 进阶: 这是 搜索旋转排序数组 的延伸题目,本题中的 nums 可能包含重复元素。 这会影响到程序的时间复杂度吗?会有怎样的影响,为什么? 二. 解题思路 解题思路:本题首先找到旋转点point,然后再进行二分查找。 步骤一:通过遍历数组找到旋转点point,判断target在point点左边还是右边。 步骤二:如果point在左边,则对左边进行二分查找。否则对右边进行二分查找。 注意:这一题的关键点是各种特殊情况需要考虑到. 三. 执行结果 执行用时 :1 ms, 在所有 java 提交中击败了99.84%的用户 内存消耗 :39.8 MB, 在所有 java 提交中击败了10.42%的用户 四. Java代码 class Solution { public boolean search(int[] nums

二分查找的递归实现和非递归实现

限于喜欢 提交于 2019-12-01 20:53:51
二分查找的递归实现和非递归实现【java】 (1)非递归实现二分查找。 算法是由静态方法binarySearch()实现的,它接受一个整数健和一个有序的int数组作为参数。如果该健存在于数组中,则返回他的索引,否则返回-1。 算法使用两个变量lo和hi,并保证如果健在数组中则它一定在a[lo…hi]中,然后方法进入一个循环,不断地将数组的中间健(索引为mid)和被查找的健比较。如果被查找的健等于a[mid],返回mid;否则算法将查找的范围缩小一半,如果被查找的健小于a[mid]就继续在左边查找,如果被查找的健大于a[mid]就继续在右边查找。 算法找到被查找的健,或者是查找范围为空时,该过程结束。 二分查找的时间复杂度O(logn)。 以下为二分查找的详细代码。 import java . util . * ; //导入必要的包。 public class BinarySearch2 { public static int binarySearch ( int [ ] a , int key ) { int lo = 0 ; //指向数组的第一个元素。 int hi = a . length - 1 ; //指向数组的最后一个元素。 while ( lo <= hi ) { int mid = ( lo + hi ) / 2 ; //取数组中间。 if ( key > a [

二分查找算法递归和非递归实现

倾然丶 夕夏残阳落幕 提交于 2019-12-01 20:51:49
自己接触和了解过的查找算法总结起来分为3个吧: 1. 静态查找(主要是二分查找,效率较高) 2. 动态查找(二叉查找树) 3. 哈希表 首先来说二分查找吧! 基本思想: 假设在一个已经排好序的有序序列(N个元素,升序排列),首先让序列N中中间的关键字与需要查找的关键字进行比较,如果相等,则查找成功,否则利用中间位置将序列分成两个子序列,如果待查找的关键字小于中间的关键字,则在前一个子序列中同样的方法进一步查找, 如果待查找的关键字大于中间的关键字,则在后一个子序列中同样的方法进一步查找,重复以上过程一直到查找结束! 时间复杂度:O(log(n)) 空间复杂度:O(1) 代码示例: #include <stdio.h> //二分查找非递归实现 int BinSearch1(int Array[], int low, int high, int key) { int ret = -1; int mid = 0; ret = (Array != NULL) && (low >= 0) && (high > low); printf("Search Key: %d\n", key); if(ret) { while(low <= high) { mid = (low + high)/2; if(Array[mid] == key) { ret = mid; printf(

二分查找(附递归的二分查找方法)

帅比萌擦擦* 提交于 2019-12-01 20:18:11
二分查找是在一组排好序的数组里查找某个指定的元素。 例如查找元素7,则如下。 利用Scanner获取一个元素,在数组中查找,先找到数组的中间位置 middle =(left+right)/2; 如果所找的元素小于中间位置的元素,则在该中间位置的左边寻找,并且将middle-1(中间位置已经比过了)值赋给right,在求出左边元素的中间下标,直到找到该元素,右侧的原理相同。 实现如下: import java.util.Scanner; public class 二分查找 { public static void main(String[] args) { int arr[] = {1,5,7,10,15,20,28,56,79,85}; Scanner sc = new Scanner(System.in); int val = sc.nextInt(); int index = search(arr,val); System.out.println(index); } /** * * @param arr * @param val 要查找的数 * @return 元素下标 */ private static int search(int[] arr, int val) { int right = arr.length - 1; int left = 0; while(left <

poj3977(折半枚举+二分查找)

岁酱吖の 提交于 2019-12-01 18:29:03
题目链接:https://vjudge.net/problem/POJ-3977 题意:给一个大小<=35的集合,找一个非空子集合,使得子集合元素和的绝对值最小,如果有多个这样的集合,找元素个数最少的。 思路:显然,可以用折半搜索,分别枚举一半,最大是2的18次方,复杂度能够满足。因为集合非空,枚举时考虑只在前一半选和只在后一半选的情况。对于前一半后一半都选的情况,把前一半的结果存下来,排序,枚举后一半的时候在前一半里二分查找最合适的即可。 思路不难,实现有很多细节,最开始用dfs写得一直wa,改成二进制循环才A。 AC代码: #include<cstdio> #include<algorithm> #include<map> using namespace std; typedef long long LL; typedef pair<LL,int> PLI; const LL inf1=1e17; const int inf2=0x3f3f3f3f; int n,m,cnt,ans2; LL a[40],ans1; PLI b[140005]; map<LL,int> mp; LL absLL(LL x){ return x>=0?x:-x; } int main(){ while(scanf("%d",&n),n){ mp.clear(); cnt=0; ans1=inf1;