题目大意:
给你一个二维矩阵 matrix
和一个整数 k
,矩阵大小为 m x n
由非负整数组成。
矩阵中坐标 (a, b)
的 值 可由对所有满足 0 <= i <= a < m
且 0 <= j <= b < n
的元素 matrix[i][j]
(下标从 0 开始计数)执行异或运算得到。
请你找出 matrix 的所有坐标中第 k 大的值(k 的值从 1 开始计数)。
来源:力扣(LeetCode
)
链接:https://leetcode-cn.com/problems/find-kth-largest-xor-coordinate-value/
解决思路:
这题的思路是使用动态规划进行优化,再使用选择算法进行求第K大的数。
设定 dp[n][m] =
∑
i
=
0
,
j
=
0
n
,
m
\sum_{i=0, j=0}^{n, m}
∑i=0,j=0n,m^matrix[i][j] ,该dp
数组可以在O(nm)复杂度内计算。故所求矩阵也就是dp
。将其带入第K大选择算法中即可。
时间复杂度:O(nm) 空间复杂度:O(nm)
class Solution {
public:
int kthLargestValue(vector<vector<int>>& matrix, int k) {
int dp[1005][1005];
memset(dp, 0, sizeof dp);
int s[1005 * 1005], tot = 0;
int n = matrix.size(), m = matrix[0].size();
for (int i = 1; i <= n; i++) {
int pre = 0;
for (int j = 1; j <= m; j++) {
pre ^= matrix[i - 1][j - 1];
dp[i][j] = pre ^ dp[i - 1][j];
s[tot++] = dp[i][j];
}
}
return select(s, tot, tot - k + 1);
}
int select(int a[], int len, int k) {
if (len <= 38) {
sort(a, a + len);
return a[k - 1];
}
int i, j, z, ans;
int *p = new int[3 * len / 4], *q = new int[3 * len / 4];
for (i = 0; i < len / 5; i++) {
p[i] = Mid(a, i);
}
int middle = select(p, i, (i + 1) / 2);
i = j = z = 0;
for (int t = 0; t < len; t++) {
if (a[t] < middle)
p[i++] = a[t];
else if (a[t] == middle)
j++;
else
q[z++] = a[t];
}
if (i >= k)
ans = select(p, i, k);
else if (i + j >= k)
ans = middle;
else
ans = select(q, z, k - i - j);
delete[] p, q;
return ans;
}
int Mid(int a[], int i) {
int k = i * 5;
if (a[k] > a[k + 2])
swap(a[k], a[k + 2]);
if (a[k + 1] > a[k + 3])
swap(a[k + 1], a[k + 3]);
if (a[k] > a[k + 1])
swap(a[k], a[k + 1]);
if (a[k + 2] > a[k + 3])
swap(a[k + 2], a[k + 3]);
if (a[k + 1] > a[k + 2])
swap(a[k + 1], a[k + 2]);
if (a[k + 4] > a[k + 2])
return a[k + 2];
else if (a[k + 4] > a[k + 1])
return a[k + 4];
else
return a[k + 1];
}
};