Skip to content

Latest commit

 

History

History

3020.Find the Maximum Number of Elements in Subset

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 

English Version

题目描述

给你一个 正整数 数组 nums

你需要从数组中选出一个满足下述条件的子集

  • 你可以将选中的元素放置在一个下标从 0 开始的数组中,并使其遵循以下模式:[x, x2, x4, ..., xk/2, xk, xk/2, ..., x4, x2, x]注意k 可以是任何 非负 的 2 的幂)。例如,[2, 4, 16, 4, 2][3, 9, 3] 都符合这一模式,而 [2, 4, 8, 4, 2] 则不符合。

返回满足这些条件的子集中,元素数量的 最大值

 

示例 1:

输入:nums = [5,4,1,2,2]
输出:3
解释:选择子集 {4,2,2} ,将其放在数组 [2,4,2] 中,它遵循该模式,且 22 == 4 。因此答案是 3 。

示例 2:

输入:nums = [1,3,2,4]
输出:1
解释:选择子集 {1},将其放在数组 [1] 中,它遵循该模式。因此答案是 1 。注意我们也可以选择子集 {2} 、{4} 或 {3} ,可能存在多个子集都能得到相同的答案。

 

提示:

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

解法

方法一:哈希表 + 枚举

我们用一个哈希表 $cnt$ 记录数组 $nums$ 中每个元素出现的次数。对于每个元素 $x$,我们可以将其不断平方,直到其值在哈希表 $cnt$ 中的出现次数小于 $2$ 为止。此时,我们判断 $x$ 在哈希表 $cnt$ 中的出现次数是否为 $1$,如果是则说明 $x$ 仍然可以被选入子集中,否则我们需要从子集中删除一个元素,确保子集个数为奇数。然后我们更新答案。继续枚举下一个元素。

注意我们需要特殊处理 $x = 1$ 的情况。

时间复杂度 $O(n \times \log \log M)$,空间复杂度 $O(n)$。其中 $n$$M$ 分别是数组 $nums$ 的长度和数组 $nums$ 中的最大值。

class Solution:
    def maximumLength(self, nums: List[int]) -> int:
        cnt = Counter(nums)
        ans = cnt[1] - (cnt[1] % 2 ^ 1)
        del cnt[1]
        for x in cnt:
            t = 0
            while cnt[x] > 1:
                x = x * x
                t += 2
            t += 1 if cnt[x] else -1
            ans = max(ans, t)
        return ans
class Solution {
    public int maximumLength(int[] nums) {
        Map<Long, Integer> cnt = new HashMap<>();
        for (int x : nums) {
            cnt.merge((long) x, 1, Integer::sum);
        }
        Integer t = cnt.remove(1L);
        int ans = t == null ? 0 : t - (t % 2 ^ 1);
        for (long x : cnt.keySet()) {
            t = 0;
            while (cnt.getOrDefault(x, 0) > 1) {
                x = x * x;
                t += 2;
            }
            t += cnt.getOrDefault(x, -1);
            ans = Math.max(ans, t);
        }
        return ans;
    }
}
class Solution {
public:
    int maximumLength(vector<int>& nums) {
        unordered_map<long long, int> cnt;
        for (int x : nums) {
            ++cnt[x];
        }
        int ans = cnt[1] - (cnt[1] % 2 ^ 1);
        cnt.erase(1);
        for (auto [v, _] : cnt) {
            int t = 0;
            long long x = v;
            while (cnt.count(x) && cnt[x] > 1) {
                x = x * x;
                t += 2;
            }
            t += cnt.count(x) ? 1 : -1;
            ans = max(ans, t);
        }
        return ans;
    }
};
func maximumLength(nums []int) (ans int) {
	cnt := map[int]int{}
	for _, x := range nums {
		cnt[x]++
	}
	ans = cnt[1] - (cnt[1]%2 ^ 1)
	delete(cnt, 1)
	for x := range cnt {
		t := 0
		for cnt[x] > 1 {
			x = x * x
			t += 2
		}
		if cnt[x] > 0 {
			t += 1
		} else {
			t -= 1
		}
		ans = max(ans, t)
	}
	return
}
function maximumLength(nums: number[]): number {
    const cnt: Map<number, number> = new Map();
    for (const x of nums) {
        cnt.set(x, (cnt.get(x) ?? 0) + 1);
    }
    let ans = cnt.has(1) ? cnt.get(1)! - (cnt.get(1)! % 2 ^ 1) : 0;
    cnt.delete(1);
    for (let [x, _] of cnt) {
        let t = 0;
        while (cnt.has(x) && cnt.get(x)! > 1) {
            x = x * x;
            t += 2;
        }
        t += cnt.has(x) ? 1 : -1;
        ans = Math.max(ans, t);
    }
    return ans;
}