[LeetCode-268] Missing Number(找缺失的数字)

Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array.

For example,
Given nums = [0, 1, 3] return 2.

Note:
Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?

1、无序数组

【问题描述】输入的数组是一个无序数组(当缺失添加进输入时,排序后是一个等差数列,公差为1),找到缺失数,题目要求时间复杂度为n,所以想先将数组排序的想法肯定不实际,由题意,大小为n的数组里的所有数都是0 - n之间的数,无需数组,我们首先遍历一遍记录最大、最小值以及实际数组和,用最小值到最大值相加之后得到的期望数组和减去实际数组和,就是缺失的整数。

题目中有几个比较恶心的处理

  1. 当数组长度为1,数组元素为0,此时默认缺失数为1;
  2. 当数组长度为1时,数组元素不为0,此时应该返回0,说明输入内容无效
其中程序有个易错点,当期望数组和减去实际数组和可能等于0,此时存在两种情况①缺失数为0②数组第一个元素为0,缺失数为最大值+1;
代码如下:
int missingNumber(int* nums, int numsSize) 
{
	/*1.Exception handling*/
	if(!nums||numsSize<=0) {
		return 0;
	}
	/*Such as 1,should return 0*/
    if(nums[0]!=0&&numsSize==1) {
        return 0;
    }
	int i = 0;
	int MAXNUM = 0xffffffff;
	int MINNUM = 0x7fffffff;
	long long numsAddSum = 0;/*long long is to advoid overflow*/
	long long numsAddSumReal = 0;
	int nResult = 0;
	
	for(i = 0;i<numsSize;i++) {
		if(nums[i]>MAXNUM) {
			MAXNUM = nums[i];
		}
		if(nums[i]<MINNUM) {
			MINNUM = nums[i];
		}
		numsAddSum += nums[i];
	}
	i = MINNUM;
	while(i<=MAXNUM) {
		numsAddSumReal +=i;
		i++;
	}
	nResult = (int)numsAddSumReal-numsAddSumReal;
	
	/*Expect numsAddSumReal - numsAddSumReal = 0*/
	if(nResult==0&&MINNUM==0){
	    return (MAXNUM+1);
	}
	else if(nResult==0&&MINNUM!=0) {
		return 0;
	}
	
	return nResult;	
}

2、有序数组

【问题描述】输入的数组是一个有序数组,找到缺失数,题目要求时间复杂度为n,由题意,大小为n的数组里的所有数都是0 - n之间的数,作为等差数列,最大值和最小值一眼就可以看出,可以对上述方法直接进行改进;
/*有序数组*/
int missingNumber(int* nums, int numsSize) 
{
	/*1.Exception handling*/
	if(!nums||numsSize<=0) {
		return 0;
	}
	/*Such as 1,should return 0*/
    if(nums[0]!=0&&numsSize==1) {
        return 0;
    }

    int i = 0;
	int MAXNUM = nums[numsSize-1];
	int MINNUM = nums[0];
	
	long long numsAddSumExpect = 0;/*long long is to advoid overflow*/
	long long numsAddSumReal = 0;
	int nResult = 0;

	for(i = 0;i<numsSize;i++) {
		numsAddSumReal += nums[i];
	}
	i = MINNUM;
	while(i<=MAXNUM) {
		numsAddSumExpect +=i;
		i++;
	}
	
	nResult = (int)numsAddSumExpect-numsAddSumReal;
	
	/*Expect numsAddSumReal - numsAddSumReal = 0*/
	if(nResult==0&&MINNUM==0){
	    return (MAXNUM+1);
	}
	else if(nResult==0&&MINNUM!=0) {
		return 0;
	}
	
	return nResult;	
	
}

3、二分搜索法改进代码

中点的下标和中点的值相同时,说明从起始到中点没有错位,缺失数应该在数组后边。如果不相等,说明前面已经有错位,缺失数在左边。如果缺失数是最后一个的话,那整个数组都没有错位,则要返回最后一个加1。
注意:中点的值需要和中点值+起始值(偏移)。

/*二分搜索法,找缺失数*/
int missingNumber(int* nums, int numsSize) 
{
	/*1.Exception handling*/
	if(!nums||numsSize<=0) {
		return 0;
	}
	/*Such as 1,should return 0*/
    if(nums[0]!=0&&numsSize==1) {
        return 0;
    }
    else if(nums[0]==0&&numsSize==1) {
		return (0+1);
	}

	int min = 0;
	int max = numsSize-1;
	while(min<=max) {
		int mid = min+(max-min)/2;
		if((mid+nums[0])==nums[mid]) {
			min = mid+1;
		}
		else {
			max = mid-1;
		}
	}
	/*没有发生错位*/
	if(min == nums[min]&&nums[0]==0) {
		return (nums[numsSize-1]+1);
	}
	else if(min == nums[min]&&nums[0]!=0) {
		return 0;
	}
	
	return (min+nums[0]);
}


你可能感兴趣的:(LeetCode,二分查找法,缺失数)