剑指Offer--038-数字在排序数组中出现的次数

链接


牛客OJ:数字在排序数组中出现的次数

九度OJ:http://ac.jobdu.com/problem.php?pid=1349

GitHub代码: 038-数字在排序数组中出现的次数

CSDN题解:剑指Offer–038-数字在排序数组中出现的次数

牛客OJ 九度OJ CSDN题解 GitHub代码
038-数字在排序数组中出现的次数 1505-数字在排序数组中出现的次数 剑指Offer–038-数字在排序数组中出现的次数 038-数字在排序数组中出现的次数

题意



题目描述

统计一个数字在排序数组中出现的次数。

暴力方法



由于数组是有序的,因此我么通过一次遍历,对要查找的元素直接计数就可以了

#include <iostream>
#include <vector>

using namespace std;

//  调试开关
#define __tmain main

#ifdef __tmain

#define debug cout

#else

#define debug 0 && cout

#endif // __tmain

class Solution
{
public:
    int GetNumberOfK(vector<int> data,int k)
    {
        if(data.size( ) == 0)
        {
            return 0;
        }

        int count = 0;
        for(unsigned int i = 0;
            i < data.size( ) && data[i] <= k;
            i++)
        {
            if(data[i] == k)
            {
                count++;
            }
        }

        return count;
    }
};

int __tmain( )
{
    Solution solu;

    int arr[] = { 1, 2, 3, 3, 3, 3, 4, 5 };
    vector<int> vec(arr, arr + 8);
    cout <<solu.GetNumberOfK(vec, 3) <<endl;

    return 0;
}

当然也可以使用STL中特定容易的计数功能

class Solution
{
public:
    int GetNumberOfK(vector<int> data ,int k)
    {
        multiset<int> mData;
        for(int i = 0; i < data.size( ); i++)
        {
            mData.insert(data[i]);
        }

        return mData.count(k);
    }
};

分治–二分查找


二分查找(递归和非递归)



我们通过二分查找到指定的元素K后,然后再分别向前和向后查找总的个数

/* 先用二分查找找出某个k出现的位置,然后再分别向前和向后查找总的个数*/
class Solution
{
public:
    int GetNumberOfK(vector<int> data,int key)
    {
        if(data.size( ) == 0)
        {
            return 0;
        }

        //  用二分查找查找到Key的位置
        int index = BinarySearch(data, 0, data.size( ) - 1, key);
        //int index = BinarySearch(data, key);
        if(index == -1)
        {
            return 0;
        }

        int count = 1;
        // 查找前面部分Key的个数
        for(int j = index - 1;
            j >= 0 && data[j] == key;
            j--)
        {
            debug <<"pos = " <<j <<", data = " <<data[j] <<endl;
            count++;
        }

        //  查找后面部分Key的个数
        for(int j = index + 1;
            j < data.size( ) && data[j] == key;
            j++)
        {
            count++;
        }

        return count;
    }

    int BinarySearch(vector<int> &data, int begin, int end ,int key)
    {
        if(begin > end)
        {
            return -1;
        }

        int mid = (begin + end) / 2;
        debug <<"mid = " <<mid <<", data = " <<data[mid] <<endl;
        if(data[mid] == key)
        {
            return mid;
        }
        else if(data[mid] > key)
        {
            return BinarySearch(data, begin, mid - 1, key);
        }
        else if(data[mid] < key)
        {
            return BinarySearch(data,mid + 1, end, key);
        }
        return -1;
    }

    int BinarySearch(vector<int> array, int key)
    {
        int low = 0, high = array.size( ) - 1;

        int mid;  

        while (low <= high)
        {
            mid = (low + high) / 2;  

            if(key == array[mid])
            {
                return mid;
            }

            if(key < array[mid])
            {
                high = mid - 1;
            }

            if(key > array[mid])
            {
                low = mid + 1;
            }
        }

        return -1;
    }
};

改进的二分查找,返回第一个和最后一个的位置



递归版

class Solution
{
    /*二分查找 找到第一个K 和 最后一个K 二者位置相减*/
public:
    int GetNumberOfK(vector<int> data ,int k)
    {
        if(data.empty())
        {
            return 0;
        }

        int number = 0;
        int first = GetFirstIndex(data, k, 0, data.size( ) - 1);
        int last  = GetLastIndex(data, k, 0, data.size( ) - 1);

        if(first > -1 && last > -1)
        {
            number = last - first +1;
            return number;
        }
    }

