贪心题目:数组大小减半
2026/9/14 5:11:12 网站建设 项目流程

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:数组大小减半

出处:1338. 数组大小减半

难度

3 级

题目描述

要求

给定一个整数数组arr \texttt{arr}arr。可以从中选出一个整数集合,并删除这些整数在数组中的每次出现。

返回至少能删除数组中的一半整数的整数集合的最小元素个数。

示例

示例 1:

输入:arr = [3,3,3,3,5,5,5,2,2,7] \texttt{arr = [3,3,3,3,5,5,5,2,2,7]}arr = [3,3,3,3,5,5,5,2,2,7]
输出:2 \texttt{2}2
解释:选择{3,7} \texttt{\{3,7\}}{3,7}将数组变成[5,5,5,2,2] \texttt{[5,5,5,2,2]}[5,5,5,2,2],长度为5 \texttt{5}5(原数组长度的一半)。
大小为2 \texttt{2}2的可行集合有{3,5},{3,2},{5,2} \texttt{\{3,5\},\{3,2\},\{5,2\}}{3,5},{3,2},{5,2}
选择{2,7} \texttt{\{2,7\}}{2,7}是不可行的,将数组变成[3,3,3,3,5,5,5] \texttt{[3,3,3,3,5,5,5]}[3,3,3,3,5,5,5],其长度大于原数组的一半。

示例 2:

输入:arr = [7,7,7,7,7,7] \texttt{arr = [7,7,7,7,7,7]}arr = [7,7,7,7,7,7]
输出:1 \texttt{1}1
解释:只能选择集合{7} \texttt{\{7\}}{7},将数组变成空数组。

数据范围

  • 1 ≤ arr.length ≤ 10 5 \texttt{1} \le \texttt{arr.length} \le \texttt{10}^\texttt{5}1arr.length105
  • arr.length \texttt{arr.length}arr.length为偶数
  • 1 ≤ arr[i] ≤ 10 5 \texttt{1} \le \texttt{arr[i]} \le \texttt{10}^\texttt{5}1arr[i]105

解法

思路和算法

遍历数组arr \textit{arr}arr得到每个元素的出现次数,创建列表counts \textit{counts}counts存储每个元素的出现次数,则counts \textit{counts}counts中的元素之和为数组arr \textit{arr}arr的长度,问题转换成从counts \textit{counts}counts中选择最少的元素个数使得所选的元素之和至少为数组arr \textit{arr}arr的长度的一半。

根据贪心思想,在所选元素之和下界确定的情况下,为了使所选元素的个数最少,应从counts \textit{counts}counts按照从大到小的顺序依次选取元素,直到选取的元素之和至少为数组arr \textit{arr}arr的长度的一半,此时选取的元素个数即为从数组arr \textit{arr}arr中选出的集合的最小元素个数。

贪心思想的正确性说明如下。

假设从counts \textit{counts}counts按照从大到小的顺序选取元素时,至少选取x xx个元素可以满足选取的元素之和至少为数组arr \textit{arr}arr的长度的一半,用halfLength \textit{halfLength}halfLength表示数组arr \textit{arr}arr的长度的一半。如果将最大的x xx个元素中的任意一个元素换成更小的元素,则选取的元素之和将减小,此时选取的元素之和可能大于等于halfLength \textit{halfLength}halfLength也可能小于halfLength \textit{halfLength}halfLength,如果小于halfLength \textit{halfLength}halfLength,则需要选取更多元素才能满足选取的元素之和大于等于halfLength \textit{halfLength}halfLength,此时选取的元素个数大于x xx。因此按照从大到小的顺序选取元素可以使选取的元素个数最少。

具体做法是,得到列表counts \textit{counts}counts之后,将counts \textit{counts}counts按降序排序,然后按从大到小的顺序遍历counts \textit{counts}counts选取元素,直到选取的元素之和大于等于halfLength \textit{halfLength}halfLength时,返回选取的元素个数,即从数组arr \textit{arr}arr中选出的集合的最小元素个数。

代码

classSolution{publicintminSetSize(int[]arr){Map<Integer,Integer>countsMap=newHashMap<Integer,Integer>();for(intnum:arr){countsMap.put(num,countsMap.getOrDefault(num,0)+1);}List<Integer>counts=newArrayList<Integer>(countsMap.values());Collections.sort(counts,(a,b)->b-a);inthalfLength=arr.length/2;intremoveCount=0;intminSize=0;for(intcount:counts){removeCount+=count;minSize++;if(removeCount>=halfLength){break;}}returnminSize;}}

复杂度分析

  • 时间复杂度:O ( n log ⁡ n ) O(n \log n)O(nlogn),其中n nn是数组arr \textit{arr}arr的长度。计算每个元素的出现次数需要O ( n ) O(n)O(n)的时间,将出现次数列表排序需要O ( n log ⁡ n ) O(n \log n)O(nlogn)的时间,排序之后遍历出现次数列表需要O ( n ) O(n)O(n)的时间,因此时间复杂度是O ( n log ⁡ n ) O(n \log n)O(nlogn)

  • 空间复杂度:O ( n ) O(n)O(n),其中n nn是数组arr \textit{arr}arr的长度。哈希表和出现次数列表需要O ( n ) O(n)O(n)的空间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询