Search for a Range

Search for a Range

问题:

Given a sorted array of integers, find the starting and ending position of a given target value.

Your algorithm's runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

思路:

  递归二分查找问题

我的代码:

public class Solution {

    public int[] searchRange(int[] A, int target) {

        int[] rst = {-1,-1};

        if(A == null || A.length == 0) return rst;

        int left = 0;

        int right = A.length - 1;

        return helper(A, target, left, right);

    }

    public int[] helper(int[] A, int target, int left, int right)

    {

        int[] rst = {-1,-1};

        if(left > right) return rst;

        if(left == right)

        {

            if(target == A[left])

            {

                rst[0] = left;

                rst[1] = left;

                return rst;

            }

            return rst;

        }

        int mid = (left + right)/2;

        if(A[mid] == target)

        {

            rst[0] = mid;

            rst[1] = mid;

            int[] leftRange = helper(A, target, left, mid - 1);

            int[] rightRange = helper(A, target, mid + 1, right);

            return mergeRange(leftRange, rightRange, rst);

        }

        else if(A[mid] > target)

            return helper(A, target, left, mid - 1);

        else

            return helper(A, target, mid + 1, right);

        

    }

    public int[] mergeRange(int[] left, int[]right, int[] mid)

    {

        int[] rst = new int[2];

        int min = Integer.MAX_VALUE;

        int max = Integer.MIN_VALUE;

        for(int num: left)

        {

            if(num >= 0)

            {

                min = Math.min(min, num);

                max = Math.max(max, num);

            }

        }

        for(int num: right)

        {

            if(num >= 0)

            {

                min = Math.min(min, num);

                max = Math.max(max, num);

            }

        }

        for(int num: mid)

        {

            if(num >= 0)

            {

                min = Math.min(min, num);

                max = Math.max(max, num);

            }

        }

        rst[0] = min;

        rst[1] = max;

        return rst;

    }

    

}
View Code

他人代码:

public class Solution {

    public int[] searchRange(int[] A, int target) {

        int start, end, mid;

        int[] bound = new int[2]; 

        

        // search for left bound

        start = 0; 

        end = A.length - 1;

        while (start + 1 < end) {

            mid = start + (end - start) / 2;

            if (A[mid] == target) {

                end = mid;

            } else if (A[mid] < target) {

                start = mid;

            } else {

                end = mid;

            }

        }

        if (A[start] == target) {

            bound[0] = start;

        } else if (A[end] == target) {

            bound[0] = end;

        } else {

            bound[0] = bound[1] = -1;

            return bound;

        }

        

        // search for right bound

        start = 0;

        end = A.length - 1;

        while (start + 1 < end) {

            mid = start + (end - start) / 2;

            if (A[mid] == target) {

                start = mid;

            } else if (A[mid] < target) {

                start = mid;

            } else {

                end = mid;

            }

        }

        if (A[end] == target) {

            bound[1] = end;

        } else if (A[start] == target) {

            bound[1] = start;

        } else {

            bound[0] = bound[1] = -1;

            return bound;

        }

        

        return bound;

    }

}
View Code

学习之处:

  • 自己的代码虽然AC了,但是判断太多了,一点也不简洁,这为以后的调试,改代码带来了痛苦,而且代码越多越容易出bug啊
  • 看看别人的代码,被人代码的模板之前也整理过,但是就没想到用呢,首先left + 1 <right 这种判断的存在是因为 之后的二分存在 left = mid or right = mid 而不是left = mid - 1 right = mid + 1 如果不是Left + 1 < right 则存在死循环
  • 对于不知道左边还是右边的:首先考虑可不可以排除一边,如通过left mid right值三者之间的大小关系,如果不能排除,更加普世的作用是使用递归分别dfsleft dfsright进行结合,其实也可以在循环里面做了,方法是首先判断左边,然后判断右边,代码就如同上面别人的代码一样,真实巧妙!

 

你可能感兴趣的:(search)