645. Set Mismatch*

​https://leetcode.com/problems/set-mismatch/​

题目描述

The set ​​S​​​ originally contains numbers from ​​1​​​ to ​​n​​. But unfortunately, due to the data error, one of the numbers in the set got duplicated to another number in the set, which results in repetition of one number and loss of another number.

Given an array ​​nums​​ representing the data status of this set after the error. Your task is to firstly find the number occurs twice and then find the number that is missing. Return them in the form of an array.

Example 1:

Input: nums = [1,2,2,4]
Output: [2,3]

Note:
The given array size will in the range ​​​[2, 10000]​​​.
The given array’s numbers won’t have any order.

解题思路

感觉这题就是 ​​442. **Find All Duplicates in an Array​​​ 以及 ​​448. *Find All Numbers Disappeared in an Array​​​ 的综合体. 首先通过 “元素值作为索引” 的方法求出重复值, 比如访问 ​​nums[i]​​​ 时, 将 ​​nums[std::abs(nums[i]) - 1]​​​ 设置为负值, 表示该元素被访问了. 如果该元素再次被访问到, 说明 ​​std::abs(nums[i])​​ 重复了两次. 这里的思路描述简单看看就行, 直接看代码更好理解, 或者了解了上面两题的解法就知道套路了. 而要求出那个被替换的值, 只要求出当前数组中负值所对应的索引即可.

C++ 实现 1

class Solution {
public:
vector<int> findErrorNums(vector<int>& nums) {
vector<int> res;
for (int i = 0; i < nums.size(); ++i) {
int index = std::abs(nums[i]) - 1;
if (nums[index] > 0) nums[index] *= -1;
else res.push_back(index + 1);
}
for (int i = 0; i < nums.size(); ++i)
if (nums[i] > 0) res.push_back(i + 1);
return res;
}
};

C++ 实现 2

通过减法来求被替换的那个元素.

class Solution {
public:
vector<int> findErrorNums(vector<int>& nums) {
int n = nums.size();
int a = std::accumulate(nums.begin(), nums.end(), 0);
vector<int> res;
for (int i = 0; i < nums.size(); ++i) {
if (nums[abs(nums[i]) - 1] > 0)
nums[abs(nums[i]) - 1] = -nums[abs(nums[i]) - 1];
else {
res = {abs(nums[i])};
break;
}
}
if (res.empty()) // 说明没有找到重复元素.
return res;
int num = (n + 1) * n / 2 - (a - res.back());
res.push_back(num);
return res;
}
};