【练习题】二分法

传统二分

特点:

在一个有序、无重复元素的数组中找出某个关键字

二分查找步骤:

  • 循环的条件是:left <= right

1、用三个指针leftmidright分别指向数组头、中间、尾leftright之间是待查找区

2、在待查找区间中,如果数组中间位置mid指向的值等于目标值,则表示已找到目标值

3、 否则:

​ ①. 如果数组中间位置mid指向的值小于目标值,则更新待查找区的最左端为中间位置mid的后一个位置:left = mid + 1

​ ②. 如果数组中间位置mid指向的值大于目标值,则更新待查找区的最右端为中间位置mid的前一个位置:right = mid - 1

【注意】:rightleft指向相同的值时:如果目标值等于该值,则找到,否则,表示该数组中没有目标值。

4、 反复进行,直到查找成果或范围缩小为空(left > right)即查找不成功为止

代码演示:

int binary_search(int target, int *num, int len) {
    int left = 0, right = len - 1;
    while (left <= right) {
    	int mid = (left + right) / 2;
    	if (target == num[mid]) return mid;
    	else if (target > num[mid]) left = mid + 1;
    	else right = mid - 1;
    }
    //找不到,返回-1
    return -1;
}

01问题之找出第一个1的位置

问题:

一串字符串,前部分由小写组成,后部分由大写组成,找出字符串中第一个大写字母。

思路:

将所有大写字母全用1来表示,小写字母用0表示

步骤:

  • 循环的条件是:left < right
  1. 写一个函数,用来把单个字符变为01

  2. 用三个指针leftmidright分别指向数组头、中间、尾。

  3. 如果数组中间位置mid指向的字符等于1(即该字符是大写),则让尾部right更新到mid所站的位置:right = mid

    (因为right更新到的mid位置有可能是第一个1出现的位置)

  4. 否则如果数组中间位置mid指向的字符不是1,让left更新到mid的后一个位置:left = mid + 1

    (因为已经确定mid指向的是小写)

  5. (left == right)时,就表示找到了第一个大写字母,否则找不到第一个大写字母

代码演示:

int is_A(char str) {
    if (str >= 'A' && str <= 'Z') {
        return 1;
    }
    return 0;
}
int find_first_capital_letter(char *str, int len) {
    int left = 0, right = len - 1, mid;
    while (left < right) {
        mid = (right + left ) / 2;
        if (is_A(str[mid]) == 1) right = mid;
        else left = mid + 1;
    }
    if (right == left) return left;
    return -1;
}

01问题之找出最后一个0的位置

步骤:

  1. 头(left),尾(right),中间(mid)三个指针
  2. 如果mid0left调到mid的位置:left = mid;
  3. 如果mid1right调到mid的前一个位置:right = mid - 1;

(详细步骤参看01问题之找出第一个1的位置)

二分法进行数值运算——求解方程

题目:

给你一个方程:x^4 + 5 * x^3 + 6 * x^2 + 7 * x + 4 = y,接受一个参数y,求出y值对应的、在0到100的范围内的解x,并返回,若范围内没有,则返回-1.

思路:

无穷趋近于一个值,我们就说这个值是他的解

【注意】y < 4y > x^4 + 5 * x^3 + 6 * x^2 + 7 * x + 4时(即等式不成立时),直接返回-1 (无解)

步骤:

  1. 设三个指针分别指向头,中,尾,其中,头=区间头,尾=区间尾
  2. 如果等式左边结果小于等于y,则left更新为mid所在的位置
  3. 如果等式左边结果大于y,则right更新为mid所在的的位置

代码演示:

#include <math.h>
#define ESP 1e-6
double solve_equation(double y) {
    if (4 > y || y > pow(100, 4) + 5 * pow(100, 3) + 6 * 100 * 100 + 7 * 100 + 4) return -1;
    double left = 0, right = 100, mid;
    while (right - left > ESP) {
        mid = (left + right) / 2;
        if (pow(mid, 4) + 5 * pow(mid, 3) + 6 * mid * mid + 7 * mid + 4 <= y) left = mid;
        else right = mid;
    }
	return left;
}

猜你喜欢

转载自blog.csdn.net/tarawin/article/details/88573916