📜  门| GATE CS 2010 |问题18(1)

📅  最后修改于: 2023-12-03 14:58:19.367000             🧑  作者: Mango

门 | GATE CS 2010 | 问题18

问题描述:

给定一个包含 n 个整数的数组 arr[],该数组按非降序排序。例如 -

arr = [1, 2, 3, 4, 4, 4, 4, 5, 6, 6, 7, 8, 8]

请实现一个函数,找到数字 x 在数组 arr 中出现的次数,并返回该次数。

函数签名:

def count_occurrences(arr: List[int], x: int) -> int:
    pass

输入:

  • 一个非降序排列的整数数组 arr
  • 一个整数 x

输出:

  • 返回数字 x 在数组 arr 中出现的次数
解题思路

由于数组 arr 是非降序排列的,我们可以使用二分查找找到数字 x 第一次出现的位置和最后一次出现的位置。

算法步骤:

  1. 初始化两个指针 lowhigh,分别指向数组的开始和结尾。
  2. 使用二分查找找到数字 x 第一次出现的位置 - 不断缩小搜索范围直到 arr[mid] 等于 x,并记录 mid。
  3. 使用二分查找找到数字 x 最后一次出现的位置 - 不断缩小搜索范围直到 arr[mid] 等于 x,并记录 mid。
  4. 如果找到了第一次和最后一次出现的位置,计算数字 x 出现的次数 count = (last - first + 1)
  5. 返回 count。
代码实现
from typing import List

def count_occurrences(arr: List[int], x: int) -> int:
    def find_first(arr: List[int], x: int) -> int:
        low = 0
        high = len(arr) - 1
        result = -1

        while low <= high:
            mid = (low + high) // 2

            if x == arr[mid]:
                result = mid
                high = mid - 1
            elif x < arr[mid]:
                high = mid - 1
            else:
                low = mid + 1

        return result

    def find_last(arr: List[int], x: int) -> int:
        low = 0
        high = len(arr) - 1
        result = -1

        while low <= high:
            mid = (low + high) // 2

            if x == arr[mid]:
                result = mid
                low = mid + 1
            elif x < arr[mid]:
                high = mid - 1
            else:
                low = mid + 1

        return result

    first = find_first(arr, x)
    last = find_last(arr, x)

    if first != -1 and last != -1:
        count = (last - first) + 1
        return count

    return 0
复杂度分析

时间复杂度:O(log n),其中 n 是数组 arr 的长度。因为使用了两次二分查找,每次查找的时间复杂度是 O(log n)。

空间复杂度:O(1),没有使用额外的空间。