zoukankan      html  css  js  c++  java
  • 二分查找、变形及应用

    [LeetCode] 35 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.
    

    测试案例

    Input: [1,3,5,6], 5
    Output: 2
    
    Input: [1,3,5,6], 2
    Output: 1
    
    Input: [1,3,5,6], 7
    Output: 4
    
    Input: [1,3,5,6], 0
    Output: 0
    

    代码如下

    class Solution {
        public int searchInsert(int[] nums, int target) {
            int start = 0, end = nums.length - 1, mid;
            while(start <= end){
                mid = (start + end) >> 1;
                if(nums[mid] == target){
                    return mid;
                }
                else if(nums[mid] > target){
                    end = mid - 1;
                }
                else{
                    start = mid + 1;
                }
            }
            return start;        
        }   
    }
    

    [LeetCode 34] 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].
    

    测试案例

    Input: nums = [5,7,7,8,8,10], target = 8
    Output: [3,4]
    
    Input: nums = [5,7,7,8,8,10], target = 6
    Output: [-1,-1]
    

    代码如下

    class Solution {
        public int[] searchRange(int[] nums, int target) {        
            int[] res = new int[2];
            if(nums.length == 0){
                res[0] = res[1] = -1;
                return res;
            }
            res[0] = find(nums, target, true);
            res[1] = find(nums, target, false);
            if(res[0] >= nums.length || nums[res[0]] != target){
                res[0] = -1;
                res[1] = -1;
            }
            return res;
        }
        int find(int[] nums, int target, boolean left){
            int mid;
            int start = 0, end = nums.length - 1;
            while(start <= end){
                mid = (start + end) >> 1;
                if(nums[mid] > target){
                    end = mid - 1;
                }
                else if(nums[mid] == target){
                    if(left){
                        end = mid - 1;
                    }
                    else{
                        start = mid + 1;
                    }
                }
                else{
                    start = mid + 1;
                }
            }
            return left ? start : end;
        }
    }
    

    [LeetCode 153] Find Minimum in Rotated Sorted Array

    题目

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
    (i.e.,  [0,1,2,4,5,6,7] might become  [4,5,6,7,0,1,2]).
    Find the minimum element.
    
    You may assume no duplicate exists in the array.
    

    测试案例

    Input: [3,4,5,1,2] 
    Output: 1
    
    Input: [4,5,6,7,0,1,2]
    Output: 0
    

    代码如下

    class Solution {
        public int findMin(int[] nums) {
            int n = nums.length, start = 0, end = n - 1, mid;
            while(start < end){
                if(nums[start] < nums[end]){
                    return nums[start];
                }
                mid = (start + end) >> 1;
                if(nums[mid] >= nums[start]){
                    start = mid + 1;
                }
                else{
                    end = mid;
                }
            }
            return nums[start];
        }
    }
    

    [LeetCode 74] Search a 2D Matrix

    题目

    Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
    - Integers in each row are sorted from left to right.
    - The first integer of each row is greater than the last integer of the previous row.
    

    测试案例

    Input:
    matrix = [
      [1,   3,  5,  7],
      [10, 11, 16, 20],
      [23, 30, 34, 50]
    ]
    target = 3
    Output: true
    
    Input:
    matrix = [
      [1,   3,  5,  7],
      [10, 11, 16, 20],
      [23, 30, 34, 50]
    ]
    target = 13
    Output: false
    

    思路

    矩阵的特点是当进行两层循环遍历,外层为行,内层为列时,矩阵中所有元素都是递增的。所以进行如下两层二分查找:

    1. 先在第一列中进行二分。找出 target 或者找出其所有的行。当二分查找的返回值为 -1时,表示矩阵中不存在 target。
    2. 在上次二分查找返回的行中再次二分。

    代码如下

    class Solution {
        public boolean searchMatrix(int[][] matrix, int target) {
            int m, n;
            if((m = matrix.length) == 0 || (n = matrix[0].length) == 0){
                return false;
            }
            //在第一列中搜索,找出 target 所在的行end。
            int start = 0, end = m - 1, mid;
            while(start <= end){
                mid = (start + end) >> 1;
                if(matrix[mid][0] == target){
                    return true;
                }
                else if(matrix[mid][0] > target){
                    end = mid - 1;
                }
                else{                
                    start = mid + 1;
                }
            }
            int pos = end;
            if(pos == -1){
                return false;
            }
            for(start = 0, end = n - 1; start <= end;){
                mid = (start + end) >> 1;
                if(matrix[pos][mid] == target){
                    return true;
                }
                else if(matrix[pos][mid] > target){
                    end = mid - 1;
                }
                else{
                    start = mid + 1;
                }
            }
            return false;
        }
    }
    

    [LeetCode 240] Search a 2D Matrix II

    题目

    Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
    
    Integers in each row are sorted in ascending from left to right.
    Integers in each column are sorted in ascending from top to bottom.
    

    测试案例

    [
      [1,   4,  7, 11, 15],
      [2,   5,  8, 12, 19],
      [3,   6,  9, 16, 22],
      [10, 13, 14, 17, 24],
      [18, 21, 23, 26, 30]
    ]
    Given target = 5, return true.
    Given target = 20, return false.
    

    思路

    1. 每次在矩阵的左边一列进行二叉查找,若查找到 target,返回 true。否则设查找结束后返回值为end。end = -1时,直接返回false。
    2. 取出子矩阵 [0 ~ end][1~ n - 1]。
    3. 重复上述过程共 n 次(因为每查找一次,矩阵列数减1)。
    4. 时间复杂度为 (O(nlgm))。当 n > m时,先在列中进行二分查找。

    代码如下

    class Solution {
        public boolean searchMatrix(int[][] matrix, int target) {
            int m, n, start, end, mid;
            //初始化 m 和 n
            if((m = matrix.length) == 0 || (n = matrix[0].length) == 0){
                reutrn false;               
            }        
            //初始化start 和 mid 
            start = 0;end = m - 1;
            //进行 n 次 二分查找
            for(int i = 0; i < n; i ++){
                start = 0;
                while(start <= end){
                    mid = (start + end) >> 1;
                    if(matrix[mid][i] == target){
                        return true;
                    }
                    else if(matrix[mid][i] < target){
                        start = mid + 1;
                    }
                    else{
                        end = mid - 1;
                    }
                }
                if(end == -1){
                    break;
                }
            }        
            reutrn false;
        }
    }
    
  • 相关阅读:
    关于二分操作的基本应用
    东北育才 d1t4 漂流
    东北育才 d1t1 优雅的序列
    从零开始的图的存储方法
    从零理解的KMP算法
    openjudge T017 黑社会团伙 (并查集)
    东北育才 day6
    poj3071 Football
    noip2015 跳石头
    noip2015 信息传递
  • 原文地址:https://www.cnblogs.com/echie/p/9592186.html
Copyright © 2011-2022 走看看