zoukankan      html  css  js  c++  java
  • 二分法题目总结

    题目

    1. 剑指 offer 数字在排序数组中出现的次数
    2. 剑指 offer 旋转数组的最小数字
    3. Leetcode Search for a Range
    4. Leetcode Search Insert Position
    5. Leetcode Search a 2D matrix
    6. Leetcode sqrt(x)
    7. 九度 1534 数组中第 K 小的数字
    8. 剑指 offer 二维数组中的查找

    思路

    1. 二分法总体不难, 但是在边界问题的处理上需要格外的小心

    2. 上面的题目都是二分查找问题的变形, 要么是二分查找配合 int 特性(1/2 = 0), 要么是利用二分查找的原理来查找

    3. 第一题和第三题是等价的, 都是查找一个数在排序数组中的最左出现位置和最右出现位置.

    class Solution {
    public:
        vector<int> searchRange(int A[], int n, int target) {
            int left = left_pos(A, 0, n-1, target);
            int right = right_pos(A, 0, n-1, target);
            
            if(left < 0 || left >= n || A[left] != target) {
            	left = right = -1;
            }
    
            vector<int> res;
            res.push_back(left);
            res.push_back(right);
    
            return res;
        }
        
        int left_pos(int A[], int m, int n, int target) {
        	if(m > n)
        		return m;
    
        	int mid = (m+n)>>1;
    
        	// when a[mid] == target, prefer left one
        	if(A[mid] >= target) {
        		return left_pos(A, m, mid-1, target);
        	}else{
        		return left_pos(A, mid+1, n, target);
        	}
        }
    
        int right_pos(int A[], int m, int n, int target) {
        	if(m > n)
        		return n;
    
        	int mid = (m+n)>>1;
        	//cout  << mid << endl;
        	// when a[mid] == target, prefer right one
        	if(A[mid] > target) {
        		return right_pos(A, m, mid-1, target);
        	}else{
        		return right_pos(A, mid+1, n, target);
        	}
        }
    };
    

    在取最左位置时, 返回 low, 最右位置返回 high.

    返回 low 或 high 是由 a[mid] == target 时递归的走向决定的.

    取最左位置时, 当 low > high 时退出递归, 假设上一步是 a[mid] == target, 那么上一步的递归走向是 left_pos(A, low, mid-1, target)

    mid-1 越界, 所以应当返回 low

    4. 旋转数组中的最小数字. 这道题考察的是二分法原理.

    考虑旋转数组二分查找的原理和以之构建的框架... OK

    二分查找递归的方向由 a[mid] 和 target 的关系决定 :

    b_search(mid+1, high, target) if(a[mid] >= target)

    b_search(low, mid-1, target) if(a[mid] < target)

    在旋转数组中, 当出现重复元素时, 假如 a[mid] == target, 递归函数的走向不明, 因此不能再使用二分查找了

    5. 第四题算是 LIS 的子过程.

    当 a[mid] == target , 直接返回 mid

    递归函数结束时, return low: 函数结束意味着 low > high, 应该返回较大的 low.

    二分法最简单的记法: 

    若 a[mid] == target 时返回 mid, 那么最终结果返回 low

    否则, 最终结果按照思路 3 的分析进行

    6. 第五题和第八题是二分法的变形. 第五题要注意, 每次进行二分至少要消去一行. 而第八题是从右上角, 每次消去一行

    7. 第六七题利用到了 int 的性质, int 除以 2 不会有小数产生, 保证结果肯定会收敛. 其中第七题每次假设第 k 小数为 x, 这种设置方法与最大值最小化问题非常类似

  • 相关阅读:
    Java Collection知识总结
    Java异常总结
    关于触发器
    关于事务
    git分支的创建、删除、切换、合并
    github项目上传管理
    如何在github上下载单个文件夹?
    常见的javascript跨站
    各类常用端口漏洞缺陷
    SEO优化实践操作
  • 原文地址:https://www.cnblogs.com/zhouzhuo/p/3618239.html
Copyright © 2011-2022 走看看