剑指offer--缺失的数字
Posted 雨轩(小宇)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer--缺失的数字相关的知识,希望对你有一定的参考价值。
1、消失的数字
数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?
示例:
输入:[9,6,4,2,3,5,7,0,1]
输出:8
思路一:
异或,设置一个变量num,先将索引 0 - numsSize 与 num 异或,在将nums[ i ] 与 num 异或,最后在循环外,在将 num 与 numsSize 进行异或,num就是缺失的数字。
int missingNumber(int* nums, int numsSize){
//方法一:异或
int i = 0;
int num = 0;
for(i=0;i<numsSize;i++)
{
num ^= i;
num ^= nums[i];
}
num ^= numsSize;
return num;
}
思路二:
等差数列求和,求出 0 - numsSize 的总和,在减数组的总和,既为缺失的数字。
int missingNumber(int* nums, int numsSize){
int i=0;
int num=0;
for(i=0;i<numsSize;i++)
{
num+=nums[i];
}
num=(numsSize*(numsSize+1))/2-num;
return num;
}
2、消失的两个数字
给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?
示例 1:
输入: [2,3]
输出: [1,4]
思路一:
先将变量num 与 索引异或,由于缺失两个数字,所以与的时候,是与 1 - numsSize+2,这里得到1-N的与结果,num 在&数组中的值,num就是缺失的两个数字的异或。
接下来,用一个数 x 来表示 num & -num,求下次&偶数,还是&奇数,再用一个变量first用来装偶数或者奇数的异或结果,在将first 与 数组中的值,first就是其中一个缺失的数,first & num 就是第二个缺失的数。
int* missingTwo(int* nums, int numsSize, int* returnSize){
int num = 0;
int i = 0;
static int ans[2];//用来装缺失的数
memset(ans,0,8);//设置数组值为0
for(i = 1; i <= numsSize +2 ; i++) //将索引全部异或
num ^= i;
for(i = 0; i < numsSize; i++)//将数组值异或
num ^= nums[i];
int first = 0;
int x = num & -num;//求出下面的与,是与偶数,还是奇数
for(i = 1; i <= numsSize +2 ; i++)
{
if(x & i)
first ^= i;//异或,x=1,只有1和3可以进入,得到这两个的异或值,first=010;
}
for(i = 0; i < numsSize; i++)
{
if(x & nums[i])
first ^= nums[i];//异或求出其中一个缺失的数,011&010=001,求出第一个缺失的数为1
}
ans[1] = first;
ans[0] = first ^ num;
*returnSize=2;
return ans;
}
思路二:
求和,先求出索引1-N的总和,在求出数组值的总和,利用总的数减去已有的数,剩下的是缺失的两个数字的总和。
在利用缺失的两个数字的大小关系,求出limits,在利用nums[ i ] <= limits求出其中小于limits的总和,在利用关系式子 limits * (limits + 1) / 2 减去小于limits的总和,即为其中缺失的一个数字,在利用两数之和求出另外一个缺失的数
int* missingTwo(int* nums, int numsSize, int* returnSize){
//方法一:求和,先求出1-N的和,在利用缺失的数字的大小关系求出
int sum = 0;
int n = numsSize + 2;
n = n*(n + 1)/2;
for(int i = 0;i < numsSize; i++)
sum += nums[i];
int sumTwo = n - sum;//缺失的两个数字总和
int limits = sumTwo / 2;//因为缺失的两个数字有大小关系,limits用来限制
sum = 0;
for(int i = 0;i < numsSize; i++)
{
if(nums[i] <= limits)
sum += nums[i];//求出其中小于limits的数字总和
}
int one = limits * (limits + 1) / 2 - sum;//求出其中一个缺失的数字
int two = sumTwo - one;
static int arr[2];
memset(arr,0,8);
arr[1] = one;
arr[0] = two;
*returnSize = 2;
return arr;
制作不易,点个赞!!!
以上是关于剑指offer--缺失的数字的主要内容,如果未能解决你的问题,请参考以下文章
剑指Offer面试题53 - II. 0~n-1中缺失的数字