• [LeetCode] 1338. Reduce Array Size to The Half


    Given an array arr.  You can choose a set of integers and remove all the occurrences of these integers in the array.

    Return the minimum size of the set so that at least half of the integers of the array are removed.

    Example 1:

    Input: arr = [3,3,3,3,5,5,5,2,2,7]
    Output: 2
    Explanation: Choosing {3,7} will make the new array [5,5,5,2,2] which has size 5 (i.e equal to half of the size of the old array).
    Possible sets of size 2 are {3,5},{3,2},{5,2}.
    Choosing set {2,7} is not possible as it will make the new array [3,3,3,3,5,5,5] which has size greater than half of the size of the old array.
    

    Example 2:

    Input: arr = [7,7,7,7,7,7]
    Output: 1
    Explanation: The only possible set you can choose is {7}. This will make the new array empty.
    

    Example 3:

    Input: arr = [1,9]
    Output: 1
    

    Example 4:

    Input: arr = [1000,1000,3,7]
    Output: 1
    

    Example 5:

    Input: arr = [1,2,3,4,5,6,7,8,9,10]
    Output: 5

    Constraints:

    • 1 <= arr.length <= 10^5
    • arr.length is even.
    • 1 <= arr[i] <= 10^5

    数组大小减半。

    给你一个整数数组 arr。你可以从中选出一个整数集合,并删除这些整数在数组中的每次出现。返回 至少 能删除数组中的一半整数的整数集合的最小大小。

    我这里提供两种思路,一种利用到priority queue,一种是counting sort。

    首先是priority queue的做法。既然是试图删除数组中的一些unique的元素,使得删除的元素数量尽量大,但是这个集合尽量小,那么我们就需要统计每个元素在input数组中的出现次数。这里我们用hashmap统计,统计好的结果我们存入一个以priority queue表示的最大堆,堆顶是出现次数最多的数字。这样每次堆顶元素弹出的时候,他的出现次数是当前最多的,这样才能尽快地删除数组中一半整数。

    时间O(nlogn)

    空间O(n)

    Java实现

     1 class Solution {
     2     public int minSetSize(int[] arr) {
     3         HashMap<Integer, Integer> map = new HashMap<>();
     4         for (int num : arr) {
     5             map.put(num, map.getOrDefault(num, 0) + 1);
     6         }
     7         PriorityQueue<Integer> queue = new PriorityQueue<>((a, b) -> b - a);
     8         for (int num : map.keySet()) {
     9             queue.offer(map.get(num));
    10         }
    11         int count = 0;
    12         int sum = 0;
    13         while (!queue.isEmpty()) {
    14             sum += queue.poll();
    15             count++;
    16             if (sum >= arr.length / 2) {
    17                 return count;
    18             }
    19         }
    20         return -1;
    21     }
    22 }

    第二种方法是counting sort。首先我们看一下数组中出现的最大元素是什么,记录为max。之后我们创建一个长度为max + 1的数组count,记录所有元素的出现次数,并在记录完毕之后对其排序。当这个count数组有序之后,我们从元素最大的地方开始统计,计算一下每个元素的出现次数,当统计到数组中一半整数为止。

    时间O(nlogn)

    空间O(n)

    Java实现

     1 class Solution {
     2     public int minSetSize(int[] arr) {
     3         int max = Integer.MIN_VALUE;
     4         for (int num : arr) {
     5             max = Math.max(max, num);
     6         }
     7 
     8         int[] count = new int[max + 1];
     9         for (int num : arr) {
    10             count[num]++;
    11         }
    12         Arrays.sort(count);
    13         int half = arr.length / 2;
    14         int res = 0;
    15         for (int i = count.length - 1; i >= 0; i--) {
    16             half -= count[i];
    17             res++;
    18             if (half <= 0) {
    19                 return res;
    20             }
    21         }
    22         return arr.length;
    23     }
    24 }

    LeetCode 题目总结 

  • 相关阅读:
    UVA 11859
    [OpenGL]OpenGL坐标系和坐标变换
    树状数组
    编程算法
    乞讨 间隔[a,b]在见面p^k*q*^m(k&gt;m)中数号码
    解析Android的 消息传递机制Handler
    Atitit.故障排除系列---php 计划网站数据库错误排除过程
    Remove Element
    [Angular Directive] Write a Structural Directive in Angular 2
    [Compose] 18. Maintaining structure whilst asyncing
  • 原文地址:https://www.cnblogs.com/cnoodle/p/14317110.html
Copyright © 2020-2023  润新知