目录
前言
这个栏目是对我算法学习过程的同步记录,我也希望能够通过这个专栏加深自己对编程的理解以及帮助到更多像我一样想从零学习算法并参加竞赛的同学。在这个专栏的文章中我会结合在编程过程中遇到的各种问题并提出相应的解决方案。当然,如果屏幕前的你有更好的想法或者发现的错误也欢迎交流和指出!不喜勿喷!不喜勿喷!不喜勿喷!那么事不宜迟,我们马上开始吧!
一、最值查找
1.min和max函数
(1)min(a,b)返回a和b中较小的值,且函数只能传入两个值或者一个列表。
(2)max(a,b)返回a和b中较大的值,且函数只能传入两个值或者一个列表。
以下是代码示例:
cout << min(3, 5) << endl; //3
cout << min({1, 3, 6, 7, 9}) << endl;//1
cout << max(3, 5) << endl; //5
cout << max({1, 3, 6, 7, 9}) << endl;//9
min和max函数是取最值时常用的操作,应当熟练掌握。这里注意,min和max函数不能直接将vector类型和数组类型当做参数传入。
2.min_element和max_element函数
(1)min_element(start, end); 返回[start, end)中最小的那个值的地址或者迭代器,传入参数为两个地址或者迭代器。这里[start, end)是一个左闭右开区间。
(2)max_element(start, end); 返回[start, end)中最大的那个值的地址或者迭代器,传入参数为两个地址或者迭代器。这里[start, end)是一个左闭右开区间。
下面是一段代码示例:
vector<int> v = {1, 2, 6, 8, 4, 9};
cout << *min_element(v.begin(), v.end()) << endl;
注意,这里的*表示解引用,即由地址得到对应存储的值。
3.nth_element函数
(1)格式:nth_element(start, k, end); 进行部分排序,返回值为void()。传入参数为三个地址或迭代器。其中第二个参数位置的元素将处于正确位置,其他位置元素顺序可能是任意的。但是前面的都比它小,后面的都比它大。时间复杂度为O(n)
以下是代码示例:
vector<int> v = {5, 1, 7, 3, 10, 18, 9};
nth_element(v.begin(), v.begin() + 3, v.end());
for(auto &i : v) cout << v[i] << ' ';//3 1 5 7 9 18 10
4.代码示例
这里的例题是lanqiao OJ 497,链接如下:
https://www.lanqiao.cn/problems/497/learning/
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
int sum = 0;
cin >> n;
int* a = new int[n];
for (int i = 0; i < n; ++i)
{
cin >> a[i];
cout << endl;
}
cout << *max_element(a, a + n) << endl;
cout << *min_element(a, a + n) << endl;
for (int i = 0; i < n; ++i) sum += a[i];
cout << fixed << setprecision(2) << 1.0 * sum / n << endl;
delete[]a;
return 0;
}
二、二分查找
1.二分查找的前提
对于库函数来说,只能对数组进行二分查找。对一个数组进行二分查找的前提是这个数组是单调的,一般为单调不减。单调不增也可,但是需要修改比较函数。在使用时,常常搭配sort()函数使用。关于sort()排序函数的用法,可以参考我的这篇文章:https://blog.csdn.net/ConquerObstacles/article/details/134428470
2.binary_search函数
binary_serach函数是一个C++标准库中的一个算法函数,用于在已排序的序列(例如数组或容器)中查找特定的元素。函数返回一个bool值,表示目标元素是否存在于序列中。
代码示例:
vector<int> v = {1, 3, 5, 7, 9};
int target = 5;
bool found = binary_search(v.begin(), v.end(), target);
if(found)
{
cout << "target " << target << " found." << endl;
}
else
{
cout << "Not found."
}
2.lower_bound和upper_bound函数
需要获取找到元素的位置,可以使用这两个函数。
使用前提:数组必须为单调不减
如果要在非升序的数组中使用,可以通过修改比较函数实现(方法与sort类似)。
lower_bound(start, end, x);返回地址[start, end)中第一个大于等于x的元素的地址。
upper_bound(start, end, x);返回地址[start, end)中第一个大于x的元素的地址。
如果不存在则返回最后一个元素的下一个位置,在vector中即end()。
代码示例:
vector<int> v = {5, 1, 7, 3, 10, 18, 9};
sort(v.begin(), v.end());// 1 3 5 7 9 10 18
for(auto i : v)cout << v[i] << ' ';
cout << endl;
cout << (lower_bound(v.begin(), v.end(), 8) - v.begin()) << endl;//4
这里我们不妨再深度剖析一下。
首先我们看一下输出结果是一个数字4,背后的运算逻辑是这样的:地址-首地址=下标。这一点的话学过单片机的同学会非常熟悉。在STM32中,每个外设寄存器的地址实际上就是外设基地址加上地址偏移得到的,于此有异曲同工之妙。这一段没看懂也没关系,就当我在闲扯吧。
然后我们再来考察一下这两个函数的命名方式,我们先准备如下的数组。
1 | 2 | 3 | 8 | 8 | 8 | 8 | 9 | 10 |
[ | ) | |||||||
lower_bound | upper_bound |
显然两者一个是上界,一个是下界。
3.代码示例
这里的例题是lanqiao OJ 1389,链接如下:https://www.lanqiao.cn/problems/1389/learning/
代码如下:
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int data[200];
for(int i = 0 ; i < 200 ; i ++)data[i] = 4 * i + 6;
int x;cin >> x;
sort(data,data+200);
cout << (lower_bound(data,data+200,x)) - data << endl;;
return 0;
}
总结
我也从没想过查找的库函数还有这么多的花样。总而言之,如果你觉得这篇文章还不错,劳烦多多支持一下!码字不易,感谢你的观看!