2965. 找出缺失和重复的数字
2965. 找出缺失和重复的数字
🟢 🔖 数组 哈希表 数学 矩阵 🔗 力扣 LeetCode
题目
You are given a 0-indexed 2D integer matrix grid of size n * n with values in the range [1, n2]. Each integer appears exactly once except a which appears twice and b which is missing. The task is to find the repeating and missing numbers a and b.
Return _a 0-indexed integer array _ans of size2whereans[0]equals toa andans[1]equals tob .
Example 1:
Input: grid = [[1,3],[2,2]]
Output: [2,4]
Explanation: Number 2 is repeated and number 4 is missing so the answer is [2,4].
Example 2:
Input: grid = [[9,1,7],[8,9,2],[3,4,6]]
Output: [9,5]
Explanation: Number 9 is repeated and number 5 is missing so the answer is [9,5].
Constraints:
2 <= n == grid.length == grid[i].length <= 501 <= grid[i][j] <= n * n- For all
xthat1 <= x <= n * nthere is exactly onexthat is not equal to any of the grid members. - For all
xthat1 <= x <= n * nthere is exactly onexthat is equal to exactly two of the grid members. - For all
xthat1 <= x <= n * nexcept two of them there is exatly one pair ofi, jthat0 <= i, j <= n - 1andgrid[i][j] == x.
题目大意
给你一个下标从0 开始的二维整数矩阵 grid,大小为 n * n ,其中的值在 [1, n2] 范围内。除了 a 出现 两次 ,b 缺失 之外,每个整数都恰好出现一次 。
任务是找出重复的数字a 和缺失的数字 b 。
返回一个下标从 0 开始、长度为 2 的整数数组 ans ,其中 ans[0] 等于 a ,ans[1] 等于 b 。
示例 1:
输入: grid = [[1,3],[2,2]]
输出:[2,4]
解释: 数字 2 重复,数字 4 缺失,所以答案是 [2,4] 。
示例 2:
输入: grid = [[9,1,7],[8,9,2],[3,4,6]]
输出:[9,5]
解释: 数字 9 重复,数字 5 缺失,所以答案是 [9,5] 。
提示:
2 <= n == grid.length == grid[i].length <= 501 <= grid[i][j] <= n * n- 对于所有满足
1 <= x <= n * n的x,恰好存在一个x与矩阵中的任何成员都不相等。 - 对于所有满足
1 <= x <= n * n的x,恰好存在一个x与矩阵中的两个成员相等。 - 除上述的两个之外,对于所有满足
1 <= x <= n * n的x,都恰好存在一对i, j满足0 <= i, j <= n - 1且grid[i][j] == x。
解题思路
思路一:数学法
设:缺失的数 y,重复的数 x,可以列出 两条数学公式:
和的公式:
- 记
expectSum为[1, 2, ..., n^2]的总和,actualSum为grid中所有数的和: y - x = expectSum - actualSum- 记为:
diffSum。
- 记
平方和的公式:
- 记
expectSquareSum为[1, 2, ..., n^2]的平方和,actualSquareSum为grid中所有数的平方和: y^2 - x^2 = expectSquareSum - actualSquareSum- 记为:
diffSquareSum。
- 记
解出
y和xy^2 - x^2可转换为:(y-x)(y+x)- 代入
y - x,可得:y + x = diffSquareSum / diffSum - 联立两个等式:
y = (diffSquareSum / diffSum + diffSum) / 2x = (diffSquareSum / diffSum - diffSum) / 2
复杂度分析
时间复杂度:
O(n^2)- 计算
expectSquareSum需要O(n^2) - 遍历
grid计算actualSum和actualSquareSum需要O(n^2) - 计算
x和y仅需O(1)
- 计算
空间复杂度:
O(1),仅使用常数级变量存储expectSum,actualSum,所以是O(1)
思路二:数组标记法
1. 使用数组 exists 标记出现的数字
- 创建一个长度为
n^2的布尔数组exists,用于标记每个数是否出现过。 - 遍历
grid:- 如果当前数
num已经在exists数组中被标记,则说明 它是重复的数x。 - 否则,标记
exists[num - 1] = true。
- 如果当前数
2. 找到 exists 中 false 的索引
- 再次遍历
exists,找到 第一个false的位置i,说明i+1是缺失的数y。
复杂度分析
时间复杂度:
O(n^2)- 遍历
grid需要O(n^2) - 遍历
exists数组需要O(n^2) - 总体
O(n^2)
- 遍历
空间复杂度:
O(n^2),额外使用了exists数组,大小O(n^2)
代码
/**
* @param {number[][]} grid
* @return {number[]}
*/
var findMissingAndRepeatedValues = function (grid) {
const n = grid.length;
const expectSum = ((1 + n * n) * n * n) / 2; // 期望的总和
let expectSquareSum = 0; // 期望的平方和
for (let i = 1; i <= n * n; i++) {
expectSquareSum += i * i;
}
let actualSum = 0,
actualSquareSum = 0;
for (let row of grid) {
for (let num of row) {
actualSum += num;
actualSquareSum += num * num;
}
}
const diffSum = expectSum - actualSum; // y - x
const diffSquareSum = expectSquareSum - actualSquareSum; // y^2 - x^2
const missing = (diffSquareSum / diffSum + diffSum) / 2;
const repeated = (diffSquareSum / diffSum - diffSum) / 2;
return [repeated, missing];
};
/**
* @param {number[][]} grid
* @return {number[]}
*/
var findMissingAndRepeatedValues = function (grid) {
const n = grid.length;
let repeated, missing;
let exists = new Array(n * n).fill(false);
// 1. 找到重复的数字,并标记出现的数字
for (let row of grid) {
for (let num of row) {
if (exists[num - 1] == true) {
repeated = num;
}
exists[num - 1] = true;
}
}
// 2. 找到缺失的数字
for (let i = 0; i < n * n; i++) {
if (exists[i] == false) {
missing = i + 1;
break;
}
}
return [repeated, missing];
};
