LeetCode 34. Search for a Range

一个升序数组,找出与target相等的元素的位置,会有两个。

For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].

如果找不到就返回[-1, -1].时间复杂度要求O(logn)


class Solution {
    public int[] searchRange(int[] nums, int target) {
        int start = 0, end = nums.length - 1, idx = -1;
        int mid = (start + end) / 2;
        int result[] = new int[2];
        while (start <= end) {
            if (nums[mid] < target) start = mid + 1;
            else end = mid - 1;
            if(nums[mid] == target) idx = mid;
        }
        result[0] = idx;
        start = idx;

        end = nums.length - 1;
        idx = -1;
        while (start <= end){
            mid = (start + end + 1) / 2; //让mid向右边界靠近Make mid biased to the right
            if (nums[mid] > target) end = mid - 1;  
            else start= mid; 
            if(nums[mid] == target) idx = mid;
        }
        result[1] = idx;
        return result; 
    }
}


这个还超复杂度我也是醉了...这第二次二分的时候start从第一个target的index处开始还超,不懂啊!只能看别人的思路了,java的全都是调用函数的,看了这个感觉比较好理解:


public class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] result = new int[2];
        result[0] = findFirst(nums, target);
        result[1] = findLast(nums, target);
        return result;
    }


    private int findFirst(int[] nums, int target){
        int idx = -1;
        int start = 0;
        int end = nums.length - 1;
        while(start <= end){
            int mid = (start + end) / 2;
            if(nums[mid] >= target){//向左边界靠近
                end = mid - 1;
            }else{
                start = mid + 1;
            }
            if(nums[mid] == target) idx = mid;
        }
        return idx;
    }


    private int findLast(int[] nums, int target){
        int idx = -1;
        int start = 0;
        int end = nums.length - 1;
        while(start <= end){
            int mid = (start + end) / 2;
            if(nums[mid] <= target){//向右边界靠近
                start = mid + 1;
            }else{
                end = mid - 1;
            }
            if(nums[mid] == target) idx = mid;
        }
        return idx;
    }
}


这个思路比较复杂一点,但用的很巧妙
class Solution {
    public int[] searchRange(int[] A, int target) {
    int start = Solution.firstGreaterEqual(A, target);
    if (start == A.length || A[start] != target) return new int[]{-1, -1};  //如果不要A.length == start会超出数组范围,因为如果target大于数组里最大数则start会到A.length的地方从而超出了A[]的范围。后一个表示如果target小于最小数时的情况
    return new int[]{start, Solution.firstGreaterEqual(A, target + 1) - 1};
    }
    //find the first number that is greater than or equal to target.
    //could return A.length if target is greater than A[A.length-1].
    //actually this is the same as lower_bound in C++ STL.
        //如果target在数组中,返回的一定是target的第一个值,因为如果是第二个不会结束循环,而会将high赋给mid(此时start一定小于mid,因为前面至少还有一个target)所以会再次循环从而找到第一个target(其实就是因为A[mid] < target这里没有=号,说明是向左边界靠近的)
    private static int firstGreaterEqual(int[] A, int target) {
        int low = 0, high = A.length;
        while (low < high) {
            int mid = (low + high) / 2;
            //low <= mid < high
            if (A[mid] < target) low = mid + 1; 
            else high = mid;
            //should not be mid-1 when A[mid]==target.
            //could be mid even if A[mid]>target because mid<high.    
        }
        return low;
    }
}


总结:这两种方法都没有在第二次的时候从第一个target的索引开始,其实是比较复杂的,不如C++

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值