力扣leetcode 面试题 17.19. 消失的两个数字

CSDN话题挑战赛第2期
参赛话题:算法题解

在这里插入图片描述

题目链接与描述

https://leetcode.cn/problems/missing-two-lcci/

关键词:求和 原地hash 异或

第一反应又是暴力求解,排序后取两个,但是时间不满足

方法一:求和

  1. 利用等差公式可以得到全部1-n的和
  2. 遍历nums可以得到缺失2位数后的和
  3. 两数相减,就是我们求的两数之和sum
  4. sum/2,可以得到两数中间值,一个在左,一个在右
  5. 同理,我们可以根据等差公式得到1-sum/2的和
  6. 也可以求到1-sum/2 数组中的和
  7. 两数相减就得到了左边的数字,sum-左边数字就是右边数字了

运行截图

在这里插入图片描述

代码


    public int[] missingTwo(int[] nums) {
    
    
        int n = nums.length + 2;
        long sum = 0;
        for (int x: nums) sum += x;

        long sumTwo = n * (n + 1) / 2 - sum;
        long limits = sumTwo / 2;
        sum = 0;
        for (int x: nums)
            if (x <= limits) sum += x; // 两个数不相同那么一个大于,一个小于
        long one = limits * (limits + 1) / 2 - sum;
        return new int[]{
    
    (int)one, (int)(sumTwo - one)}; 
    }

方法二:异或

原理与求和类似,异或(相同为0,不同为1)是使用了:

  • a xor a = 0
  • 异或遵循算数组合(1-n的异或 1-n缺失两位的异或=两位缺失的异或):
    • a xor b xor b = a
    • a xor b = c 并且 a xor b xor a=c xor a,即 b = c xor a
  • 然后最后得到两个缺失的异或,通过lowbit,必然是一个为1一个为0(不然就两个数相等了),再前面的两个全员异或一遍,通过分界,能够得到其中一个,再与前面的异或结果 就得到另一个

运行截图

在这里插入图片描述

代码


public int[] missingTwo(int[] nums) {
    
    
        int n = nums.length + 2;
        int xor = 0;
        for (int v : nums) {
    
    
            xor ^= v;
        }
        for (int i = 1; i <= n; ++i) {
    
    
            xor ^= i;
        }
        int diff = xor & (-xor);
        int a = 0;
        for (int v : nums) {
    
    
            if ((v & diff) != 0) {
    
    
                a ^= v;
            }
        }
        for (int i = 1; i <= n; ++i) {
    
    
            if ((i & diff) != 0) {
    
    
                a ^= i;
            }
        } 
        return new int[] {
    
    a, xor ^ a}; 
    }

方法三:原地hash

通过数组下标和值映射,不再一个的就交换,最终遍历一遍就得到了缺失的数,这个和前面刷到的一道题解法一致

运行截图

在这里插入图片描述

代码

    public int[] missingTwo(int[] nums) {
    
    
      int[] hash = new int[nums.length+2];
        for(int i = 0 ; i < nums.length;i++){
    
    
            hash[nums[i]-1]++;
        } 
        //hash记录
        int[] re = new int[2];
        int i = 0;
        for(int j = 0 ; j < hash.length;j++){
    
     
        	//把0排除在外
            if(hash[j] == 0){
    
    
                re[i++] = j+1;
            }
        }
        return re; 
    }


结尾

发现这道题的一百有点容易啊

欢迎评论区交流,每日打卡,冲冲冲!!!

猜你喜欢

转载自blog.csdn.net/qq_35530042/article/details/127058743