# 二分查找

  • 二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法,前提是数据结构必须先排好序,可以在数据规模的对数时间复杂度内完成查找。但是,二分查找要求线性表具有有随机访问的特点(例如数组),也要求线性表能够根据中间元素的特点推测它两侧元素的性质,以达到缩减问题规模的效果

# 1 数组

  • 二分搜索, 寻找比目标字母大的最小字母, 峰值查找,搜索二维矩阵

# 2 树

  • 二叉搜索树第k小的元素

# 1 数组实例

# 1 二分搜索

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9

输出: 4

解释: 9 出现在 nums 中并且下标为 4

class Solution {
    public int search(int[] nums, int target) {
        int lo =0, hi = nums.length-1;
        
        while(hi >= lo){
            int mid = lo+(hi-lo)/2;
            if(nums[mid] == target){
                return mid;
            }
            else if(nums[mid] > target){
                hi = mid-1;
            }
            else if(nums[mid] < target){
                lo = mid+1;
            }
        }
        return -1;
    }
}

# 2寻找峰值

峰值元素是指其值大于左右相邻值的元素。

给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。

数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞。

示例 1

输入: nums = [1,2,3,1]

输出: 2

解释: 3 是峰值元素,你的函数应该返回其索引 2。

class Solution {
    public int findPeakElement(int[] nums) {
        int lo = 0, hi = nums.length-1;
        while(hi>=lo){
            int mid = (hi+lo)/2;
            if(nums[mid]> nums[mid+1]){
                hi = mid-1;
            }else{
                lo = mid+1;
            }
        }
        return lo;
    }
}

2
    
    class Solution {
    public int findPeakElement(int[] nums) {
        int lo = 0, hi = nums.length-1;
        for(int i =0; i<hi; i++){
            if(nums[i]>nums[i+1]{
            return i
                }
        }
    }
}

# 3二维矩阵搜索

编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:

每行中的整数从左到右按升序排列。

每行的第一个整数大于前一行的最后一个整数。

示例 1:

输入:

matrix = [

[1, 3, 5, 7],

[10, 11, 16, 20],

[23, 30, 34, 50]

]

target = 3

输出: true

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        
        int m = matrix.length;
        if(m == 0)  return false;
        int n  =matrix[0].length;
        int lo = 0, hi = m*n-1;
        
        while(hi >= lo){
            int mid = lo+(hi-lo)/2;
            int r = mid/n;
            int c = mid%n;
            int part = matrix[r][c];
            if( part== target){
                return true;
            }
            else if(part < target){
                lo = mid+1;
            }else{
                hi = mid-1;
            }
        }
        return false;
        
    }
}
// 二维数组展开成一位, 二维数组的中点转换,
            // int mid = lo+(hi-lo)/2;
            // int r = mid/n;
            // int c = mid%n;

# 2 树实例

# 1二叉搜索树中第k小的元素

给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。

你可以假设 k 总是有效的,1 ≤ k ≤ 二叉搜索树元素个数。

示例 1:

输入: root = [3,1,4,null,2], k = 1

3

/ \

1 4

\

2

输出: 1

class Solution {
    private int i = 0;
    private int val = 0;
    public void dfs(TreeNode root, int k) {
        if (root == null) {
            return;
        }
        dfs(root.left, k);
        if (k == ++i) {
            val = root.val;
        }
        dfs(root.right, k);
    }
    public int kthSmallest(TreeNode root, int k) {
        dfs(root, k);
        return val;
    }
// 中序遍历二叉树得到有序数组, 递归的思想