Python leetcode 3020 子集中元素的最大数量,力扣练习,暴力枚举,字典counter使用

1.题目描述

给你一个 正整数 数组 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

2.题目解析与代码

首先要想满足题目条件,需要以下要求:

a. 中间的数是一个,其余的数是两个,总数为奇数

思路:

a.创建Counter字典统计nums的频率;

Counter() 是 collections 库中的一个函数,可以用来统计一个 python 列表、字符串、元组等可迭代对象中每个元素出现的次数,并返回一个字典。)

b.讨论nums中数值为1的情况,“cnt[1] - 1 | 1”的作用保证结果恒为奇数;

c.遍历count中的数值,对每个数值求x2,然后查询x2的频率是否大于等于2,这步变相检测x2是否在count字典中了;

d.最后在循环的每一步更新结果answer

代码:

class Solution:
    def maximumLength(self, nums: List[int]) -> int:
        cnt = Counter(nums)
        ans = cnt[1] - 1 | 1
        del cnt[1]
        for x in cnt:
            res = 0
            while cnt[x] > 1:
                res += 2
                x *= x
            ans = max(ans, res + (1 if x in cnt else -1))
        return ans

代码二,这个比较麻烦,但殊途同归:

class Solution:
    def maximumLength(self, nums: List[int]) -> int:
        # 特殊情况
        # [1, 1, 1, 1, 1]
        cnt = Counter(nums)
        # 只能是奇数个
        ans = cnt[1] % 2 + cnt[1] - 1 
        # 用一个字典保存 以 已经遍历到的数目开头能构成的数组长度
        dic = {}
        # 遍历到一个数时,如果想能继续增加长度,那么他的个数至少有2个,除非是山顶
        nums.sort(reverse=True)
        for v in nums:
            if v == 1:
                continue
            if cnt[v] == 1:
                dic[v] = 1
            else:
                if v**2 in dic:
                    dic[v] = dic[v**2] + 2
                else:
                    dic[v] = 1
        
        for v in dic.values():
            ans = max(ans, v)
        
        return ans

 

 

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

医学小达人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值