完成一半题目

标签: 贪心 数组 哈希表 排序

难度: Easy

有 `N` 位扣友参加了微软与力扣举办了「以扣会友」线下活动。主办方提供了 `2*N` 道题目,整型数组 `questions` 中每个数字对应了每道题目所涉及的知识点类型。 若每位扣友选择不同的一题,请返回被选的 `N` 道题目至少包含多少种知识点类型。 **示例 1:** >输入:`questions = [2,1,6,2]` > >输出:`1` > >解释:有 2 位扣友在 4 道题目中选择 2 题。 > 可选择完成知识点类型为 2 的题目时,此时仅一种知识点类型 > 因此至少包含 1 种知识点类型。 **示例 2:** >输入:`questions = [1,5,1,3,4,5,2,5,3,3,8,6]` > >输出:`2` > >解释:有 6 位扣友在 12 道题目中选择题目,需要选择 6 题。 > 选择完成知识点类型为 3、5 的题目,因此至少包含 2 种知识点类型。 **提示:** - `questions.length == 2*n` - `2 <= questions.length <= 10^5` - `1 <= questions[i] <= 1000`

Submission

运行时间: 44 ms

内存: 25.9 MB

from collections import Counter

class Solution:
    def halfQuestions(self, questions: List[int]) -> int:
        # 人数
        n = len(questions) // 2
        
        # 知识点统计
        cnt = Counter(questions)
        cnt_list = sorted(cnt.values(), reverse=True)

        # 开始选
        result = 0
        for x in cnt_list:
            n -= x
            result += 1
            if n <= 0:
                break

        return result

Explain

题解的思路是首先统计每种知识点类型的题目数量,然后将这些数量排序。接着从数量最多的知识点类型开始选择题目,直到选中的题目数量达到或超过扣友人数的一半。算法的关键在于优先选择那些题目数量多的知识点类型,以尽可能减少所需的不同知识点类型数量。

时间复杂度: O(n log n)

空间复杂度: O(n)

from collections import Counter

class Solution:
    def halfQuestions(self, questions: List[int]) -> int:
        # 计算总的扣友数(需要选择的题目数)
        n = len(questions) // 2
        
        # 统计每个知识点类型出现的次数
        cnt = Counter(questions)
        # 将知识点类型按数量从大到小排序
        cnt_list = sorted(cnt.values(), reverse=True)
        
        # 初始化结果变量
        result = 0
        # 选题,直到选够n道题
        for x in cnt_list:
            n -= x
            result += 1
            if n <= 0:
                break
        
        return result

Explore

在这个算法中,排序步骤是关键,因为它确保了可以首先选择出现次数最多的知识点类型。这样做可以最大程度地减少所需选择的知识点类型数量达到题目要求的一半。如果不进行排序,算法可能会从出现次数少的知识点类型开始选择,从而导致最终选择的知识点类型数目增多,无法保证以最小的类型数量达到题目要求。因此,排序是优化解题策略的重要步骤,确保了算法的效率和符合题目要求的目标。

哈希表(在Python中通常是字典或Counter类)被用来统计知识点数量,因为它提供了快速的插入、查找和更新操作。这使得统计每种知识点类型的出现频率变得非常高效。相比之下,如果使用列表或数组,我们需要手动处理索引和可能的越界问题;如果使用树结构,虽然可以维护有序性,但在频繁更新操作中可能不如哈希表效率高。因此,哈希表是处理此类“元素计数”问题的最佳数据结构,提供了简洁和高效的解决方案。

题解中的算法总是寻找一个确保题目数量至少为扣友数一半的最小知识点类型组合。在一些情况下,可能存在多个不同的组合可以达到这个目标,尤其是当多个知识点类型的题目数量相近时。然而,题解算法通过优先选择题目数量最多的知识点类型,来确保所需类型数量最小。因此,尽管可能存在其他组合可以满足题目条件,题解提供的答案依然是最优的选择,即最小化涉及的知识点类型数量。