📌  相关文章
📜  国际空间研究组织 | ISRO CS 2011 |问题 15(1)

📅  最后修改于: 2023-12-03 15:23:02.870000             🧑  作者: Mango

ISRO CS 2011 - 问题 15

问题描述

给定一个数组A,包含N个正整数。定义以下函数:

f(x) = 数组A中所有小于等于x的数字的个数

写一个函数实现上述功能,并返回该数组的函数值。

函数签名
def count_numbers_less_than_or_equal_to_x(n: int, arr: list[int], x: int) -> int:
    pass
输入
  • 第一行为一个整数T,表示测试用例数量。
  • 对于每个测试用例,第一行为一个整数N,表示数组的大小。
  • 接下来一行包含N个整数,表示数组A。
  • 最后一行为一个整数X,表示要查找的数字。
输出
  • 对于每个测试用例,输出函数f(x)的值。
示例

输入:

2
5
1 2 4 5 8
4
4
1 2 2 2 3
2

输出:

3
4
解释

示例1: 数组A中小于等于4的数字有1、2、4,共3个。 示例2: 数组A中小于等于2的数字有1、2、2、2,共4个。

解题思路

最简单的方法是使用两个嵌套循环,寻找小于等于x的数字个数。时间复杂度是$O(N^2)$。但是,这种方法的时间复杂度较高,不建议使用。

更优秀的解法是先排序数组,然后使用二分查找寻找第一个大于x的数字的下标,该下标即为小于等于x的数字的个数。时间复杂度为$O(N\log N)$。

要注意一点的是,在使用二分查找时,如果数组里存在与x相等的数字,则需要返回与x相等的最后一个数字的下标,这是因为题目要求小于等于x的数字个数,而不是小于x的数字个数。

参考实现
def count_numbers_less_than_or_equal_to_x(n: int, arr: list[int], x: int) -> int:
    # 先对数组排序
    arr.sort()

    # 在排好序的数组中查找第一个大于x的数字的位置
    l, r = 0, n - 1
    while l <= r:
        mid = l + (r - l) // 2
        if arr[mid] > x:
            r = mid - 1
        else:
            l = mid + 1

    # 如果数组中存在与x相等的数字,则需要从后往前查找最后一个相等的数字的位置
    while r >= 0 and arr[r] == x:
        r -= 1

    return r + 1  # 返回小于等于x的数字的个数

该函数的时间复杂度为$O(N\log N)$,空间复杂度为$O(1)$。