5.20学习笔记

First Part

今天花了很多时间在鼻塞和Android 开发上,leetcode希望现在能马上补上两道来弥补罪恶。

Leetcode

Find First and Last Position of Element in Sorted Array

Given an array of integers nums sorted in ascending order, 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].

题目意为给定一个向上的递增数组(允许有重复元素),找到target value,并输出target value的最小下标和最大下标。
如果target 不在数组里,则返回 [-1, -1]
代码如下:

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] output = {-1, -1};
        if (nums.length == 0) return output;
        int left = 0, right = nums.length - 1;
        while (left <= right){
            int pivot = (left + right) / 2;
            if(nums[pivot] == target){
                output = extension(nums, pivot, target);
                return output;
            }
            if (target < nums[pivot])
                right = pivot - 1;
            else
                left = pivot + 1;
        }
        return output;
    }
    private int[] extension(int[] nums, int pivot, int target){
        int[] output = new int[2];
        int h = pivot;
        int l = pivot;
        while(h <= nums.length - 1 &&nums[h] == target){
            h ++;
        }
        while(l >= 0 && nums[l] == target){
            l--;
        }
        output[0] = l + 1;
        output[1] = h - 1;
        return output;
    }
}

这里我写了两个函数,第一个就是主函数,searchRange,第二个辅助函数extension,就是在找到target value的下标后,向上和向下进行拓展,找到最小下标和最大下标。
searchRange用了binary search。就如同正常的binary search一般,只不过找到条件在返回前,先实现extension 方法。

Tag:binary search。

接下来看leetcode 官方给的解法:

class Solution {
    // returns leftmost (or rightmost) index at which `target` should be
    // inserted in sorted array `nums` via binary search.
    private int extremeInsertionIndex(int[] nums, int target, boolean left) {
        int lo = 0;
        int hi = nums.length;

        while (lo < hi) {
            int mid = (lo + hi) / 2;
            if (nums[mid] > target || (left && target == nums[mid])) {
                hi = mid;
            }
            else {
                lo = mid+1;
            }
        }

        return lo;
    }

    public int[] searchRange(int[] nums, int target) {
        int[] targetRange = {-1, -1};

        int leftIdx = extremeInsertionIndex(nums, target, true);

        // assert that `leftIdx` is within the array bounds and that `target`
        // is actually in `nums`.
        if (leftIdx == nums.length || nums[leftIdx] != target) {
            return targetRange;
        }

        targetRange[0] = leftIdx;
        targetRange[1] = extremeInsertionIndex(nums, target, false)-1;

        return targetRange;
    }
}

先初始化targetRange, 用extremeInsertionIndex方法获得left index, 然后加条件判断,left index是否在nums数组的bounds中。
重点来看extremeInsertionIndex方法,首先传入的值标准来看,就是nums和target,它这里还有一个布尔变量left来判定寻找上界还是下界。
与一般的二分法相同,但判断条件变为

if (nums[mid] > target || (left && target == nums[mid])) 

这里有一个很tricky的技巧,在于 left && target == nums[mid]
也就是说在寻找下界的时候,判断的是nums[mid] >=target都成立,但在寻找上界的时候,nums[mid]就必须大于target。

Search insert position

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

You may assume no duplicates in the array.

题目意为给定一个排序好的数组,和一个target value,返回target value的下标,如果没找到的话,返回一个它应该被插入的位置。 该数组中没有重复元素。

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0;
        int right = nums.length - 1;
        while (left <= right){
            int pivot = (left + right) / 2;
            if(nums[pivot] == target) 
                return pivot;
            if (target > nums[pivot])
                left = pivot + 1;
            else
                right = pivot - 1;
        }
        return left;
    }
}

利用binary search,如果找到的话,就返回下标。如果没找到的话,因为跳出循环的条件是left > right。且在最后一个判定条件一定为target > nums[pivot],所以在pivot + 1也就是再大一个值的地方,适合插入target value。

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 深蓝海洋 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读