力扣-645. 错误的集合

1.题目介绍

题目地址(645. 错误的集合 - 力扣(LeetCode))

https://leetcode.cn/problems/set-mismatch/

题目描述

集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复

给定一个数组 nums 代表了集合 S 发生错误后的结果。

请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。

 

示例 1:

输入:nums = [1,2,2,4]
输出:[2,3]

示例 2:

输入:nums = [1,1]
输出:[1,2]

 

提示:

  • 2 <= nums.length <= 104
  • 1 <= nums[i] <= 104

2. 题解

2.1 set集合求重复值 + 数学方法求丢失数

思路

只要找到了重复的数字rep_num, 1->n总和为sum(等差数列公式计算), 数组总和为Array_sum(在第一个循环中即可计算), 丢失的数字abandon_num , 有 abandon_num - rep_num= sum - totalSum ; 就可以计算出来了

代码

  • 语言支持:C++

C++ Code:


class Solution {
public:
    vector<int> findErrorNums(vector<int>& nums) {
        long long totalSum = 0;
        int rep_num, n = nums.size();
        set<int> s;
        for (int i = 0; i < n; i++){
            if(!s.count(nums[i])){
                s.emplace(nums[i]);
            }else{
                rep_num = nums[i];
            }
            totalSum += nums[i];
        }

        long long sum = (1 + n) * n / 2;
        int abandon_num = sum - totalSum + rep_num;
        vector<int> ans;
        ans.push_back(rep_num);
        ans.push_back(abandon_num);
        return ans;
    }
};

复杂度分析

令 n 为数组长度。

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

2.2 unordered_map哈希表

思路

unordered_map记录出现次数, 若为0则是丢失的数字, 若为2则是重复的数字

代码

class Solution {
public:
    vector<int> findErrorNums(vector<int>& nums) {
        vector<int> errorNums(2);
        int n = nums.size();
        unordered_map<int, int> mp;
        for (auto& num : nums) {
            mp[num]++;
        }
        for (int i = 1; i <= n; i++) {
            int count = mp[i];
            if (count == 2) {
                errorNums[0] = i;
            } else if (count == 0) {
                errorNums[1] = i;
            }
        }
        return errorNums;
    }
};

复杂度分析

令 n 为数组长度。

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

2.3 位运算

思路

注意点:
1.x xor x = 0, x xor 0 = x;
2.我们后续再引入1-n 这n个数为的是将无关数排除出去, 只留下出现了三次的 rep_num 和 出现了一次的 abandon_num
3.求最低位的思路来自我们想要将这两个数分开, 必须有一个能区分这两个数的标志, 便利用 二进制负数的性质获得了二者不同的最低位.
4.如果xor = [0 1 0 0 1 0 0 0]
则 (- xor) = [1 0 1 1 1 0 0 0]
那么 lowbit = xor & (-xor) = [0 0 0 0 1 0 0 0],lowbit 就是 x 和 y 的二进制表示中的最低不同位。

代码

class Solution {
public:
    vector<int> findErrorNums(vector<int>& nums) {
        int n = nums.size();
        int xorSum = 0;
        for(int i = 0; i < n; i++){
            xorSum ^= nums[i]; // 先加入数组的所有数
        }
        // 加入1-n这n个数(为了使无关数出现两次,异或为0)
        for(int i = 1; i <= n; i++){
            xorSum ^= i; // 再加入1-n这n个数, 由于除了丢失的数和重复的数, 在这次计算后都是异或了两次, x ^ x = 0, 所以 相当于 xor = rep_num ^ rep_num ^ rep_num ^ abandon_num = rep_num ^ abandon_num
        }

        int low_bit = xorSum & (-xorSum); // 由于 -xor 等于所有位取反,再加一, 这里就可以获得两个数不同的最低位,方便后面分组将其区分开来
        
        // 求得最低位, 对2n个数进行处理
        int num1 = 0, num2 = 0;
        // 先处理2n个数中 数组的数
        for(int num : nums){
            if(num & low_bit){
                num1 ^= num;
            } else{
                num2 ^= num;
            }
        }
        // 处理2n个数中的 1-n
        for(int i = 1; i <= n; i++){
            if(i & low_bit){
                num1 ^= i;
            } else{
                num2 ^= i;
            }
        }

        // 判断重复数,返回数组
        for(int num: nums){
            if(num == num1){
                return vector<int>{num1, num2};
            }
        }
        return vector<int>{num2, num1};
    }
};

复杂度分析

令 n 为数组长度。

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)
posted @   DawnTraveler  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示