algorithm 库
-
- lower_bound()
-
- upper_bound()
-
- unique()
lower_bound(first , last , val)
传入参数:
- first : 集合首地址(集合第一个元素的地址)
- last : 集合末尾地址
注: 左闭右闭
举例:
int a[100] = {1 , 2 , 2 , 4 , 4 , 4 , 6 , 8};
int t = lower_bound(a , a + 8 , 3) - a;
在序列中查找3
输出的结果:3(下标从0开始)
说明lower_bound() 是返回第一个大于等于val的地址 , 因为此处减去a(首地址),返回的是数组中的逻辑地址——下标。
对于不存在的该元素会返回对应位置!
input :
5
1 2 3 4 10
15 // 查找的元素
output :
6 // 返回对应位置
实则:该函数将输出按照升序排列 ,输出val第一个大于等于val的位置。意指,就算你是无序数组 , 它会将其处理成有序 , 再查找。这个函数的底层其实是排序 + 二分左边界。
注:该函数是左闭右开的区间,所以 last = (first + 末元素的下标) 即可
upper_bound(first , last , val)
传入参数:
- first : 集合首地址(集合第一个元素的地址)
- last : 集合末尾地址(集合的最后一个元素的地址)
注: 左闭右开
举例:
int t = upper_bound(a , a + 8 , 4) - a;
在序列中查找4
输出的结果:6(下标从0开始)
说明upper_bound() 是返回第一个大于val的地址
实则:该函数的底层也是有序表+二分查找 使用方法和lower_bound() 几乎相同
注:对于这个两个函数还可以自定义排序规则 , 再进行二分。 两个函数默认升序规则 , 此处代码是降序规则。
int t = lower_bound(a , a + 7 , 3 , greater<int>()) - a;
upt
今天踩了一个坑 ,半天才反应过来。
std::cin >> n >> k;
std::vector<int> v(n);
for (int i = 0; i < n; i ++ ) std::cin >> v[i];
std::sort(v.begin() , v.end());
int idx = *std::lower_bound(v.begin() , v.end() , k) + 1;
std::cout << idx << '\n';
这样的元素返回二分到的值 , 因为返回的这个迭代器是指向二分到的值,解引用的话直接拿到的该值了 upper_bound(container.begin() , container.end() , value) 类似。笔者遇到这个问题甚至问了gpt ,被自己蠢笑了。
unique(first , last)
传入参数
- first:元素首地址
- last : 集合末地址的后面一个位置 注: 左闭右开
int t = unique(a , a + 8) - a;
for (int i = 0; i < 8; i ++ )
cout << a[i] << ' ';
puts("\n");
cout << "t = " << t << '\n';
puts("");
for (int i = 0; i < t; i ++ )
cout << a[i] << ' ';
据此可以观察到 unique 是将相同的元素放到最后面了,返回了最后一个不重复的元素的个数(下标从0开始) , 同时也可以理解成返回了不重复元素的最后一个元素下一个元素位置
注:使用unique() 需要先将元素排序,才能正确去重!
区间问题
对于lower_bound 、upper_bound 、unique , 我都非常纠结区间,其实参见vector 查询元素即可。 vector.end() 是最后一个元素的后一个位置。
离散化方法
- 排序 , 使用sort 函数
- 去重 , 使用unique 函数
- 二分索引 , 推荐可以使用lower_bound , 不需要写二分函数。