【剑指Offer1】0~n-1中缺失的数字

题目:

一个长度为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;
    }
}

初步看下来应该是左标+中值的偏移量来解决可能存在的下标越界,后面再仔细地学一下

上一篇:689. 三个无重叠子数组的最大和


下一篇:C++学习笔记容器篇2(deque)