    // 查找第一个的位置
    int GetFirstIndex(vector<int> &data, int low, int high, int k)
    {
        if(low > high)
        {
            return -1;
        }

        int mid = (low + high) / 2;

        if(data[mid] == k)
        {
            if((mid > 0 && data[mid-1] != k) || mid == 0)
            {
                return mid;
            }
            else
            {
                high = mid - 1;
            }
        }
        else if(data[mid] > k)
        {
            high = mid - 1;
        }
        else if(data[mid] < k)
        {
            low = mid + 1;
        }

        return GetFirstIndex(data, k, low, high);
    }

    int GetLastIndex(vector<int> &data, int low, int high, int k)
    {
        if(low > high)
        {
            return -1;
        }

        int mid = (low + high) / 2;
        if(data[mid]==k)
        {
            if((mid>0 && data[mid+1] !=k) || mid == high)
            {
                return mid;
            }
            else
            {
                low = mid +1;
            }
        }
        else
        {
            if(mid>k)
            {
                high = mid-1;
            }
            else
            {
                low = mid+1;
            }
        }

        return GetLastIndex(data,k,low,high);
    }
};

非递归版

class Solution
{
public:
    int GetNumberOfK(std::vector<char> array , int k)
    {
        if (array == null || array.size( ) == 0)
        {
            return 0;
        }

        int low = 0, high = array.size( ) - 1,
        int first = 0, last = 0;

        if (low == high)
        {
            if (array[0] != k)
            {
                return 0;
            }
            else
            {
                return 1;
            }
        } 

        int number = 0;
        int first = GetFirstIndex(data, k, 0, data.size( ) - 1);
        int last  = GetLastIndex(data, k, 0, data.size( ) - 1);

        if(first > -1 && last > -1)
        {
            number = last - first +1;
            return number;
        }
        else
        {
            return 0;
        }
    }

    int GetFirstIndex(vector<int> &data, int low, int high, int k)
    {
        int mid
        while (low < high)
        {
            int mid = (low + high) / 2;
            if (array[mid] < k)
            {
                if (array[mid + 1] == k)
                {
                    first = mid;
                    break;
                }
                low = mid + 1;
            }
            else
            {
                high = mid;
                first = -1;
            }
        }

        if (array[first + 1] != k)   // can‘t find it.
        {
            return 0;
        }
    }

    int GetLastIndex(vector<int> &data, int low, int high, int k)
    {
        int last, mid;

        while (low < high)
        {
            mid = (low + high) / 2;
            if (array[mid] <= k)
            {
                last = mid;

                if (array[mid + 1] > k)
                {
                    break;
                }
                else if (mid + 1 >= high)
                {
                    last++;
                    break;
                }
                low = mid + 1;
            }
            else
            {
                high = mid;
            }
        }
    }
};

STL的

 ForwardIter lower_bound(ForwardIter first, ForwardIter last,const _Tp& val)

算法返回一个非递减序列[first, last)中的第一个大于等于值val的位置。

ForwardIter upper_bound(ForwardIter first, ForwardIter last, const _Tp& val)

算法返回一个非递减序列[first, last)中第一个大于val的位置。

class Solution
{
public:
    int GetNumberOfK(vector<int> data ,int k)
    {
        int upper = upper_bound(data.begin(),data.end(),k);
        int low = lower_bound(data.begin(),data.end(),k);
        return upper - low;
    }
};
时间: 2024-10-24 15:30:59

剑指Offer--038-数字在排序数组中出现的次数的相关文章

【剑指offer】数字在排序数组中出现的次数

转载请注明出处:http://blog.csdn.net/ns_code/article/details/27364557 题目描写叙述: 统计一个数字在排序数组中出现的次数. 输入: 每一个測试案例包括两行: 第一行有1个整数n,表示数组的大小.1<=n <= 10^6. 第二行有n个整数,表示数组元素,每一个元素均为int. 第三行有1个整数m,表示接下来有m次查询.1<=m<=10^3. 以下有m行,每行有一个整数k,表示要查询的数. 输出: 相应每一个測试案例,有m行输出,

[剑指Offer] 37.数字在排序数组中出现的次数

