与128题类似的2007题 O(n)做法

2007. 从双倍数组中还原原数组

class Solution:
    def findOriginalArray(self, changed: List[int]) -> List[int]:

        cnt = Counter(changed)
        # 单独处理 0
        cnt0 = cnt.pop(0, 0)
        if cnt0 % 2:
            return []
        ans = [0] * (cnt0 // 2)

        for x in cnt:
            # 如果 x/2 在 cnt 中,则跳过
            if x % 2 == 0 and x // 2 in cnt:
                continue
            # 把 x, 2x, 4x, 8x, ... 全部配对
            while x in cnt:
                # 每次循环,把 cnt_x 个 x 和 cnt_x 个 2x 配对
                cnt_x = cnt[x]
                # 无法配对,至少要有 cnt_x 个 2x
                if cnt_x > cnt[x * 2]:
                    return []
                ans.extend([x] * cnt_x)
                if cnt_x < cnt[x * 2]:
                    # 还剩下一些 2x
                    cnt[x * 2] -= cnt_x
                    x *= 2
                else:
                    x *= 4
        return ans

解释: 此类问题可以分组 并且可以根据某些条件判断组别起始点,遍历Counter()的键,如果满足条件则从该键行进算法逻辑,如果不满足条件则跳过直到寻找到起始点。

128题思路也是如此,数组的每个序列都一定有一个起始点,如果遍历到某点,判断该点元素-1是否在Counter()中,如果在,那就不是起始点,如果不是就从该点出发判断。

分组的思想也体现在了2982题中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值