zoukankan      html  css  js  c++  java
  • 【剑指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那么这个位置就是第一个num出现的位置
                    return m;
                else   //否则num在左半部分
                    r = m - 1;
            }
            else if(a[m] < num)
            {
                l = m + 1;
            }
            else
            {
                r = m - 1;
            }
        }
        return -1; //没找到
    }
    
    int findRight(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 == n - 1 || a[m + 1] != num) ////如果这是最后一个数字或者它后面的数字不是num那么这个位置就是最后一个num出现的位置
                    return m;
                else //否则 最后一个num在右半部分
                    l = m + 1;
            }
            else if(a[m] < num)
            {
                l = m + 1;
            }
            else
            {
                r = m - 1;
            }
        }
        return -1; //没找到
    }
    
    int times(int a[], int n, int num)
    {
        if(a == NULL) return 0;
        int l = findLeft(a, n, num);
        int r = findRight(a, n, num);
        return (l == -1 || r == -1) ? 0 : r - l + 1;
    }
    
    int main()
    {
        int a[10] = {1,2,3,3,3,3,4,5};
        int ans = times(a, 8, 5);
    
        return 0;
    }

    最开始写的是用普通二分查找找到一个指定数字再左右扩展,O(N)不好。

    //O(N)解法 不好
    int appearTimes(int a[], int n, int num)
    {
        int l = 0;
        int r = n - 1;
        int pos = -1; //找到的num的下标
        while(l <= r) //二分查找 找到一个num
        {
            int m = l + (r - l) / 2;
            if(a[m] == num)
            {
                pos = m;
                break;
            }
            else if(a[m] < num)
                l = m + 1;
            else
                r = m - 1;
        }
        if(pos == -1) //没有该数字
            return 0;
        
        l = r = pos;
        while(l >= 0 && a[l] == num) //找左边界
            l--;
        while(r < n && a[r] == num) //找右边界
            r++;
    
        return r - l - 1;
    }
  • 相关阅读:
    E
    J
    D
    并查集加优先队列
    动态规划-数位DPwindy
    动态规划-分组背包问题
    动态规划-LIS1
    动态规划-01背包
    [cf1434E]A Convex Game
    [atAGC106F]Figures
  • 原文地址:https://www.cnblogs.com/dplearning/p/4631308.html
Copyright © 2011-2022 走看看