首页 > 其他分享 >二分查找法upper版(找大于某个值的最小下标)递归+非递归版

二分查找法upper版(找大于某个值的最小下标)递归+非递归版

时间:2023-06-22 13:55:04浏览次数:49  
标签:upper 下标 target 递归 int mid data public

需求:比如说查询一个班级大于60分的最低分等等。

思路与二分法基本相同,只不过是对比的逻辑发生了一些小变化,这里所说的上界就是指大于某个值的最小下标。

  • 当mid < target :说明 target 的上界还在mid的右边,所以要去找比mid大的

  • 当mid > target:说明 mid 有可能是target的上界,所以我们加个判断,如果mid前一个元素就刚好是target,说明mid就是我们要找的上界,否则继续找。

另一个注意的点,就是我们取变量 r 的时候,不再是取数组最大的下标了,而是要超过一个,因为如果你找的是数组最后一个元素的上界,其实是不在数组里的。

递归版:

package com.Search;
/**
 * @Author: 翰林猿
 * @Description: 二分查找upper版(找大于某个值的最小下标)
 **/
public class BinarySearchUpper {
    public BinarySearchUpper() {
    }
​
    public static <E extends Comparable<E>> int SearchUpper(E[] data, E target) {
        return SearchUpper(data, 0, data.length, target);     //是length而不是length-1,因为有可能上界值不在该数组里,所以此时r就应该取大于数组最大值下标+1的位置
    }
​
    /**
     * @Description 递归版本
     */
    public static <E extends Comparable<E>> int SearchUpper(E[] data, int l, int r, E target) {
        if (l >= r) return -1;
        int mid = l + (r - l) / 2;
        if (data[mid].compareTo(target) <= 0) {         //如果mid小于目标值,说明target的上界还在右边,要去找比mid大的
            return SearchUpper(data, mid + 1, r, target);
        }
        if (data[mid].compareTo(target) > 0 && data[mid - 1].compareTo(target) == 0) {
            return mid;
        }
        //说明mid又大于target,但是mid-1又不等于target,说明当前的mid不是上界。比如说测试用例1, 1, 1, 2, 2, 3, 6, 8, 18, 20
        //我们要找大于3的最小下标也就是6的下标,但是经过两次递归,mid=18,但是18所在的下标为8,8-1=7的元素是8,但是8并不等于3,所以mid=18时不是我们要找的upper
        //此时继续递归
        return SearchUpper(data, l, mid, target);   //mid已经大于目标值了,而且当前的mid不是上界,所以我们往左边找
​
    }
​
        public static void main (String[]args){
            Integer[] arr = {1, 1,1, 2, 2, 3, 6, 8, 18, 20};
            int index = SearchUpper(arr, 3);
            System.out.println(index);
        }
    }

非递归版:

package com.Search;
/**
 * @Author: 翰林猿
 * @Description: 二分查找upper版(找大于某个值的最小下标)
 **/
public class BinarySearchUpper {
    public BinarySearchUpper() {
    }
​
    public static <E extends Comparable<E>> int SearchUpper2(E[] data, E target) {
        return SearchUpper2(data, 0, data.length, target);     //是length而不是length-1,因为有可能上界值不在该数组里,所以此时r就应该取大于数组最大值下标+1的位置
    }
    
    /**
     * @Description 非递归版本
     */
    public static <E extends Comparable<E>> int SearchUpper2(E[] data, int l, int r, E target) {
        while (l < r) {
            int mid = l + (r - l) / 2;
            if (data[mid].compareTo(target) == 0) {
                return mid + 1;
            } else if (data[mid].compareTo(target) > 0) { // 这个r = mid是因为mid的位置可能是目标值
                r = mid;
            } else {
                l = mid + 1;
            }
        }
        // l和r最后都都指向同一个位置。没找到则返回arr.length
        return l;
    }
​
        public static void main (String[]args){
            Integer[] arr = {1, 1,1, 2, 2, 3, 6, 8, 18, 20};
            int index2 = SearchUpper2(arr, 3);
            System.out.println(index2);
        }
    }

