c++20|第k大-快速选择|nth_element
lc1738
二维异或和
neat
只要满足交换律并且重复计算 那么二维矩阵不管是什么处理 都可以用二维前缀和加法的思想
这里XOR是一样的
还可利用 a ^ a ^ a = a,进行一维优化
class Solution {
public:
int kthLargestValue(vector<vector<int>>& matrix, int k) {
int m = matrix.size(), n = matrix[0].size();
vector<int> a;
vector<vector<int>> s(m + 1, vector<int>(n + 1));
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
s[i + 1][j + 1] = s[i + 1][j] ^ s[i][j + 1] ^ s[i][j] ^ matrix[i][j];
}
//添加每行
a.insert(a.end(), s[i + 1].begin() + 1, s[i + 1].end());
}
ranges::nth_element(a, a.end() - k);
return a[a.size() - k];
}
};
第k大--快速选择算法
要理解最后两行如何获取第 k 大的元素,结合快速选择算法(由 ranges::nth_element 实现)
1. 快速选择算法的作用
ranges::nth_element 是 C++20 引入的算法,基于快速选择思想:
- 它会对容器(这里是 vector<int> a )进行部分排序,使得指定位置的元素最终处于“正确排序后”的位置。
- 具体来说, ranges::nth_element(a, a.end() - k) 会将 a 中第 (a.size() - k) 个位置的元素,调整为“若整个数组排序后,该位置应有的值”。此时:
- 该位置左边的所有元素都小于等于它,
- 该位置右边的所有元素都大于等于它
2. 结合“第 k 大”的逻辑
数组的“第 k 大”元素,等价于排序后数组中从后往前数的第 k 个元素。
- 假设数组长度为 len ,排序后最后一个元素是第 1 大,倒数第二个是第 2 大,……,倒数第 k 个就是第 k 大。
- 因此,“第 k 大的位置”对应数组的索引为 len - k (数组从 0 开始计数)。
3. 代码中两行的联动
- 第一步: ranges::nth_element(a, a.end() - k) 将 a 中索引为 a.size() - k 的元素,调整为“排序后该位置应有的值”(即第 k 大的元素)。
- 第二步: return a[a.size() - k]; 直接返回该位置的元素,即为矩阵所有子矩阵异或和中的第 k 大值。
简单来说, nth_element 通过部分排序,直接定位到“第 k 大”的位置,无需对整个数组完全排序(时间复杂度为 O(N) ,远优于完全排序的 O(N \log N) ),效率更高