首页 > 其他分享 >力扣-645. 错误的集合

力扣-645. 错误的集合

时间:2024-04-25 09:03:50浏览次数:22  
标签:vector nums int 复杂度 力扣 num 645 集合 rep

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)\)

标签:vector,nums,int,复杂度,力扣,num,645,集合,rep
From: https://www.cnblogs.com/trmbh12/p/18156665

相关文章

  • 力扣-697. 数组的度
    1.题目介绍题目地址(697.数组的度-力扣(LeetCode))https://leetcode.cn/problems/degree-of-an-array/题目描述给定一个非空且只包含非负数的整数数组 nums,数组的度的定义是指数组里任一元素出现频数的最大值。你的任务是在nums中找到与 nums 拥有相同大小的度的最短......
  • 力扣-396. 旋转函数
    1.题目介绍题目地址(396.旋转函数-力扣(LeetCode))https://leetcode.cn/problems/rotate-function/题目描述给定一个长度为n的整数数组 nums 。假设 arrk 是数组 nums 顺时针旋转k个位置后的数组,我们定义 nums 的旋转函数  F 为:F(k)=0*arrk[0]+1*......
  • 力扣-189. 轮转数组
    1.题目题目地址(189.轮转数组-力扣(LeetCode))https://leetcode.cn/problems/rotate-array/题目描述给定一个整数数组nums,将数组中的元素向右轮转k 个位置,其中 k 是非负数。 示例1:输入:nums=[1,2,3,4,5,6,7],k=3输出:[5,6,7,1,2,3,4]解释:向右轮转1步......
  • java lambda list集合中对象某属性重复,只取第一个对象
    可以使用Java8的流式编程和Lambda表达式来实现这个需求:List<MyObject>list=getList();//获取List集合Map<String,MyObject>map=list.stream().collect(Collectors.toMap(MyObject::getProperty,Function.identity(),(o1,o2)->o1));List<MyObject>r......
  • 力扣-414. 第三大的数
    1.题目题目地址(414.第三大的数-力扣(LeetCode))https://leetcode.cn/problems/third-maximum-number/题目描述给你一个非空数组,返回此数组中第三大的数。如果不存在,则返回数组中最大的数。 示例1:输入:[3,2,1]输出:1解释:第三大的数是1。示例2:输入:[1,2]输出:2......
  • 力扣-495. 提莫攻击
    1.题目题目地址(495.提莫攻击-力扣(LeetCode))https://leetcode.cn/problems/teemo-attacking/题目描述在《英雄联盟》的世界中,有一个叫“提莫”的英雄。他的攻击可以让敌方英雄艾希(编者注:寒冰射手)进入中毒状态。当提莫攻击艾希,艾希的中毒状态正好持续 duration秒。正......
  • Linux问题集合
    Linux问题集合1.Linux下如何定位死锁?如果你想排查你的Java程序是否死锁,则可以使用jstack工具,它是jdk自带的线程堆栈分析工具。在Linux下,我们可以使用pstack+gdb工具来定位死锁问题。pstack命令可以显示每个线程的栈跟踪信息(函数调用过程),它的使用方式也很简单,只......
  • JTCR-java.util 集合框架-17
    JDK9开始,java.util包作为java.base模块的一部分。概述集合框架的设计目标高性能。不同类型的集合使用方式相似,有很好的互操作性。容易扩展或适配集合。Iterator接口提供了访问集合中元素通用、标准化的方式。任意集合类都可以使用Iterator提供的方法访问元素。JDK......
  • 力扣-665. 非递减数列
    1.题目题目地址(665.非递减数列-力扣(LeetCode))https://leetcode.cn/problems/non-decreasing-array/题目描述给你一个长度为 n 的整数数组 nums ,请你判断在最多改变 1个元素的情况下,该数组能否变成一个非递减数列。我们是这样定义一个非递减数列的: 对于数组中任......
  • 【每周例题】力扣 C++ 分割字符串
    分割字符串题目 题目分析1.先确定用容器存储,容器的存储结构如下图所示: 2.这个题目的话,第一反应应该是用到动态规划,下面是动态规划的模板:res=[]ans=[]defbacktrack(未探索区域,res,path):if未探索区域满足结束条件:res.add(ans)#深度拷贝......