leetcode
leetcode 2501 ~ 2550
移除后集合的最多元素数

移除后集合的最多元素数

难度:

标签:

题目描述

You are given two 0-indexed integer arrays nums1 and nums2 of even length n.

You must remove n / 2 elements from nums1 and n / 2 elements from nums2. After the removals, you insert the remaining elements of nums1 and nums2 into a set s.

Return the maximum possible size of the set s.

 

Example 1:

Input: nums1 = [1,2,1,2], nums2 = [1,1,1,1]
Output: 2
Explanation: We remove two occurences of 1 from nums1 and nums2. After the removals, the arrays become equal to nums1 = [2,2] and nums2 = [1,1]. Therefore, s = {1,2}.
It can be shown that 2 is the maximum possible size of the set s after the removals.

Example 2:

Input: nums1 = [1,2,3,4,5,6], nums2 = [2,3,2,3,2,3]
Output: 5
Explanation: We remove 2, 3, and 6 from nums1, as well as 2 and two occurrences of 3 from nums2. After the removals, the arrays become equal to nums1 = [1,4,5] and nums2 = [2,3,2]. Therefore, s = {1,2,3,4,5}.
It can be shown that 5 is the maximum possible size of the set s after the removals.

Example 3:

Input: nums1 = [1,1,2,2,3,3], nums2 = [4,4,5,5,6,6]
Output: 6
Explanation: We remove 1, 2, and 3 from nums1, as well as 4, 5, and 6 from nums2. After the removals, the arrays become equal to nums1 = [1,2,3] and nums2 = [4,5,6]. Therefore, s = {1,2,3,4,5,6}.
It can be shown that 6 is the maximum possible size of the set s after the removals.

 

Constraints:

  • n == nums1.length == nums2.length
  • 1 <= n <= 2 * 104
  • n is even.
  • 1 <= nums1[i], nums2[i] <= 109

代码结果

运行时间: 50 ms, 内存: 25.4 MB


/*
题目思路:
1. 找出 nums1 和 nums2 中每个元素的出现次数。
2. 将两个数组合并成一个数组。
3. 按元素出现频率从低到高排序。
4. 移除频率最高的 n/2 个元素。
5. 返回剩余元素组成的集合的大小。
*/
import java.util.*;
import java.util.stream.*;
public class Solution {
    public int maxDistinctElements(int[] nums1, int[] nums2) {
        int n = nums1.length;
        Map<Integer, Long> freqMap = Stream.concat(Arrays.stream(nums1).boxed(), Arrays.stream(nums2).boxed())
                .collect(Collectors.groupingBy(e -> e, Collectors.counting()));
        List<Map.Entry<Integer, Long>> freqList = freqMap.entrySet().stream()
                .sorted(Map.Entry.comparingByValue())
                .collect(Collectors.toList());
        Set<Integer> resultSet = new HashSet<>();
        int toRemove = n;
        for (Map.Entry<Integer, Long> entry : freqList) {
            if (toRemove <= 0) break;
            toRemove -= entry.getValue();
        }
        freqList.stream()
                .filter(entry -> entry.getValue() <= toRemove)
                .forEach(entry -> resultSet.add(entry.getKey()));
        return resultSet.size();
    }
}

解释

方法:

首先,将nums1和nums2转换为集合set1和set2,以去除重复元素。然后,计算两个集合的交集大小(common)。接下来,计算每个集合的元素数量(n1和n2)。定义m为需要从每个数组中移除的元素数量(即n/2)。初始答案(ans)设置为n1 + n2 - common,代表了如果没有交集元素重叠,集合s能包含的最大元素数。接下来的逻辑是调整答案以考虑在移除元素时可能需要删除一些重复的元素。如果集合1的元素数n1大于m,那么可能需要从集合1中删除一些元素以满足移除要求,同时也可能需要从交集中减去一些重复的元素。同样的逻辑也适用于集合2。最终返回调整后的ans。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在算法中,为什么要先将nums1和nums2转换成集合set1和set2?
将nums1和nums2转换成集合set1和set2主要是为了去除各自数组中的重复元素。这样做不仅简化了后续的计算,因为集合不包含重复元素,而且使得计算两个数组的交集、并集等集合操作变得更加直接和高效。此外,这也有助于更准确地估计在移除一定数量元素后所能达到的最大不重复元素的数量。
🦆
算法中提到的‘初始答案设置为n1 + n2 - common’,为何要用这样的计算方式来确定初始可能的最大元素数量?
这种计算方式基于集合的基本理论。其中,n1和n2分别是集合set1和set2的元素数量,而common是这两个集合的交集元素数量。在不考虑任何元素移除的情况下,两个集合合并的总元素数为n1 + n2。然而,因为交集中的元素在两个集合中都出现过,所以被重复计算了一次,故需要从总数中减去这部分重复计算的元素数量(common),以得到合并后不重复的元素总数。这个计算提供了一个没有元素移除时的最大可能元素数量的初始估计。
🦆
如何确定集合1和集合2中需要删除的元素数量?算法中的逻辑是否确保了能够精确地达到最优解?
算法中,需要删除的元素数量基于每个集合的元素数量与m(即每个数组的一半长度)的比较来确定。如果一个集合的元素数量超过了m,那么就需要将集合的元素数量减少到m。算法尝试从交集中优先移除重复元素,以尽量减少对最大元素数量的影响。此逻辑确保了在给定的移除限制下,尽可能保留最多的不重复元素,但是否是绝对最优解可能需要更详细的分析或实际的例子来验证,因为复杂的交集和不同大小的集合可能影响最终的结果。
🦆
为什么在调整答案时需要从交集中减去重复的元素,其对应的逻辑是什么?
从交集中减去重复的元素是为了确保在满足移除要求的同时,最大化保留不同的元素。由于交集的元素在两个集合中都存在,如果不从交集中移除重复元素,那么这些元素在计算最终元素总数时会被重复计算。因此,通过减少交集的重复元素,可以更有效地利用每个集合独有的元素来增加最终集合的元素多样性。这一步骤是优化元素总数的关键,尤其是在有严格的元素移除限制时。

相关问题