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

题目:

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

思路:

1、顺序遍历

顺序扫描一遍数组,统计该数字出现的次数。

时间复杂度:O(n)

2、二分查找

假设我们需要找的数字是k,那么就需要找到数组中的第一个k和最后一个k出现的位置。

如何通过二分查找得到第一个k的位置呢?

取数组中间的数字与k作比较,

如果该数字比k大,那么k只能出现在前半部分,那么下一轮只能在前半部分找;

如果该数字比k小,那么k只能出现在后半部分,那么下一轮只能在后半部分找;

如果该数字等于k,需要判断这是不是第一个k,如果该数字的前一个数字不是k,那么该数字就是第一个k,否则需要在前半部分继续寻找第一个k;

寻找最后一个k的方法与寻找第一个k的方法一样。

代码:

#include <iostream>

using namespace std;

int getFirstK(int* data,int k,int start,int end){
    while(start<=end){
        int mid=start+((end-start)>>1);
        if(data[mid]==k){
            if((mid>0 && data[mid-1]!=k) || mid==0)
                return mid;
            else
                end=mid-1;
        }
        else if(data[mid]>k)
            end=mid-1;
        else
            start=mid+1;
    }
    return -1;
}

int getLastK(int* data,int length,int k,int start,int end){
    while(start<=end){
        int mid=start+((end-start)>>1);
        if(data[mid]==k){
            if((mid<length-1 && data[mid+1]!=k) || mid==length-1)
                return mid;
            else
                start=mid+1;
        }
        else if(data[mid]<k)
            start=mid+1;
        else
            end=mid-1;
    }
    return -1;
}

int getNumberOfK(int* data,int length,int k){
    if(data==NULL || length<=0)
        return 0;
    int first=getFirstK(data,k,0,length-1);
    int last=getLastK(data,length,k,0,length-1);
    cout<<first<<" "<<last<<endl;
    if(first!=-1 && last!=-1)
        return last-first+1;
    return 0;
}

int main()
{
    int A[]={1,2,3,3,3,3,4,5};
    int len=sizeof(A)/sizeof(A[0]);
    int k=3;
    cout << getNumberOfK(A,len,k) << endl;
    return 0;
}

在线测试OJ:

http://www.nowcoder.com/books/coding-interviews/70610bf967994b22bb1c26f9ae901fa2?rp=2

AC代码:

class Solution {
public:
    int GetNumberOfK(vector<int> data,int k) {
        int len=data.size();
        if(len<=0)
            return 0;
        int first=getFirstK(data,k,0,len-1);
        int last=getLastK(data,len,k,0,len-1);

        if(first!=-1 && last!=-1)
            return last-first+1;
        return 0;
    }

    int getFirstK(const vector<int> &data,int k,int start,int end){
        int mid;
        while(start<=end){
            mid=start+((end-start)>>1);
            if(data[mid]==k){
                if((mid>0 && data[mid-1]!=k) || mid==0)
                    return mid;
                else
                    end=mid-1;
            }
            else if(data[mid]>k)
                end=mid-1;
            else
                start=mid+1;
        }
        return -1;
    }

    int getLastK(const vector<int> &data,int length,int k,int start,int end){
        int mid;
        while(start<=end){
            mid=start+((end-start)>>1);
            if(data[mid]==k){
                if((mid<length-1 && data[mid+1]!=k) || mid==length-1)
                    return mid;
                else
                    start=mid+1;
            }
            else if(data[mid]>k)
                end=mid-1;
            else
                start=mid+1;
        }
        return -1;
    }
};
时间: 2024-08-09 23:09:49

(剑指Offer)面试题38:数字在排序数组中出现的次数的相关文章

剑指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 数字在排序数组中出现的次数

思路: 应该是用二分查找分别找到该数字第一次和最后一次出现的位置,相减即可.O(logn) int findLeft(int a[], int n, int num) { int l = 0, r = n - 1; while(l <= r) { int m = l + (r - l) / 2; if(a[m] == num) //与普通二分查找的区别在等于这里 { if(m == 0 || a[m - 1] != num) //如果这是第一个数字或者它前面的数字不是num那么这个位置就是第一个

剑指offer(二十七)之数字在排序数组中出现的次数

题目描述 统计一个数字在排序数组中出现的次数 我用了两种方法求解,思路都比较简单直接,看代码都懂了,就不做介绍啦 代码1: <span style="font-size:18px;">public class Solution { public int GetNumberOfK(int [] array , int k) { int num=0; for(int i=0;i<array.length;i++){ if(array[i]==k){ num++; } }

《剑指offer》:[38]数字在排序数组中出现的次数

"沟通.学习能力就是看面试者能否清晰.有条理地表达自己,是否会在自己所得到的信息不够的情况下主动发问澄清,能否在得到一些暗示之后迅速做出反应纠正错误"                                                                                                                   ---陈黎明(MSoft-SDE) 题目:统计一个数字在排序数组中出现的次数.例如输入排序数组{1,2,3,3

面试题38_数字在排序数组中出现的次数

题目描写叙述 统计一个数字在排序数组中出现的次数. 解题思路 数组是排序的,所以反复出现的数字是相邻排列的. 用二分查找算法,找到第一次出现的位置.和 最后一次出现的位置. 推断第一次出现的位置条件为:当前数字的前一个是否与之相等.若是则继续查找,否则该位置就是第一次出现的位置. 推断最后一次出现的位置条件为:当前数字的后一个是否与之相等,若是则继续查找,否则该位置就是最后一次出现的位置. 出现的次数= last - first +1 时间复杂度:O(logn) 实现代码 class Solut

面试题:数字在排序数组中出现的次数

题目描述:统计一个数字在排序数组中出现的次数. 代码: public class Solution { public int GetNumberOfK(int [] array , int k) { if(array.length==0||array==null) return 0; int count=0; for(int i=0;i<array.length;i++){ if(array[i]==k) count++; } return count; } } 原文地址:https://www

剑指Offer面试题:2.二维数组中的查找

一.题目:二维数组中的查找 题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 例如下面的二维数组就是每行.每列都递增排序.如果在这个数组中查找数字7,则返回true:如果查找数字5,由于数组不含有该数字,则返回false. 二.解题思路 首先选取数组中右上角的数字.如果该数字等于要查找的数字,查找过程结束:如果该数字大于要查找的数字,剔除这个数字所在的列:如果该数字小于要查

剑指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);

38.数字在排序数组中出现的次数

半段查找. int GetFirstK(int* data, int length, int k, int start, int end) { if (start > end) return -1; int middleIndex = (start + end) / 2; int middleData = data[middleIndex]; if (middleData == k) { if ((middleIndex > 0 && data[middleIndex - 1]

剑指offer——面试题38:数字在排序数组中出现的次数(利用二分查找来找第一次和最后一次的位置)

题目: 统计一个数字在排序数组中出现的次数. 思路: 因为是排好序的数组,所以可以采用二分查找的算法. 一般最容易想到的思路是采用二分查找先找到一个,然后往他左右两边遍历,但是这个方法由于在n个数组中还可能有n个k,所以 查找的复杂度还是O(n) 可以先用二分查找算法找到第一个出现的位置,即当找到一个时,看它前面一个是否也是k或者是否已经是查找这段的第一个了 然后同样用二分查找找最后一个出现的位置. 1 #include<iostream> 2 #include<vector> 3