算法初探LeetCode-数组大小减半

251 阅读2分钟

LeetCode1338:数组大小减半

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

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

 

示例 1:

输入: arr = [3,3,3,3,5,5,5,2,2,7]
输出: 2
解释: 选择 {3,7} 使得结果数组为 [5,5,5,2,2]、长度为 5(原数组长度的一半)。
大小为 2 的可行集合有 {3,5},{3,2},{5,2}。
选择 {2,7} 是不可行的,它的结果数组为 [3,3,3,3,5,5,5],新数组长度大于原数组的二分之一。

示例 2:

输入: arr = [7,7,7,7,7,7]
输出: 1
解释: 我们只能选择集合 {7},结果数组为空。

提示:

  • 1<=arr.length<=1051 <= arr.length <= 10^5
  • arr.length 为偶数
  • 1<=arr[i]<=1051 <= arr[i] <= 10^5

思路分析

先使用哈希表对数组各个元素的数量进行统计,我们不关心数组各个元素具体是多少,只关心各个元素出现的次数,将次数存入一个数组ar中,对该数组进行排序。从大到小进行遍历,当移除的元素个数之和大于等于数组元素个数的一半时,即完成任务,返回移除数字的种数。

  • 1.用哈希映射map记录每个整数出现的数目
  • 2.再从哈希映射map中将整数的数目存入数组num中
  • 3.将数组num进行排序
  • 4.用原数组arr的数目不断减去最大的数目(用ans'每减一次记录一次),直至小于或等于原数组大小的一半返回ans即可

算法代码

public int minSetSize(int[] arr) {
    //哈希
    HashMap < Integer, Integer > map = new HashMap < > (); //记录各个整数出现的次数
    int len = arr.length;
    for (int i = 0; i < len; i++) {
        map.put(arr[i], map.getOrDefault(arr[i], 0) + 1);
    }
    int size = map.size();
    int[] num = new int[size];
    int f = 0;
    for (int n: map.values()) { //将各个整数的数目记录在num数组中
        num[f++] = n;
    }
    int ans = 0;
    Arrays.sort(num); //排序
    for (int i = size - 1; i >= 0; i--) { //从数目大的开始减(因为找最小·步数
        if (len > arr.length / 2) //目前数组数目仍大于一半
        {
            len -= num[i];
            ans++;
        } else break;
    }
    return ans;
}

结果详情

nxy1.png

算法复杂度

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)一起进步,一起成长!