标签:upper,下标,target,递归,int,mid,data,public
From: https://www.cnblogs.com/hanlinyuan/p/17497699.html

相关文章

  • 代码随想录算法训练营第十四天| 104.二叉树的最大深度 (优先掌握递归) 111.二叉树的最小
    104.二叉树的最大深度(优先掌握递归)迭代法,上一篇已经讲过,只需要对每一层+1,这里重要些递归法递归法注意:如果当前节点为NULL,返回0,不是NULL,那么就是1+max(right,left)代码:1voidmaxD_cursor(TreeNode*node,int&result)2{3if(!node)return;45result......
  • 时间序列转图像:符号递归图(Symbolic recurrence plots)(matlab版复现)
    符号递归图(Symbolicrecurrenceplots):是一种以为时间序列转图像技术,可用于平稳和非平稳数据集;对噪声具有鲁棒性,在一定的数据变换条件下具有不变性。结合深度学习技术可以解决能源电力,水利,天气,生物医学,交通等领域的复杂模式识别和监测任务。链接:https://mbd.pub/o/bread/mbd-ZJqY......
  • [Leetcode] 0724. 寻找数组的中心下标
    724.寻找数组的中心下标点击上方,跳转至leetcode题目描述给你一个整数数组 nums,请计算数组的中心下标。数组中心下标是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。如果中心下标位于数组最左端,那么左侧数之和视为0,因为在下标的左侧不存在元素。......
  • 代码随想录算法训练营第十三天| 层序遍历 226.翻转二叉树 (优先掌握递归) 101. 对
    层序遍历注意:1,使用队列的形式,依次入队,同时对队列进行计数2,知道数目消失,才进行下一个队列代码:1vector<vector<int>>levelOrder(TreeNode*root)2{3vector<vector<int>>result;4if(root==NULL)returnresult;5queue<TreeNode*>selected;6......
  • java递归创建目录
    importjava.io.File;publicclassCreateDirectory{publicstaticvoidmain(String[]args){Stringpath="D:\\heap\\d\\c\\e";createDirectory(path);}publicstaticvoidcreateDirectory(Stringpath){......
  • 【计算机算法设计与分析】线性时间选择(C++_分治递归)
    问题描述给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素。思路线性时间选择有两种方法:(1)随机选择快排的标准元素。(2)将集合分为n个由五个元素组成的集合,对每个五元素集合求其中位数,再对所有的五元素集合的中位数求其中位数,作为快排的标准元素。CodeV-1(Ran......
  • 代码随想录算法训练营第十二天| 递归遍历 (必须掌握)迭代遍历 统一迭代
    递归遍历重点:1,TreeNode的自定义2,val=0== val=NULL;代码:1voidpreRecursor(TreeNode*root,vector<int>&result)2{3if(root==NULL)4return;5result.push_back(root->val);6preRecursor(root->left,result);7......
  • 数据结构代码整理_基于邻接表的拓扑排序(C++_DFS_BFS_递归)
    目录Chat图解基于栈实现(dfs)基于队列实现(bfs)基于递归实现(dfs)Chat1.代码所属的类在数据结构代码整理_基于邻接表存储结构的有向图的实现(C++)2.拓扑排序的思想就是不断找入度为0的节点并将其输出并标记,标记后与他相连的节点的入度都会减一,不断进行标记直至所有的节点都被输出为止......
  • js递归简易深拷贝
    letobj={a:1,b:{b1:1,b2:2},c:[1,2,3]}functiondeepClone(obj){letresult=Array.isArray(obj)?[]:{}for(letkeyinobj){if(obj.hasOwnProperty(key)){if(obj[key]&&typeofobj[key]==&......
  • C# 获取数组排序后的下标
    usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceConsoleApp9{classProgram{staticvoidMain(string[]args){int[]src=newint[]{2,1......