数字在升序数组中出现的次数(二分法)

数字在升序数组中出现的次数

http://www.nowcoder.com/practice/70610bf967994b22bb1c26f9ae901fa2

描述

题目描述

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

示例
输入:[1,2,3,3,3,3,4,5],3
返回值:4
引言

看到有序数组,就要立马想到用二分查找,一般都能解决问题并且优化时间复杂度

知识点:数组,二分法
难度:⭐⭐


题解

解题思路

二分查找法,获取目标值的前后下标,即获取目标值在数组中的长度

关键是运用微妙的 + 0.5 和 - 0.5,找出数组中第一个大于k和最后一个小于k的数的下标,相减就可以获得k在数组中的长度

方法一:二分法

图解

image-20210623135207020

算法流程:
  • 二分查找法,返回 num 在 arr 的第一个下标
  • 如果找不到目标值,则返回第一个大于目标值的数的下标
  • 通过浮点数,只需要找出数组中第一个大于k和最后一个小于k的数的下标,相减就可以获得k在数组中的长度
Java 版本代码如下:
public class Solution {
    public int GetNumberOfK(int [] array , int k) {
        // 通过浮点数,只需要找出数组中第一个大于k和最后一个小于k的数的下标
        // 相减就可以获得k在数组中的长度
        return helper(array, k + 0.5) - helper(array, k - 0.5);
    }

    // 找到num在arr的第一个下标
    int helper(int[] arr, double num) {
        // 二分法
        int lo = 0, hi = arr.length - 1;
        int mid = 0;
        // 该二分查找法,返回num在arr的第一个下标
        // 如果找不到目标值,则返回第一个大于目标值的数的下标
        while(lo <= hi) {
            // 这种写法可以避免整型相加时溢出
            mid = lo + ((hi - lo) >> 1);
            if(arr[mid] < num) {
                lo = mid + 1;
            } else if(arr[mid] > num) {
                hi = mid - 1;
            }
        }
        // 找到num在arr的第一个下标
        // 如果找不到目标值,则返回第一个大于目标值的数的下标
        return lo; 
    }
}
Python 版本代码如下:
class Solution:
    def GetNumberOfK(self, data, k):
        # write code here
        n = len(data)
        left, right = 0, n - 1
        while left <= right:
            mid = (left + right) // 2
            if data[mid] < k:
                left = mid + 1
            elif data[mid] > k:
                right = mid - 1
            else:
                right = mid - 1
        l = right
        left, right = 0, n - 1
        while left <= right:
            mid = (left + right) // 2
            if data[mid] < k:
                left = mid + 1
            elif data[mid] > k:
                right = mid - 1
            else:
                left = mid + 1
        r = left
        cur = r - l - 1
        return cur if cur > 0 else 0
复杂度分析:

时间复杂度 O(logN):二分法通常时间复杂度都是O(logN)
空间复杂度 O(1):只用到整数型的数据类型,常数项级别

总结:求解升序数组的题目一般都可以用二分法解决

方法二:暴力解法

算法流程:
  • 遍历、计数即可
Java 版本代码如下:
public class Solution {
    public int GetNumberOfK(int [] array , int k) {
        int count = 0;
        for(int a : array){
            if(k == a){
                count++;
            } 
        }
        return count;
    }
}
Python 版本代码如下:
# -*- coding:utf-8 -*-
class Solution:
    def GetNumberOfK(self, data, k):
        # write code here
        if not data:
            return 0
        return data.count(k)
复杂度分析:

时间复杂度 O(N):遍历数组,长度为 N
空间复杂度 O(1):只用到整型类型

全部评论

相关推荐

8 1 评论
分享
牛客网
牛客企业服务