Link:
题目要求
给定一个m * n矩阵,对每一个位置,求其所在主对角线的 | 左上角所有元素中不同元素的个数 - 右下角所有元素中不同元素的个数 |,记录到answer矩阵的对应位置 注:grid[i][j] ≤ 50
核心算法和原理
- 对角线的遍历模板:对于同一主 / 副对角线上的元素,其下标一定满足i - j / i + j 为定值
- 主对角线:令k = i - j + n, 则左下角的对角线 k = m + n - 1,右上角的 k = 1
- 副对角线:令k = i + j,则左上角的k = 0,右下角的k = m + n - 2
- 遍历每条对角线的前后缀(不同元素的个数),则ans[i][j] = 对应位置的 前后缀之差的绝对值,可以直接记录到ans里
- 位运算优化:grid元素最大50,拿一个uint64_t记录不同元素个数
- popcount(i): i的二进制表示中1的个数
代码
class Solution { public: vector<vector<int>> differenceOfDistinctValues(vector<vector<int>>& grid) { int m = grid.size(), n = grid[0].size(); vector<vector<int>> ans(m, vector<int>(n, 0)); uint64_t cntBit = 0; // diagnoals iteration: i - j is const // k = i - j + n, left below: k = m + n - 1, right above: k = 1 for (int k = 1; k < m + n; k++) { int minj = max(0, n - k); int maxj = min(n - 1, m + n - 1 - k); cntBit = 0; for (int j = minj; j <= maxj; j++) { int i = k - n + j; ans[i][j] = popcount(cntBit); cntBit |= (1ULL << grid[i][j]); } cntBit = 0; for (int j = maxj; j >= minj; j--) { int i = k - n + j; ans[i][j] = abs(ans[i][j] - popcount(cntBit)); cntBit |= (1ULL << grid[i][j]); } } return ans; } };
