LeetCode——面试题17.04 消失的数字

题目

数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?

思路

先不要考虑在O(n)时间内完成,怎么解决这道题,直观的想法,先排序,再遍历一遍,当 i!= nums[i] 的时候,就break。那么,如果万一刚刚好缺失的是最后一个数呢,即缺失n。

这个也是没问题的,因为如果 i != nums[i] 这个条件没有成立,最后的话,i是等于 n的,这个时候,我们也直接输出即可。

代码

import java.util.Arrays;

class Solution {
    public int missingNumber(int[] nums) {
        //排序
        Arrays.sort(nums);
        int i=0;
        for (;i<nums.length;++i)
            if (i!=nums[i])
                break;
        return  i;
    }
}

结果

在这里插入图片描述

改进思路

既然我们排好序了,再这样一个一个遍历,就很浪费排序这个过程了,可以利用二分法来找出结果。

改进代码

import java.util.Arrays;

class Solution {
    public int missingNumber(int[] nums) {
        //排序
        Arrays.sort(nums);
        int left=0;
        //因为搜索到最后,可能是n缺失,所以,这里需要将right扩大到n
        int right=nums.length-1;
        int middle=0;
        while (left<right)
        {
            middle=left+(right-left)/2;
            if (middle==nums[middle])
                left=middle+1;
            else
                right=middle-1;
        }
        int a=middle-1;
        if (a<0)
            a=0;
        int b=middle+1;
        if (b>nums.length-1)
            b=nums.length-1;
        int i=a;
        for (;i<=b;++i)
        {
            if (nums[i]!=i)
             break;
        }
        return i;
    }
}

结果

在这里插入图片描述
可能是测试的例子不够多,所以,二分搜索好像并没有快多少。

再改进思路

因为我们知道,两个相同的数,进行异或,结果为0,且异或是没有顺序的。因为题目说是从0-n中有一个数字没有,我们先拿那个数,异或一遍0-n,再去异或数组,就能找出那个数。

再改进代码

class Solution {
    public int missingNumber(int[] nums) {
        int length=nums.length;
        int result=0;
        for (int i=0;i<=length;++i)
            result^=i;
        
        for (int i=0;i<length;++i)
            result^=nums[i];
        return result;
    }
}

结果

在这里插入图片描述
虽然达到了双百了,但是其实,上面那个代码还可以再精简一下,因为我们观察两个for循环,循环的范围就缺了个 nums.length(),,所以,最终代码还可以这样子修改。

最终最精简的代码

class Solution {
    public int missingNumber(int[] nums) {
        int length=nums.length;
        int result=0;
        for (int i=0;i<length;++i)
        {
            result^=i;
            result^=nums[i];
        }
        result^=length;
        return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值