📜  门| GATE-CS-2003 |第 77 题(1)

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

题目描述

给定一个由 $n$ 个正整数构成的序列 $a_1, a_2, \cdots, a_n$,一个长度为 $s$ 的区间的众数定义为出现次数大于 $\lfloor \frac{s}{2} \rfloor$ 的数。现在请你写一个程序,输出从左往右依次扫描每个长为 $w$ 的区间的众数。

输入格式

第一行包含两个正整数 $n$ 和 $w$,表示序列长度和区间长度。

第二行包含 $n$ 个整数,表示给定的序列。

输出格式

共输出 $n-w+1$ 行,每行一个整数,表示从左往右每个长为 $w$ 的区间的众数。

数据范围

$1 \leq n, w \leq 10^5$, $1 \leq a_i \leq 10^8$。

输入样例:
9 3
1 1 1 2 2 3 3 3 3
输出样例:
1
1
2
3
3
3
3

解题思路

题目要求求出每个长度为 $w$ 的区间的众数,不难想到用库函数及字典来解决问题。具体步骤如下:

  • 定义一个字典,记录当前区间中每个数字出现的次数。
  • 按照顺序遍历给定序列中的所有长度为 $w$ 的子区间,对于每个子区间进行以下操作:
    • 在字典中记录每个数字出现的次数。
    • 遍历字典,找到出现次数最大的数字,并检查它是否符合众数的定义。
    • 如果是众数,输出该数字。
    • 否则,输出子区间中的任意一个数字即可。
  • 返回所有长度为 $w$ 的子区间的众数。
代码实现
from collections import defaultdict

def majority_number(n, w, nums):
    nums_count = defaultdict(int)
    max_count = 0
    max_num = None
    res = []

    for i in range(n):
        # 记录当前区间内每个数字出现的次数
        num = nums[i]
        nums_count[num] += 1

        # 如果当前数字成为出现次数最大的数字,就更新 max_count 和 max_num
        if nums_count[num] > max_count:
            max_count = nums_count[num]
            max_num = num

        # 如果当前区间已经处理完了,就看看出现次数最大的数字是否符合众数的定义
        if i >= w - 1:
            if max_count > w // 2:
                res.append(max_num)
            else:
                res.append(next(iter(nums_count))))
                # 如果没有众数,就输出区间中的任意一个数

            # 将区间最左边的数字从字典中删除,准备处理下一个区间
            left_num = nums[i - w + 1]
            nums_count[left_num] -= 1
            if nums_count[left_num] == 0:
                del nums_count[left_num]

            max_count = 0
            max_num = None

    return res
时间复杂度分析
  • 该算法处理了所有长度为 $w$ 的子区间,每个子区间需要遍历一遍当前区间内的所有数字,时间复杂度为 $O(nw)$。
  • 除了遍历区间中的数字,该算法的空间复杂度主要由字典维护的每个数字出现次数的数量决定,最多有 $O(n)$ 个数字,因此空间复杂度为 $O(n)$。

相关资料

  • 众数的定义:在一个序列中出现次数最多的数被称为众数。