• 【LeetCode & 剑指offer刷题】数组题8:53 数字在排序数组中出现的次数


    【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)

    53 数字在排序数组中出现的次数

    题目描述
    统计一个数字在排序数组中出现的次数。
     
    //方法一:顺序扫描,统计出现的次数,O(n)
    /*
    方法二:由于是有序数组,可以用二分查找
    stl中函数
    lower_bound upper_bound
    O(logn) O(1)
    */
    class Solution
    {
    public:
        int GetNumberOfK(vector<int>& data ,int k)
        {
            if(data.empty()) return 0;
           
            vector<int>::iterator first = lower_bound(data.begin(),data.end(),k); //返回第一个大于等于k的位置
            vector<int>::iterator last = upper_bound(data.begin(),data.end(),k); //返回第一个大于k的位置
            return last - first;
        }
    };
    /*
    方法:自己实现
    lower_bound upper_bound
    O(logn) O(1)
    */
    class Solution
    {
    public:
        int GetNumberOfK(vector<int>& data ,int k)
        {
            if(data.empty()) return 0;
           
            int first = my_lower_bound(data,k); //返回第一个大于等于k的位置
            int last = my_upper_bound(data,k); //返回第一个大于k的位置
            return last - first;
        }
    private:
        int my_lower_bound(vector<int>& a, int target)
        {
            int left = 0, right = a.size(); //stl中喜欢把end指向末尾后一个元素的做法类似
            while (left < right)
            {
                int mid = left + (right - left) / 2;
                if (a[mid] < target)
                    left = mid + 1;
                else            //没有单独考虑等于的情况
                    right = mid;
            }
            return right;
        }
        int my_upper_bound(vector<int>& a, int target)
        {
            int left = 0, right = a.size(); //stl中喜欢把end指向末尾后一个元素的做法类似
            while (left < right)
            {
                int mid = left + (right - left) / 2;
                if (a[mid] <= target)
                    left = mid + 1;
                else
                    right = mid;
            }
            return right;
        }
    };
     
     
    //方法二:由于是有序的,可以用二分查找,找到该数第一次出现的位置和最后一次出现的位置,计算次数即可
    //O(logn)
    class Solution
    {
    public:
        int GetNumberOfK(vector<int>& data ,int k)
        {
            if(data.empty()) return 0;
            int first = getFirst(data, k);
            int last = getLast(data, k);
            if(first != -1 && last != -1) return last - first + 1;
            else return 0; //如果找不到就返回0
        }
    private:
        int getFirst(vector<int>& a, int k)
        {
            int left = 0;
            int right = a.size() - 1;
            int mid;
            while(left <= right)
            {
                mid = (left+right) / 2;          
                if(a[mid] < k)
                    left = mid + 1;
                else if(a[mid] > k)
                    right = mid - 1;
                else if(mid-1 >= 0 && a[mid-1] == k)//当前数等于k,前一个数也等于k时,继续在左半区间查找
                    right = mid - 1;
                else //当前数等于k,前一个数不等于k或者为开头时,返回mid
                    return mid;
            }
            return -1; //找不到时返回-1
        }
        int getLast(vector<int>& a, int k)
        {
            int left = 0;
            int right = a.size() - 1;
            int mid;
            while(left <= right)
            {
                mid = (left+right) / 2;
                if(a[mid] < k)
                    left = mid + 1;
                else if(a[mid] > k)
                    right = mid - 1;
                else if(mid+1 < a.size() && a[mid+1] == k) //当前数等于k,后一个数也等于k时,继续在右半区间查找
                    left = mid+1;
                else //当前数等于k,后一个数不等于k或者后一个数为末尾时,返回mid
                    return mid;
            }
            return -1; //找不到时返回-1
        }
    };
     
    //回顾普通的二分查找
    int binarysearch(vector<int>& a, int k)
    {
        int left = 0;
        int right = a.size() - 1;
        int mid;
        while(left <= right)
        {
            mid = (left+right) / 2;
            if(a[mid] < k) //k较a[mid]大时,在右半区间找
                left = mid + 1;
            else if(a[mid] > k) //k较小时,在左半区间找
                right = mid - 1;
            else //若想等则返回mid
                return mid;
        }
        return -1; //找不到时返回-1
    }
     
     
  • 相关阅读:
    一起谈.NET技术,Silverlight中二维变换详解 狼人:
    一起谈.NET技术,通过16道练习学习Linq和Lambda 狼人:
    一起谈.NET技术,技巧:使用可扩展对象模式扩展HttpApplication 狼人:
    一起谈.NET技术,ASP.NET的运行原理与运行机制 狼人:
    一起谈.NET技术,.NET远程处理框架详解 狼人:
    一起谈.NET技术,从原理来看Silverlight 4的架构 狼人:
    一起谈.NET技术,ASP.NET MVC中对Model进行分步验证的解决方法 狼人:
    一起谈.NET技术,解决编程中序列化问题 狼人:
    一起谈.NET技术,asp.net控件开发基础(2) 狼人:
    一起谈.NET技术,asp.net控件开发基础(1) 狼人:
  • 原文地址:https://www.cnblogs.com/wikiwen/p/10224328.html
Copyright © 2020-2023  润新知