leetcode
leetcode 2701 ~ 2750
子集中元素的最大数量

子集中元素的最大数量

难度:

标签:

题目描述

You are given an array of positive integers nums.

You need to select a subset of nums which satisfies the following condition:

  • You can place the selected elements in a 0-indexed array such that it follows the pattern: [x, x2, x4, ..., xk/2, xk, xk/2, ..., x4, x2, x] (Note that k can be be any non-negative power of 2). For example, [2, 4, 16, 4, 2] and [3, 9, 3] follow the pattern while [2, 4, 8, 4, 2] does not.

Return the maximum number of elements in a subset that satisfies these conditions.

 

Example 1:

Input: nums = [5,4,1,2,2]
Output: 3
Explanation: We can select the subset {4,2,2}, which can be placed in the array as [2,4,2] which follows the pattern and 22 == 4. Hence the answer is 3.

Example 2:

Input: nums = [1,3,2,4]
Output: 1
Explanation: We can select the subset {1}, which can be placed in the array as [1] which follows the pattern. Hence the answer is 1. Note that we could have also selected the subsets {2}, {3}, or {4}, there may be multiple subsets which provide the same answer. 

 

Constraints:

  • 2 <= nums.length <= 105
  • 1 <= nums[i] <= 109

代码结果

运行时间: 131 ms, 内存: 28.2 MB


/*
题目思路:
1. 使用流处理,将数组排序。
2. 使用动态规划计算满足条件的最大子集长度。
3. dp[i] 表示以第 i 个数为结尾的满足条件的子集的最大长度。
4. 对于每个数,找到之前的数,如果其平方是当前数,则更新 dp 值。
5. 最终返回 dp 数组中的最大值。
*/

import java.util.*;
import java.util.stream.*;

public class Solution {
    public int longestSubset(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n];
        Arrays.fill(dp, 1);
        int[] sortedNums = Arrays.stream(nums).sorted().toArray();
        int maxLen = 1;
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if (sortedNums[i] == sortedNums[j] * sortedNums[j]) {
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
            maxLen = Math.max(maxLen, dp[i]);
        }
        return maxLen;
    }
}

解释

方法:

题解的核心思路是构建一个频率计数的哈希表,然后遍历每个数,尝试构建符合题意的数组。对于每个数k,尝试构建以k开始的序列[k, k^2, (k^2)^2, ...],直到当前的数x不在哈希表中或其计数小于等于1。对于特殊的数字1,由于任何数的0次方都是1,我们需要特别处理,最优的情况是使用所有的1构成[1, 1, ..., 1],长度为cnt[1](cnt为1的个数)。对于其他数字,每次迭代尝试计算以当前数字为基础能构成的最长序列的长度,并更新答案。

时间复杂度:

O(n loglogm)

空间复杂度:

O(n)

代码细节讲解

🦆
在构建哈希表时,你是如何处理数组中的重复元素的?
在构建哈希表时,我使用了Python的`Counter`类,这是`collections`模块中的一个特殊类,用于计数对象中元素的出现次数。当出现重复元素时,`Counter`会自动为每个元素维护一个计数器。因此,每次元素出现时,其对应的计数就会增加,从而有效地记录了每个数字出现的次数。这允许我们在后续的逻辑处理中方便地访问每个数字的频率,以决定如何构建目标序列。
🦆
为什么要特别处理数字1,而不是像处理其他数字一样进行平方序列的构建?
数字1需要特别处理,因为1的任何次幂都等于1,这与其他数字不同。如果按照其他数字的处理方式,即构建形如[k, k^2, (k^2)^2, ...]的序列,对1来说这个序列将会是[1, 1, 1, ...],实际上没有增长。因此,最优的处理方法是直接计算1出现的次数,构建一个仅包含1的数组,其长度等于1出现的次数。这种方法直接利用了1的这一特性,而不需要进入更复杂的平方序列构建过程。
🦆
在解析`k^2^2`和类似的高次幂时,你是如何确保计算的准确性,考虑到可能出现的整数溢出问题?
在处理如`k^2^2`这样的高次幂时,确实存在整数溢出的风险,尤其是在某些编程语言中。在Python中,整数类型是动态的,可以处理非常大的数而不会溢出,但这并不意味着没有性能问题。为了避免在实际应用中处理过大的数字,我的实现在每次计算高次幂时都会检查当前数字是否仍存在于哈希表中以及对应的计数是否大于1。如果这两个条件任何一个不满足,循环将停止。这样,我们可以在实际中限制序列的长度和数值的大小,避免不必要的计算和潜在的性能问题。

相关问题