首页 > 其他分享 >有重复值的二分查找

有重复值的二分查找

时间:2023-04-23 17:22:47浏览次数:26  
标签:二分 arr temp 重复 mid int range 查找

最近在验证SQL join的算法,感觉在内存中实现的话,比较高效的方法就是二分查找了。

但与普通二分查找不同,SQL join的时候左右两边的值可能会有重复,这些重复值都是要找到的。

所以我对二分查找进行了升级优化,不再返还一个索引,而是返回一个索引范围,找不到就返回null

实现了两个版本:

1.递归二分查找

2.while循环二分查找

 /**
     * 带重复值的二分查找,返回目标所在的索引范围
     * 二分查找-递归版本
     *
     * @param arr
     * @param left
     * @param right
     * @param findVal
     * @return
     */
    public static <T extends Comparable<T>> Range binarySearch2(List<T> arr, int left, int right, T findVal) {
        // 当left > right 时,说明递归整个数组没有找到
        if (left > right) {
            return null;
        }
        int mid = (left + right) / 2;
        T midVal = arr.get(mid);

        if (midVal.compareTo(findVal) > 0) {
            return binarySearch2(arr, left, mid - 1, findVal);
        } else if (midVal.compareTo(findVal) < 0) {
            return binarySearch2(arr, mid + 1, right, findVal);
        } else {
            Range range = new Range();
            range.setStart(mid);
            range.setEnd(mid);
            // 先让temp向左移
            int temp = mid - 1;
            while (temp >= 0 && arr.get(temp).equals(findVal)) {
                // 否则,就把temp放进resIndex中
                range.setStart(temp);
                temp -= 1; // temp 左移
            }
            //temp右移
            temp = mid + 1;
            while (temp < arr.size() && arr.get(temp).equals(findVal)) {
                range.setEnd(temp);
                temp += 1; // temp 左移
            }
            return range;

        }

    }

    /**
     * 有重复值的二分查找,while循环版本
     *
     * @param des
     * @return
     */
    public static <T extends Comparable<T>> Range binarySearch(List<T> arr, T des) {
        //定义初始最小、最大索引
        int start = 0;
        int end = arr.size() - 1;
        int mid = -1;
        //确保不会出现重复查找,越界
        while (start <= end) {
            //计算出中间索引值
            int middle = (end + start) / 2;//防止溢出
            if (des.equals(arr.get(middle))) {
                mid = middle;
            } else if (des.compareTo(arr.get(middle)) < 0) {
                end = middle - 1;
            } else {
                start = middle + 1;
            }
        }
        //没找到,返回null
        if (mid == -1) {
            return null;
        }
        Range range = new Range();
        range.setStart(mid);
        range.setEnd(mid);
        // 先让temp向左移
        int temp = mid - 1;
        while (temp >= 0 && arr.get(temp).equals(des)) {
            // 否则,就把temp放进resIndex中
            range.setStart(temp);
            temp -= 1; // temp 左移
        }
        //temp右移
        temp = mid + 1;
        while (temp < arr.size() && arr.get(temp).equals(des)) {
            range.setEnd(temp);
            temp += 1; // temp 左移
        }
        return range;

    }

    /**
     * 目标索引范围,左闭右闭区间
     */
    @Data
    static class Range {
        private int start;
        private int end;
    }

 

标签:二分,arr,temp,重复,mid,int,range,查找
From: https://www.cnblogs.com/wangbin2188/p/17347146.html

相关文章

  • 三大类算法:递归、排序、二分查找
    一、递归”递“+”归“。这两个意思,正是递归思想的精华所在,去的过程叫做递,回来的过程叫做归,在编程语言中对递归可以简单理解为:方法自己调用自己,只不过每次调用时参数不同而已。满足递归的条件:1、递归表达是(规律)如果一个问题的解能够拆分成多个子问题的解,拆分之后,子问题和该问题在求......
  • 九、数组中存在重复
    给定一个整数数组,判断是否存在重复元素。如果任何值在数组中出现至少两次,函数返回true。如果数组中每个元素都不相同,则返回false。示例1:输入:[1,2,3,1]输出:true示例2:输入:[1,2,3,4]输出:false示例 3:输入:[1,1,1,3,3,4,3,2,4,2]输出:trueclassSolution{pub......
  • 9.折半查找
     问题分析:首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记......
  • 剑指Offer——03.数组中重复的数字(c语言)
    title:剑指Offer03.数组中重复的数字(c语言)找出数组中重复的数字。在一个长度为n的数组nums里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。示例1:输入:[2,3,1,0,2,......
  • 力扣——83.删除排序链表中的重复元素(c语言)
    title:力扣——83.删除排序链表中的重复元素(c语言)题目描述:给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。示例1:输入:1->1->2输出:1->2示例2:输入:1->1->2->3->3输出:1->2->3代码如下:/***Definitionforsingly-linkedlist.*structListNode{*......
  • 1241.二分法求函数零点 | 浮点二分
    1241二分法求函数的零点题目来源信息学奥赛一本通题目描述\(有函数:f(x)=x5−15x4+85x3−225x2+274x−121.已知f(1.5)>0,f(2.4)<0且方程f(x)=0在区间[1.5,2.4]有且只有一个根,请用二分法求出该根。\)输出要求\(该方程在区间[1.5,2.4]中的根。要求四舍五入到小数点后6位。\)......
  • 扎实打牢数据结构算法根基,从此不怕算法面试系列之002 week01 02-02 线性查找法
    1、线性查找法什么是线性查找法?举例:在一沓试卷中,找到属于自己的那张试卷。第1张:不是第2张:不是第3张:不是……第n张:是,找到了!第n+1张:不找了……这个解决问题的思路和过程体现就是线性查找法的思想。2、线性查找法思路梳理线性查找法,就是在线性的数据结构中来完成。例如:在data数......
  • 扎实打牢数据结构算法根基,从此不怕算法面试系列之003 week01 02-03 代码实现线性查找
    1、算法描述在数组中逐个查找元素,即遍历。2、思路原理如算法描述,基本是最简单的代码块了,没有什么额外的原理。3、初步的代码实现线性查找法初步的代码实现:packagecom.mosesmin.datastructure.week01.chap02;/***@Misson&Goal代码以交朋友、传福音*@ClassNameLinearSearc......
  • 数据清洗--缺失值与重复值的处理
    1.df.info()查看是否有缺失值: 2.df.isnull和df.notnull判断缺失值: 3.df.dropan()删除缺失值: 4.删除课程总数量为空的行: 5.将为NaN的值指定填充为0: 6.去除全部的重复值: 7.去除指定列的重复数据行: 8.直接删除数据生成新的副本,不修改原数据: ......
  • 折半查找
    一、问题描述:  二、设计思路: 折半查找思路是找首位置low,和末位置high,中间位置mid=(首位置+末位置)/2,满足的循环是首位置<=末位置,如果中间的位置上的数小于要找的目标,则low=mid+1转换为新的首位置和末位置之间找数字,之间缩小一半的范围,这就是二分查找的妙处,如果中间的位置上......