二分法的细节理解

  1. 二分法的主旨: 通过不断二分来缩小范围直到搜索出目标值;

  2. 最近在做一道二分题时,如何来划分范围成为了一个难点!(并不是随便来划分的)0

  3. 下面以一道题目为例来刨分二分法;题目连接

给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素。
请注意,它是排序后的第k小元素,而不是第k个元素。

示例:

matrix = [
   [ 1,  5,  9],
   [10, 11, 13],
   [12, 13, 15]
],
k = 8,

返回 13。
说明:
你可以假设 k 的值永远是有效的, 1 ≤ k ≤ n2 。

/**
 *
 * 这道题看似有规律,实则 给我们的信息仅有
 * todo 表面提供的信息 , 而推出的特性基本没有,而且在我们做题的时候还产生了很多误解;
 *
 *
 * todo 解题思路:
 * todo 全局思路:
 *  1. 知道最大值最小值, 我们需要寻找第 k值 ,而第 k 值就在 L = min   与   R = max  中间 , 然后我们可以不断取中间值,然后
 *  逐步缩小范围,直到 出现 L = R 的情况;
 *
 * todo 注意:  范围值代表 L <= 范围 <= R ;
 *
 *todo    L->|_____________|<-R   划分范围 : L->|____|mid     (mid +1)|_____|<-R
 *todo    这里要重点说明 mid 划分判定条件一定是  属于左范围的 , 当然会问为甚麽呢?
 * 这里 将mid 划分为右半范围   L--mid-1  mid--R 这种划分方式不可以吗?  在整数划分时,这种划分是肯定不行的;
 * for example    (2+3)/2 =2 ;  此时如果恰好判定范围为右范围,这样的话 新范围还是 【 2,3】,无线循环; 
 *
 */

 

   public int kthSmallest(int[][] matrix, int k) {

        int L =matrix[0][0];
        int R =matrix[matrix.length-1][matrix.length-1];

        while (L != R ){
            int mid =(L+R)/2;
            int count =getIndex(mid,matrix);//todo 找到 mid 的 index ; 分割点 必须是 左范围包含中间点;右范围不包括中间点

            if (count>=k){//todo k在左范围的情况
                R=mid;
            }else{
                L=mid +1; //todo k在右范围 情况
            }
        }
        return L;

    }

    //todo 用于计算 <=mid 的值有多少;
    private int getIndex(int mid ,int[][] a) {
        int count =0;
        for (int i = 0; i <a.length; i++) {
            int len =a.length;
            while (len>=1){
                if (a[i][len-1]>mid){
                    len--;
                    continue;
                }
                count=count+len;
                break;
            }
        }
        return count;
    }

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值