文章目录
- 1.二分查找mid防溢出
- 2.快速幂扩展
- 3.vector实现领接矩阵
- 4.有序集合的范围查找
- 5.查找容器内最大最小值
- 6.含边界位置遍历方案
1.二分查找mid防溢出
我们通常写二分求mid
,一般这样写:
int mid = (right - left >> 1) + left;
原因在于两个正整数int
相加,可能存在溢出的可能性,因此我们使用减法,而不直接使用加法。这是一个好的编程习惯。
下面的写法存在溢出风险:
int mid = right + left >> 1;
- 四则运算的优先级高于左移和右移运算。
下面的写法是错误的:
int mid = right - left >> 1 + left; //这等价于(right - left) >> (1 + left);
2.快速幂扩展
快速幂可以在
O
(
l
o
g
n
)
O(logn)
O(logn)的时间内算出一个
n
n
n次幂,那么如果我们将需要递推计算
n
n
n次的内容,直接找到规律,得到通项公式,那么我们在
O
(
l
o
g
n
)
O(logn)
O(logn)的时间内就能计算完。
- 快速幂不仅能够求普通数乘,也可以求矩阵乘法
- 即使是对于 a n = a n − 1 + a n − 2 a_n = a_{n-1} + a_{n-2} an=an−1+an−2这样的斐波那契数列,也是可以通过矩阵乘法得到递推关系的。
3.vector实现领接矩阵
vector<vector<int>> matrix(n, vector<int>(n,0));
4.有序集合的范围查找
很多时候我们想使用一个动态的可维护的有序序列:
- 插入排序 O ( n ) O(n) O(n)
- 每加入一个元素排序 O ( n l o g n ) O(nlogn) O(nlogn)
- 使用
set
和map
维护 O ( l o g n ) O(logn) O(logn)
更多时候我们不仅要维护一个有序序列,我们还想进行查找元素,很显然set
和map
都能以
O
(
l
o
g
n
)
O(logn)
O(logn)的速度查找到元素。但是如果我们要找到一个范围的值呢?比如不大于target
的值存不存在,不大于target
的值存在的话第一个是几?
这个问题有序集合set
和map
都能解决。使用lower_bound()
和upper_bound
。
-
lower_bound
和upper_bound
的定义lower_bound(x)
:返回指向第一个不小于x
的元素的迭代器。(大于等于)upper_bound(x)
:返回指向第一个大于x
的元素的迭代器。- 如果没有则返回尾迭代器。
例题:LeetCode:220. 存在重复元素 III
5.查找容器内最大最小值
min_element()
,可以用于任何支持前向迭代的迭代器。它返回最小元素的所在的迭代器。
unordered_set<int> st = {2,3,4,6,1,0};
vector<int> vec = {12,6,9,13};
cout << *min_element(st.begin(), st.end()) << '\n';
cout << *min_element(vec.rbegin(), vec.rend());
max_element()
,可以用于任何支持前向迭代的迭代器。它返回最大元素的所在的迭代器。
例题:LeetCode:931. 下降路径最小和
6.含边界位置遍历方案
对于一个for
循环,我们经常使用if
语句来判断边界条件,这样是可行的,不过这样导致每一个元素都会被进行判断。
那么若每个边界值都有相同的操作,我们何不把它提取出来对其进行单独操作,然后循环非边界值元素。这样就不需要进行判断了。
正如以下代码:
对于左右两个边界,我们有相同的操作,对于中间元素我们也有相同的操作。我们直接将边界的两个元素拿出来单独操作,中间元素直接for
循环,节省了if
语句。
class Solution {
public:
int minFallingPathSum(vector<vector<int>>& matrix) {
if(matrix.size() == 1) return matrix[0][0];
int n = matrix.size();
for(int i = 1; i < n; ++ i){
matrix[i][0] += min(matrix[i - 1][0], matrix[i - 1][1]);
for(int j = 1; j < n - 1; ++ j){
matrix[i][j] += min(matrix[i - 1][j], min(matrix[i - 1][j - 1], matrix[i - 1][j + 1]));
}
matrix[i].back() += min(matrix[i - 1].back(), matrix[i - 1][n - 2]);
}
return *min_element(matrix.back().begin(), matrix.back().end());
}
};