zoukankan      html  css  js  c++  java
  • leetcode二分查找相关

    33/81搜索旋转排序数组

    假设按照升序排序的数组在预先未知的某个点上进行了旋转。

    ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

    思路:

    • 设置左右指针开始进入二分循环
    • 判断中间的数是否为target,否则通过比较nums[mid] < nums[right]确定是右边有序还是左边有序,从而通过有序的那部分判断target的是否属于该部分,并以此调整左右指针。

    注意包含边界与target的比较,如nums[left] <= target

    // len = 0情况
    if (nums.length == 0) return -1;
    
    // 左右指针
    int left = 0, right = nums.length - 1;
    
    // 二分循环
    while (right >= left){
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) return mid;
        else if (nums[mid] < nums[right]){
            if (nums[mid] < target && nums[right] >= target) left = mid + 1;
            else right = mid - 1;
        }
        else {
            if (nums[left] <= target && nums[mid] > target) right = mid - 1;
            else left = mid + 1;
        }
        // 81 中可以有重复值,就会出现来面两种情况,[3 1 1] 和 [1 1 3 1],中间值等于最右值,3既可以在左边又可以在右边
        // 要添加nums[mid] == nums[right]的处理
        // else right--;
    }
    
    // 出了循环,就是没有找到
    return -1;
    

    34在排序数组中查找元素的第一个和最后一个位置

    在有重复值,且需要返回重复值中的第一个或最后一个时,用下面的二分搜索

    while (lo < hi){
        int mid = 1 + lo + (hi - lo) / 2; // 找最后一个时用,+1为了让mid能进一,找第一个不用加
        if (nums[mid] > target){ // 找第一个时,这里的逻辑相反
            hi = mid - 1;
        } else {
            lo = mid;
        }
    }
    

    35搜索插入位置

    二分搜索,有就返回index,没有就返回left(二分结束后落在第一个比target大的数的位置上)

    74搜索二维矩阵

    只是二分搜索的二维版本,最大的不同就是除以列数获取层,对列数取模获取列,即matrix[mid / colsNum][mid % colsNum]

    if (matrix.length == 0 || matrix[0].length == 0) return false;
    
    int rowsNum = matrix.length, colsNum = matrix[0].length;
    
    if (matrix[0][0] > target || matrix[rowsNum - 1][colsNum - 1] < target) return false;
    
    int low = 0, high = rowsNum * colsNum - 1;
    
    while (low <= high) {
        int mid = low + (high - low) / 2;
        if (matrix[mid / colsNum][mid % colsNum] < target) low = mid + 1;
        else if (matrix[mid / colsNum][mid % colsNum] > target) high = mid - 1;
        else return true;
    
    }
    return false;
    

    300最长上升子序列,354俄罗斯套娃信封问题

    354需要w和h都大于才能装下。
    输入: envelopes = [[5,4],[6,4],[6,7],[2,3]]
    输出: 3 
    解释: 最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。
    

    排序规则,w从小到大,w相等时,h从大到小。原因是,w相等时先让h大的加到list中,从而限制后续再有w相同的信封加入进来扩大list.size(w只有大于才能装下小的)。即便h可能太大了,但后续的信封可以把它替换掉,只要它大于倒数第二个,此时增加信封的门槛又降低了。

    List<Integer> list = new ArrayList<>();
    // 300省略排序,直接遍历
    Arrays.sort(envelopes, (arr1, arr2) -> {
        if (arr1[0] != arr2[0]) {
            return arr1[0] - arr2[0];
        } else {
            return arr2[1] - arr1[1];
        }
    });
    
    for (int[] envelope : envelopes) {
        int left = 0, right = list.size() - 1, t = envelope[1];
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (list.get(mid) < t) left = mid + 1;
            else if (list.get(mid) > t) right = mid - 1;
            else {
                left = mid;
                break;
            }
        }
        if (left >= list.size()) list.add(t);
        else list.set(left, t);
    }
    return list.size();
    
  • 相关阅读:
    URAL 1993 This cheeseburger you don't need
    python获取教务管理系统的MM照片
    ZOJ 3175 Number of Containers 分块
    ZOJ 3435 Ideal Puzzle Bobble 莫比乌斯反演
    整理各种线性筛法
    SPOJ 7001 Visible Lattice Points 莫比乌斯反演
    UVA 11997 K Smallest Sums
    HDU 4768 Flyer 二分
    HDU 4135 Co-prime 容斥
    POJ 3468 A Simple Problem with Integers 线段树
  • 原文地址:https://www.cnblogs.com/code2one/p/10100167.html
Copyright © 2011-2022 走看看