力扣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; 
    }


结尾

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木秀林

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值