题目:
一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。
思路:
首先就是遍历:
class Solution { public int missingNumber(int[] nums) { int res = -1; if (nums.length == 1) { return nums[0]==0?1:0; } for (int i = 0; i < nums.length; i++) { if (nums[i] != i) { res = i; break; } } return res==-1?nums.length:res; } }
注意点:如果遍历结束res仍为初始值-1,则认为没有找到位置错误的元素,缺失元素为nums.length
思考:
看到评论说有序数组都要考虑二分,提高效率,试着写了一个,代码如下:
class Solution { public int missingNumber(int[] nums) { int beg = 0; int end = nums.length-1; while (beg < end - 1) { int mid = (beg + end) >> 1; if (nums[mid] != mid) { end = mid; } else { beg = mid; } } if (nums[beg] != beg) { return beg; } else if (nums[end] != end) { return end; } else { return end + 1; } } }
因为二分结束的下标问题一致搞错,提交了几次都有问题,最后想了个办法特殊处理,就是遍历到只剩2个元素时退出,分别判断左右是否错位,如果都正确则返回右边下标+1(即数组缺少最大值)
看了评论的二分,果然有办法把这些特殊情况也包含进来:
class Solution { public int missingNumber(int[] nums) { int left = 0; int right = nums.length - 1; while (left <= right) { int mid = left + (right - left) / 2; // 数组下标是从0开始连续的向n增长,若相等范围区域继续向右靠 if (nums[mid] == mid) { left = mid + 1; } // 不相范围区域向左靠拢 else { right = mid - 1; } } return left; } }
初步看下来应该是左标+中值的偏移量来解决可能存在的下标越界,后面再仔细地学一下