当前位置:首页 > 算法 > 正文内容

【二分】----基础用法

亿万年的星光5年前 (2021-01-28)算法2658
0.二分法简介
  • 二分法是一种查找算法

  • 要求:数据必须是有序序列

  • 核心思想:掐头去尾取中间


1. 引入

对于一个有序数组,如{1,3,6,8,23,56,78,99},如果我们要查找其中的一个数78的下标位置,按照以前的写法,可能会这么写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
    int a[]={1,3,6,8,23,56,78,99},target;// 定义数组和要查找的目标
    int len= sizeof(a)/sizeof(int);
    cin>>target;
    for(int i=0;i<len;i++)
    {
        if(a[i]==target)
            {
                cout<<i<<endl;
                return 0;
            }
    }
    return 0;
}

这种顺序查找的方式对于数据量较小的情况还可以应付,但是对于数据量大的情况就很难处理了。试想一下特殊情况,如果你要查找的值正好在数组的最后一个,那么你的时间复杂度就是O(n)。所以引入二分查找来解决这个问题。


640?


640?


2. 二分法求解

【例题1】

【题目描述】

给定一个排序的整数数组(升序)和一个要查找的整数target,找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1

【输入描述】

输入包含三行,第一行n,表示有n个数,第二行是已经排好序的n个数,第三行是target。

【输出描述】

一行,target第一次出现的下标,如果没有找到输出-1。

【样例输入1】

6
1 4 6 7 9 11
4


【样例输出1】

1

【样例输入2】

7
1 2 6 8 9 12 78
4

【样例输出2】

-1


【注意】题目不一定有解,可以遵循下面的算法框架

1
2
3
4
5
6
7
8
9
10
11
while (left < right - 1) {
    int mid = left + (right - left) / 2;
    //添加结束条件
     
    //
    if (A[mid] > A[left]) {
        left = mid;
    } else {
        right = mid;
    }
}


【参考代码】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<cstdio>
#include<iostream>
using namespace std;
int search(int A[], int n, int target) 
    int left = 0, right = n-1; 
    while(left <= right) 
    
        // 注意:若使用(low+high)/2求中间位置容易溢出 
        int mid = left+((right-left)>>1);  
        if(A[mid] == target) 
            return mid; 
        else if(A[mid] < target) 
            left = mid+1; 
        else // A[mid] > target 
            right = mid-1; 
    
    return -1; 
int main()
{
    int a[100]={0},target;// 定义数组和要查找的目标
    int len,n,index;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];   
    }  
    cin>>target;
    index = search(a,n,target);
    cout<<index;
    return 0;
}



【例题2】

【题目描述】

给定一个有序(非降序)数组A,可含有重复元素,求最大的i使得A[i]等于target,不存在则返回-1。

【输入描述】

输入包含三行,第一行n,表示有n个数,第二行是已经排好序的n个数。

【输出描述】

一行,target最后一次出现的下标,如果没有找到输出-1。



扫描二维码推送至手机访问。

版权声明:本文由青少年编程知识记录发布,如需转载请注明出处。

分享给朋友:

相关文章

【算法】动态规划—区间DP问题

一、定义区间DP是动态规划的一种特殊形式,主要用于解决涉及区间操作的问题,比如合并区间、分割区间、区间匹配等。其核心思想是通过枚举区间的划分点,将大区间的问题分解为小区间的子问题,逐步求解并保存中间结...

【排序】----插入排序

【排序】----插入排序

1.基本思想在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。2.过程·(1)从第一个元素开始,该元素可以...

【算法】最短路径算法——Floyed-Warshell算法

【算法】最短路径算法——Floyed-Warshell算法

如下图所示,我们把边带有权值的图称为带权图。边的权值可以理解为两点之间的距离。一张图中任意两点间会有不同的路径相怜。最短路径就是指连接两点的这些路径中最短的一条。【注意】边的权值可以为负。当出现负边权...

【贪心】----最优装载、背包、乘船问题

【贪心】----最优装载、背包、乘船问题

1.最优装载题目描述:有n个物体,第i个物体的重量为wi(wi为正整数)。选择尽量多的物体,使得总重量不超过C。【分析】由于只关心选择的物品的最大数量(而不是最大重量,最大重量需要考虑DP),所以装重...

【贪心】最大子矩阵

【题目描述】已知矩阵的大小定义为矩阵中所有元素的和。给定一个矩阵,你的任务是找到最大的非空(大小至少是1X1)子矩阵。比如,如下4 x 4的矩阵0    -2&...

【算法】博弈论——取石子游戏

【题目描述】有两堆石子,数量任意,可以不同。游戏开始由两个人轮流取石子。游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子;二是可以在两堆中同时取走相同数量的石子。最后把石子全部取...