缺失数字
链接:https://www.nowcoder.com/questionTerminal/9ce534c8132b4e189fd3130519420cde?toCommentId=9702903
来源:牛客网
来源:牛客网
从 0,1,2,...,n 这 n+1 个数中选择 n 个数,选择出的数字依然保持有序,找出这 n 个数中缺失的那个数,要求 O(n) 或 O(log(n)) 并尽可能小。
示例1
输入
[0,1,2,3,4,5,7]
输出
6
示例2
输入
[0,2,3]
输出
1
整理一下几种思路
1.利用异或的性质 A^A=0 A^0=A 可以对数组中的每个数字进行异或 然后与给定区间的数字进行异或 当然也可以同时进行.
public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * 找缺失数字 * @param a int整型一维数组 给定的数字串 * @return int整型 */ public int solve (int[] a) { if(a[0]!=0)return 0; int result=0; for(int i=0;i<a.length;i++){ result^=(i+1)^a[i]; } return result; } }
2.利用有序的性质 可以利用等差数列进行求和 然后减掉数组中的每一项 最终结果就是缺失的数字。
public int solve(int[] a) { int length = a.length; int sum = length * (length + 1) / 2; for (int i = 0; i < length; i++) sum -= a[i]; return sum; }
3.利用奇数加偶数等于奇数 ,奇数相加等于偶数,若出现相邻两数相加等于偶数,则说明两个数中间的数缺失了
public int solve(int[] a) { if(a[0]!=0) return 0; for (int i = 0, j = 1; i < a.length && j<a.length; i++, j++) { if ((a[i] + a[j]) % 2 == 0) { return a[i] + 1; } } return a[a.length-1]+1; }
4.暴力枚举 因为题目已经表明数组是有序的 ,所以我们只需要从前往后逐个遍历,缺少了哪个就返回哪个
public int solve(int[] a) { int length = a.length; for (int i = 0; i < length; i++) { if (a[i] != i) return i; } return length; }
5.二分法 一般的二分法查找,找到之后会直接返回,这里使用二分法主要是在不断的缩小区间,直到找到为止
public int solve(int[] a) { int start = 0; int end = a.length - 1; while (start < end) { int mid = (start + end) / 2; if (a[mid] == mid) { //如果nums[mid] == mid也就是说当前元素的 //下标等于他自己,比如数组[0,1,2,3,4,5]每 //个元素的下标都等于他自己,说明[start,mid] //没有缺少任何数字,那么缺少的肯定是在[mid+1,end] start = mid + 1; } else { //如果当前元素的下标不等于他自己,比如[0,1,2,4]中 //nums[3]==4,说明说明缺少的数字就在这个区间内 end = mid; } } //如果类似于[0,1,2,3]这种start指向了数组的最后一个,我们让他加1 return start == a[start] ? start + 1 : start; }
本文来自博客园,作者:guoyuxin3,转载请注明原文链接:https://www.cnblogs.com/guoyuxin3/p/15121078.html

浙公网安备 33010602011771号