题目描述 统计一个数字在排序数组中出现的次数. [思路]因为是排序数组,所以可以用二分法搜索到要查找的值在数组中的一个位置,接着向两侧扫描,遇到不等的就停止. 1 class Solution { 2 public: 3 int getIndexbyDivision(vector<int> data,int k){ 4 int left = 0,right = data.size() - 1; 5 int middle = left + (right - left)/2; 6 while(le

剑指offer:数字在排序数组中出现的次数

题目描述: 统计一个数字在排序数组中出现的次数. 思路分析: 1. 直观思路是直接遍历一遍,统计.复杂度也只要O(n). 2. 显然这道题要考察的内容不这么简单,实际上考虑二分的思想来完成.分别二分查找第一个k和最后一个k.具体来说,利用二分查找思想,找到k,再判断当前的前一个是否为k或是否为第一个元素,若是,则返回:否则即第一个k在前面,则右边界r左移,继续递归查找.对于最后一个k的查找思路类似. 代码: 思路二: 1 class Solution { 2 public: 3 int GetF

剑指offer 38 数字在排序数组中出现的次数

自己的写法 class Solution { public: int GetNumberOfK(vector<int> data ,int k) { int length = data.size(); if(length <= 0) return 0; for(int i = 0;i < length;i++){ } int index1 = GetFirst(data,k,0,length-1); int index2 = GetLast(data,k,0,length-1);

剑指offer系列41---数字在数组中出现的次数

[题目]统计一个数字在排序数组中出现的次数. 1 package com.exe9.offer; 2 3 /** 4 * [题目]统计一个数字在排序数组中出现的次数. 5 * @author WGS 6 * 7 */ 8 public class GetNumOfK { 9 public int getNumOfK(int[] arr,int target){ 10 if(arr==null || arr.length<=0) return -1; 11 int len=arr.length;

剑指Offer——数字在排序数组中出现的次数

1.题目描述 统计一个数字在排序数组中出现的次数. 2.代码实现 package com.baozi.offer; /** * 统计一个数字在排序数组中出现的次数. * * @author BaoZi * @create 2019-07-14-8:52 */ public class Offer26 { public static void main(String[] args) { Offer26 offer26 = new Offer26(); int[] array = new int[]

数字在排序数组中出现的次数(剑指offer)利用快排思想(O(logn))

数字在排序数组中出现的次数 参与人数:1216时间限制:1秒空间限制:32768K 通过比例:28.43% 最佳记录:0 ms|0K(来自 ) 题目描述 统计一个数字在排序数组中出现的次数. 题意:首先数组是个已经排列的有序递增序列!统计一个数出现的次数,相当于在有序的序列里插入一个数,那么我只要确定插入的位置,利用快排的思想,也可以说是二分,如果在数组中找到k,那么左右拓展边界就可以确定,该数在数组中出现的次数了. 一些特殊情况可以特判!比如k小于数组最小数,或者大于数组最大数: class

剑指offer 面试题38—数字在排序数组中出现的次数

题目: 统计一个数字在排序数组中出现的次数.例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4. 解法一:O(n) 顺序遍历 解法二:O(logn) 用二分查找,分别找出第一个3,和最后一个3的位置,然后计算个数. #include <stdio.h> int GetFirstK(int* data,int length,int k,int start,int end) { if(start > end) return -1; int m

剑指offer面试题38:数字在排序数组中出现的次数

题目描述: 统计一个数字在排序数组中出现的次数. 输入: 每个测试案例包括两行: 第一行有1个整数n,表示数组的大小.1<=n <= 10^6. 第二行有n个整数,表示数组元素,每个元素均为int. 第三行有1个整数m,表示接下来有m次查询.1<=m<=10^3. 下面有m行,每行有一个整数k,表示要查询的数. 输出: 对应每个测试案例,有m行输出,每行1整数,表示数组中该数字出现的次数. 样例输入: 81 2 3 3 3 3 4 513 样例输出: 4 //source:http

【剑指offer】面试题38:数字在排序数组中出现的次数

题目: 统计一个数字在排序数组中出现的次数. 思路: 对二分查找进行改进,找到数字在数组中第一次出现和最后一次出现的位置,这样就得到它出现的次数. 以找第一次出现的位置为例:如果mid元素大于k,则在前半段找:如果小于k,则在后半段找:如果等于k,则要看mid的前一个元素是不是k,如果是,则在前半段找,如果不是,则这就是第一次出现的位置. 时间复杂度O(logn). 代码: class Solution { public: int GetNumberOfK(vector<int> data ,