文章目录
实验目的
1)了解分治策略算法思想及基本原理;
2)掌握使用分治算法求解问题的一般特征;
3)掌握分解、治理的方法;
4)能够针对实际问题,能够正确的分解、治理,设计分治算法;
5)能够正确分析算法的时间复杂度和空间复杂度。
实验内容(要求)
实现整数和浮点数的二分查找。
算法设计(问题分析、建模、算法描述)
- 二分查找问题描述(整数):
给定N个数据和待查找的数据x,采用二分查找算法来搜索x,输出x在N个数据中的位置。 - 二分查找问题描述(浮点数):
给一个浮点数,求它的根。
分析:
每次取数组中间索引mid = (l + r)/ 2,比较搜索,确定往右还是往左搜,直到l < r停止。由于整数二分存在边界值问题,相较于浮点数二分要多一步处理防止边界错误。
每次二分都会选择答案所在的区间,保证区间里一定有答案,到区间长度为1时,即为答案。
算法源码
整数二分:
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int fd, n;
int a[N];
bool check1(int x)
{
if(a[x] >= fd)
return true;
else
return false;
}
bool check2(int x)
{
if(a[x] <= fd)
return true;
else
return false;
} // 检查x是否满足某种性质
// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:(取第一次出现的位置)
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;// r用mid更新,mid用l + r >> 1计算
if (check1(mid)) r = mid; // r用mid更新,mid用l + r >> 1计算
else l = mid + 1;
}
return l;
}
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:(取第二次出现的位置)
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check2(mid)) l = mid;//l用mid更新,mid用l + r + 1 >> 1计算
else r = mid - 1;//l用mid更新,mid用l + r + 1 >> 1计算
}
return l;
}
int main()
{
cin >> n >> fd;
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
cout << bsearch_1(0, n-1) << endl;
cout << bsearch_2(0, n-1) << endl;
return 0;
}
浮点数二分:
#include<iostream>
using namespace std;
int main()
{
double x;
cin >> x;
double l = 0, r = x;
while(r - l > 1e-8) //1e-8表示精确到小数点过后七位,可调整。
{
double mid = (l + r) / 2;
if(mid * mid >= x) r = mid;
else l = mid;
}
cout << l << endl;
return 0;
}
测试数据及运算结果(要求:截图说明算法运行的结果)
整数二分
测试数据1
5 3
1 2 3 8 9
输出:
测试数据2:
5 3
1 2 3 3 9
输出:
浮点数二分
测试数据1:
10.987
输出:
测试数据2:
9856.4321
输出:
算法分析(分析算法的时间复杂度和空间复杂度)
二分算法时间复杂度:O(log n)
在每一次比较后,二分查找会将范围缩小一半,并只搜索高于或低于中间值的半侧范围,因此平均只需进行 log N 次比较即可找到目标元素
二分算法空间复杂度:O(1)
算法的空间复杂度并不是计算实际占用的空间,而是计算整个算法的辅助空间单元的个数。由于辅助空间是常数级别的所以空间复杂度是O(1)。