leetcode
leetcode 1801 ~ 1850
统计按位或能得到最大值的子集数目

统计按位或能得到最大值的子集数目

难度:

标签:

题目描述

代码结果

运行时间: 40 ms, 内存: 16.2 MB


/*
 * Solution approach using Java Streams:
 * 1. Calculate all possible OR values by generating subsets using bitwise operations.
 * 2. Use IntStream to iterate through all subset combinations.
 * 3. Use Collectors.groupingBy to count occurrences of each OR result and find the maximum.
 */
import java.util.*;
import java.util.stream.*;

public class SolutionStream {
    public int countMaxOrSubsets(int[] nums) {
        Map<Integer, Long> orCountMap = IntStream.range(1, 1 << nums.length)
            .map(i -> IntStream.range(0, nums.length)
                .filter(j -> (i & (1 << j)) != 0)
                .map(j -> nums[j])
                .reduce(0, (a, b) -> a | b))
            .boxed()
            .collect(Collectors.groupingBy(orValue -> orValue, Collectors.counting()));

        int maxOr = Collections.max(orCountMap.keySet());
        return orCountMap.get(maxOr).intValue();
    }
}

解释

方法:

这个题解的核心思路是使用动态规划的方式来解决问题。首先,通过对数组中所有元素进行按位或操作,计算出能够得到的最大值 xor_sum。接着,使用一个字典 c 来保存不同子集按位或结果的出现次数。遍历每个元素 x,将已经存在的按位或结果与新元素 x 进行按位或操作,并更新这些结果的计数。特别地,每个元素自身也被视为一个子集,因此每次遍历到新元素时,都将其按位或结果计数增加1。最后,返回字典 c 中按位或结果为 xor_sum 的子集数量。

时间复杂度:

O(n * 2^17 * log(n))

空间复杂度:

O(2^17)

代码细节讲解

🦆
在解题思路中,首先提到计算所有元素的按位或结果得到最大值,如何保证这个方法能准确无误地得到最大按位或值?
按位或操作具有累积性和非减性质,这意味着对任意整数进行按位或操作的结果只会增加或保持不变,不会减少。因此,在给定一组数时,对它们全部进行按位或操作,可以确保得到这组数能达到的最大按位或值。这是因为任何子集的按位或结果都不会超过全集的按位或结果。所以,通过reduce函数结合or_操作符逐个合并数组中的所有元素能准确无误地得到最大按位或值。
🦆
题解中提到使用动态规划的方式解决问题,但具体的动态规划状态定义是什么?
在这个问题中,动态规划的状态可以定义为在考虑到当前元素之前,每一个可能的按位或结果及其出现的次数。状态转移则是基于新加入的元素更新这些按位或结果。具体来说,对于每一个新元素x,我们考虑已有的所有按位或结果(由Counter字典c维护),将x与这些结果进行按位或操作,并更新这些新结果的计数。此外,元素x本身也被添加到字典中,作为新的结果。
🦆
为什么在遍历每个元素时,需要复制当前字典以避免在迭代过程中修改字典?具体的影响是什么?
在Python中,字典在迭代时不能修改(增加或删除键值对),因为这会影响迭代器的状态,可能导致运行时错误或不正确的行为。在本题解中,我们需要在迭代过程中基于当前按位或的结果生成新的结果并更新这些结果的计数。如果不复制当前字典,那么在迭代字典的同时修改字典(如添加新的按位或结果),将引发运行时错误。通过先复制字典项为列表,我们可以在遍历这个列表的同时,安全地修改原字典。
🦆
返回最大按位或结果的子集数量时,如何处理如果字典中不存在xor_sum的情况?
在代码实现中,如果字典c中不存在xor_sum,表示没有任何子集的按位或结果等于xor_sum。这种情况理论上不会发生,因为xor_sum是从所有元素的按位或中得到的最大值。但为了代码的健壮性,可以通过字典的get方法访问xor_sum的计数,如果不存在,则默认返回0。即,使用c.get(xor_sum, 0)可以安全地处理这种异常情况,确保总是返回一个整数结果。

相关问题