题目:
一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。
题解思路:
方法一:数组排序法
1…数组已经是排序,遍历数组的元素,元素值不等于下标值,则数组中缺失的数字就是它。
函数代码:
class Solution {
public:
int missingNumber(vector<int>& nums) {
//如果数组没有排序,就排序数组,,题目中数组元素递增
//sort(nums.begin(),nums.end())
int i;
for(i=0; i<nums.size(); i++)
{
if(i != nums[i])
{
break ;
}
}
return i ;
}
};
方法二:数组求和作差法
1.在不缺失数字的情况下,求出总数sum
2.用sum减去数组中元素的值,遍历数组即可。
函数代码:
class Solution {
public:
int missingNumber(vector<int>& nums) {
int n=nums.size();
//n+1是一共元素的个数(包括0),从0到n,
int sum=(0+n)*(n+1)/2;
for(int i=0;i<n;i++)
{
sum=sum-nums[i];
}
return sum;
}
};
函数代码:
class Solution {
public:
int missingNumber(vector<int>& nums) {
int n=nums.size();
//元素0不计入数组长度,也不计入sum
//所以1到n长度为n,累加求起始元素是1不是0
int sum=(1+n)*n/2;
for(int i=0;i<n;i++)
{
sum=sum-nums[i];
}
return sum;
}
};
方法三:二分查找
1.让left=0,right=nums.size()-1,这就是取闭区间(while(left<=right))
2.让mid=(left+right)/2,判断nums[mid]是否相等于下标mid,如果相等,则表明前面都是有序,不缺失数字的,在右边查找,即left=mid+1;如果不等,在左边查找,即right=mid-1
3.当不满足循环判断条件时(left<=right)时,退出循环,返回left
函数代码:
class Solution {
public:
int missingNumber(vector<int>& nums) {
int left=0;
int right=nums.size()-1;
while(left<=right)
{
//防止数据溢出
int mid=left+(right-left)/2;
if(nums[mid]==mid)
{
left=mid+1;
}
else
{
right=mid-1;
}
}
return left;
}
};
方法:二分查找,左闭右开
1.因为left=0,right=nums.size();循环条件是while(left<right)终止条件肯定是 left = right
2.在进行划分区间时,左边left已经判断了该值,所以是mid + 1。右边是我们的哨兵元素所以是mid,mid-1就会忽略掉一个元素。因为我们是缺少某个元素,所以不可能出现nums[i] < i的情况。
3.终止条件有一个位置出现值大于我们的数组下标,比如题目的8的位置是9,这时我们的left不断右逼到指向8,再做一次判断right也指向了8循环终止,所以我们返回的left和right都可以。
函数代码:
class Solution {
public:
int missingNumber(vector<int>& nums) {
int left=0;
int right=nums.size();
while(left<right)
{
//防止数据溢出
int mid=left+(right-left)/2;
if(nums[mid]==mid)
{
left=mid+1;
}
else if(nums[mid]>mid)
{
right=mid;
}
}
return left;
}
};
方法四:hash法