美文网首页
要成功就做一百题-95

要成功就做一百题-95

作者: 西5d | 来源:发表于2020-05-25 21:39 被阅读0次

题目名称

已经排序的数组,必须在O(logn)的复杂度下统计得到指定元素的重复次数。

描述

比如数组[1,1,2,2,2,3,4,4,4,4,5,7,19],其中4重复4次。

解题思路

如果不要求logn的复杂度,可以二分查到目标值相等某个位置,然后分别向两边统计,得到最终的结果。但要求logn的情况下,必须要全局都是二分的操作。排除向两边分别查找的方法,可以看到目标是数组中的一个范围。所以可以先找左边,再找右边;之前是遇到相等就返回,现在需要额外再加限制条件,先从左边开始,如果找到了相等的位置,而且该位置左边的值,即mid-1的位置小于目标值,则是重复元素区间的最左开始,这里注意也包括索引位0的位置,即数组最左边;否则,就从end = mid-1的位置往左找,找到索引位0的位置结束,最终就是重复元素区间最左侧;
现在回到右边,只是截止条件包括了mid == arr.length - 1的情况。找的时候是从start = mid + 1的位置开始。如下是代码。

代码

    @Test
    public void test(){
        int[] arr = new int[]{1,1,1,2,2,2,3,4,4,4,5,6};
        int key = 3;

        System.out.println(bsRangeLeft(arr,key));
        System.out.println(bsRangeRight(arr, key));
        System.out.println(rangeSize(arr,key));
    }

    private int rangeSize(int[] arr, int key){
        if(null == arr || arr.length == 0){
            return -1;
        }
        int l = bsRangeLeft(arr, key);
        int r = bsRangeRight(arr, key);
        if(l == r && l < 0){
            return -1;
        }else {
            return Math.abs(r - l) + 1;
        }
    }
   //找左边索引位置
    private int bsRangeLeft(int[] arr, int key){
        int start = 0;
        int end = arr.length - 1;
        int mid;
        while (start <= end){
            mid = start + (end - start)/2;
            if(key == arr[mid]){
                if(mid == 0 || arr[mid - 1] < key){
                   //找到直接返回,条件是已经是最左边或者左边隔一位的值比目标小。
                    return mid;
                }
                end = mid - 1;
             //从mid-1的位置往前找
            }else if(key > arr[mid]){
                start = mid + 1;
            }else if(key < arr[mid]){
                end = mid -1;
            }
        }
        return -1;
    }

    private int bsRangeRight(int[] arr, int key){
        int start = 0;
        int end = arr.length - 1;
        int mid;
        while (start <= end){
            mid = start + (end - start)/2;
            if(key == arr[mid]){
                if(mid == arr.length -1 || arr[mid+1] > key){
                    return mid;//已经到最右边最大值或者它的右边一个比目标值大
                }
                start = mid + 1;//从mid+1的位置往右找
            }else if(key > arr[mid]){
                start = mid + 1;
            }else if(key < arr[mid]){
                end = mid - 1;
            }
        }
        return -1;
    }

总结

O(n)O(logn)还是有区别的,一是一,二是二,鸡蛋没有鹅蛋大。

相关文章

  • 要成功就做一百题-95

    题目名称 已经排序的数组,必须在O(logn)的复杂度下统计得到指定元素的重复次数。 描述 比如数组[1,1,2,...

  • 要成功就做一百题-90

    题目名称 第十三题 罗马数字转整数 描述 解题思路 这里做了个找规律,先把所有字符加起来,再处理特殊情况,题目说了...

  • 要成功就做一百题-89

    题目名称 实现字符串函数strStr() ,第28题 描述 解题思路 目的是找出某个字符串在另一个字符串的起始位置...

  • 要成功就做一百题-92

    题目名称 括号生成 描述 难度属于中等,目的是根据给定的括号数,生成有效的括号集合。 解题思路 这题比较有意思,这...

  • 要成功就做一百题-93

    题目名称 有效的括号判断 描述 输入的字符串只包含{ [] } ()三种括号的组合,判断输入是否是有效的括号,如下...

  • 要成功就做一百题-91

    题目名称 矩阵置零 描述 难度属于中等,如下是题目的描述,leetcode 73题。 解题思路 这里我也没用其他复...

  • 要成功就做一百题-99

    题目名称 爬楼梯问题,斐波拉契数列,泰波拉契数列 描述 第一个是常见的题目,第二个斐波拉契,第三个是斐波拉契的变种...

  • 要成功就做一百题-98

    题目名称 二叉树的中序遍历 描述 给定一个先序遍历的二叉树,打印出其中序(中根)遍历的结构。 解题思路 首先是根据...

  • 要成功就做一百题-100

    题目有点唬人,当然要的就是这个效果,标题党一把。从现在开始做100道leetcode题目,为了起到比较好的督促作用...

  • 要成功就做一百题-97

    题目名称 今天来一个简单题目试试水,好久没发了。 一来遇到个复杂题,一时没解,二来最近实在有点忙。废话不多,开始正...

网友评论

      本文标题:要成功就做一百题-95

      本文链接:https://www.haomeiwen.com/subject/ohwuahtx.html