找出数字在已排序数组中出现的次数

简介:

一,问题描述

假设给定一个有序的整型数组arr,以及一个整数 k,问 k在数组中出现了几次?

 

二,求解思路

①数组是有序的,故可考虑用二分查找

②如果能找到 k 在数组中第一次出现时的索引位置first_index 和 最后一次出现时的索引位置last_index

就可以知道 k 出现的次数了: (last_index - first_index) + 1

而对于有序数组而言,可以通过二分查找求出某个数第一次出现的索引位置 和 最后一次出现的索引位置。故总的时间复杂度为O(logN)

③特殊情况考虑

k 不在数组中时怎么办? 数组arr为null 或者 数组 arr.length == 0

 

核心思路:求解 k 第一次出现时的索引位置

首先找出arr[middle],如果 k 比中间元素,则在右边寻找k第一次出现时的索引位置(递归),若 k 比中间元素,则在左边寻找...(递归)。

若 k == arr[middle],则需要判断 arr[middle -1] 是否等于 k,若不等于k,则说明 middle 就是 k 第一次出现时的索引;若等于 k,则继续递归在左边寻找,但是此时要注意 左边索引不要越界(middle == low 了,就不能再往左边寻找了)。

同理可求解,k 最后一次出现时的索引位置。

 

三,完整代码实现

复制代码
public class OccFreq {
    
    /**
     * 求解 k 在 arr 中第一次出现的索引位置
     * @param arr 有序数组
     * @param k
     * @return k第一次出现的索引位置,若 k 不在 arr中返回 -1
     */
    public static int getFirst(int[] arr, int k){
        if(arr == null || arr.length == 0)
            throw new IllegalArgumentException("arr == null or arr.lenght == 0");
        
        return getFirst(arr, 0, arr.length - 1, k);
    }
    
    private static int getFirst(int[] arr, int low, int high, int k){
        int middle = (low + high) / 2;
        if(middle == low || middle == high)
        {
            if(arr[middle] == k)
                return middle;
            else
//                throw new IllegalArgumentException(k + " not in arr");
                return -1;
        }
        
        if(arr[middle] > k)
            return getFirst(arr, low, middle - 1, k);
        else if(arr[middle] < k)
            return getFirst(arr, middle + 1, high, k);
        else
        {
            if(arr[middle - 1] == k)
                return getFirst(arr, low, middle - 1, k);
            else
                return middle;
        }
    }
    
    /**
     * 求解 k 在 arr 中最后一次出现的索引
     * @param arr
     * @param k
     * @return k 在arr中的最后出现的索引, 若 k 不在 arr中返回 -1
     */
    public static int getLast(int[] arr, int k){
        if(arr == null || arr.length == 0)
            throw new IllegalArgumentException("arr == null");
        return getLast(arr, 0, arr.length - 1, k);
    }
    private static int getLast(int[] arr, int low, int high, int k){
        int middle = (low + high) / 2;
        //已经寻找到最左边 或 最右边了.
        if(middle == low || middle == high)
        {
            if(arr[middle] == k)
                return middle;
            else
//                throw new IllegalArgumentException(k + " not in arr");
                return -1;//k 不在 arr中
        }
        if(arr[middle] > k){//继续在左边寻找
            return getLast(arr, low, middle - 1, k);
        }
        else if(arr[middle] < k){//继续在右边寻找
            return getLast(arr, middle + 1, high, k);
        }
        else//k== arr[middle]
        {
            if(arr[middle + 1] == k)
                return getLast(arr, middle + 1, high, k);//继续在右边寻找
            else
                return middle;
        }
    }
    
    /**
     * 求解 k 在 arr数组中出现的次数
     * @param arr 有序数组
     * @param k
     * @return k 在 arr 数组中出现的次数
     */
    public static int freq(int[] arr, int k){
        int first_index = getFirst(arr, k);
        int last_index = getLast(arr, k);
        if(first_index < 0 && last_index < 0)
            return 0;
        return last_index - first_index + 1;
    }
    
    public static void main(String[] args) {
        int[] arr = {2,4,5,6,8,8,8,9};
    
        int freqs = freq(arr, 1);
        System.out.println(freqs);
    }
}
本文转自hapjin博客园博客,原文链接:http://www.cnblogs.com/hapjin/p/5674810.html,如需转载请自行联系原作者
相关文章
|
SQL 监控 关系型数据库
Postgresql CPU 资源占用过高问题
Postgresql CPU 资源占用过高问题
1803 0
Postgresql CPU 资源占用过高问题
|
Kubernetes 架构师 Java
史上最全对照表:大厂P6/P7/P8 职业技能 薪资水平 成长路线
40岁老架构师尼恩,专注于帮助读者提升技术能力和职业发展。其读者群中,多位成员成功获得知名互联网企业的面试机会。尼恩不仅提供系统化的面试准备指导,还特别针对谈薪酬环节给予专业建议,助力求职者在与HR谈判时更加自信。此外,尼恩还分享了阿里巴巴的职级体系,作为行业内广泛认可的标准,帮助读者更好地理解各职级的要求和发展路径。通过尼恩的技术圣经系列PDF,如《尼恩Java面试宝典》等,读者可以进一步提升自身技术实力,应对职场挑战。关注“技术自由圈”公众号,获取更多资源。
|
SpringCloudAlibaba 负载均衡 网络协议
快速搭建 SpringCloud Alibaba Nacos 配置中心!
快速搭建 SpringCloud Alibaba Nacos 配置中心!
572 0
|
存储 安全 数据安全/隐私保护
|
编解码 芯片
红外遥控模块的使用方法,以及stm32代码
红外遥控模块的使用方法,以及stm32代码
1321 0
红外遥控模块的使用方法,以及stm32代码
|
安全 Java API
原来SpringSecurity整合OAuth2后开放权限拦截路径还能这么玩?
当我们整合了`Spring Security`以及`OAuth2`后发现,有一些业务请求是需要开放的,因为种种原因这时访问者还没有身份标识(`比如:用户刚来,还没有注册,需要进行新用户注册,这时注册业务相关的接口都应该是开放的`),下面我们来看看`ApiBoot`是怎么排除路径不进行权限拦截的。
|
存储 SQL 搜索推荐
阿里云PostgreSQL精选案例 - 实时精准营销、人群圈选
标签 PostgreSQL , 阿里云 , 实时精准营销 , 人群圈选 , 广告 背景 行业: 几乎所有行业, 如互联网、新零售、教育、游戏等. 应用场景: 根据目标群体的特征, 快速提取目标群体.
3043 0
阿里云PostgreSQL精选案例 - 实时精准营销、人群圈选
|
SQL 存储 并行计算
ClickHouse性能测试
ClickHouse性能测试
278 0
|
存储 运维 对象存储