剑指 Offer 53 - II. 0~n-1中缺失的数字
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
1、题目
一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。
实例1:
输入: [0, 1 , 3]
输出: 2
实例2:
输入: [0, 1, 2, 3, 4, 5, 6, 7, 9]
输出: 8
提示:
1 <= 数组长度 <= 1000
2、思路
方法一:二分查找
- 基于二分法的思想,先找到中间的位置
nums[M] == M表示当前元素的下标等于他自己,举个例子,[0, 1, 2, 3, 4, 5] 每个元素的下标与元素的值相等,说明[start,mid]区间没有缺少任何数字- 所以我们可以肯定缺少的在
[mid+1,end]区间中
方法二:求和
我们先来普及一下等差数列的求和公式
第n项 = 首项 + (项数-1) * 公差长度为length的数组最后一项为(length - 1) * 1- 求和
Sn = [ n * (a1 + an)] / 2所以该等差数列求和Sn = length * (0 + length - 1) / 2
- 如果该数组不缺少数字的话,这个数组的所有数字可以组成一个等差数列
- 只需要根据公式求和,然后再减去数组中所有的数字即可求出缺少的是哪一个数字。
- 我们可以发现题目中所给我们的数组是少一个的所以这个的求和公式就要改动为
Sn = (length + 1) * (0 + length) / 2
方法三:暴力求解
题中说了是递增排序数组,只需要从前往后逐个遍历,少了哪个就返回哪个
3、代码
第一次commit AC
class Solution {
public int missingNumber(int[] nums) {
int L = 0;
int R = nums.length - 1;
while(L <= R){
int M = (L + R) >> 1;
if(nums[M] == M) L = M + 1;
else R = M - 1;
}
return L;
}
}
时间复杂度: O(logn) 空间复杂度:O(1)
第二次commit AC
class Solution {
public int missingNumber(int[] nums) {
int length = nums.length;
int sum = (length + 1) * (0 + length) / 2;
for (int i = 0; i < length; i++)
sum -= nums[i];
return sum;
}
}
- 时间复杂度:O(n)
- 空间复杂度:O(1)
第三次commit AC
class Solution {
public int missingNumber(int[] nums) {
int length = nums.length;
for (int i = 0; i < length; i++) {
if (nums[i] != i)
return i;
}
return length;
}
}
- 时间复杂度:O(n)
- 空间复杂度:O(1)
4、总结
该题目的使用二分查找的应用实例,首先要对二分法有所了解。
二分法模板:
public static int binarysearch(int arr[], int L, int R, int target){
int count = 0;
int M = (L + R) >> 1;
if(L > R) return -1;
if (target > arr[M]){
return binarysearch(arr, M + 1, R, target);
}else if(target < arr[M]){
return binarysearch(arr, L, M - 1, target);
}else {
return M;
}
}
❤️来自专栏《LeetCode基础算法题》欢迎订阅❤️
厂长写博客目的初衷很简单,希望大家在学习的过程中少走弯路,多学一些东西,对自己有帮助的留下你的赞赞👍或者关注➕都是对我最大的支持,你的关注和点赞给厂长每天更文的动力。
对文章其中一部分不理解,都可以评论区回复我,我们来一起讨论,共同学习,一起进步!