题目
数组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;
}
}