小R的子数组权值| 豆包MarsCode AI 刷题

45 阅读2分钟

问题描述

小R有一个长度为 n 的数组 a,她定义每个子区间 [l, r] 的权值为 a[l] | a[l+1] | ... | a[r],即该区间内所有元素的按位或运算结果。小R非常好奇,在这 n × (n + 1) / 2 个子区间中,究竟有多少种不同的权值。
她希望你能帮她计算一下,所有子区间中的不同权值总共有多少种。


测试样例

样例1:

输入:a = [1, 2, 4]
输出:6

样例2:

输入:a = [5, 3, 8, 1]
输出:8

样例3:

输入:a = [1, 1]
输出:1

样例4:

输入:a = [7, 8, 9, 10, 11]
输出:6

关键点:

  1. 按位或运算:按位或运算(|)是逐位进行的,只要有一个位为1,结果的对应位就为1。
  2. 子区间生成:对于长度为 n 的数组,子区间的数量是 n * (n + 1) / 2
  3. 去重:使用集合(set)来存储不同的权值,因为集合会自动去重。

解题思路

  1. 理解按位或运算:按位或运算(|)是逐位进行的,只要有一个位为1,结果的对应位就为1。
  2. 子区间的生成:对于长度为 n 的数组,子区间的数量是 n * (n + 1) / 2
  3. 计算每个子区间的权值:需要计算每个子区间的按位或运算结果。
  4. 去重:使用集合(set)来存储不同的权值,因为集合会自动去重。

代码分析

  • 使用集合来存储不同的权值
unique_values = set()
  • 遍历所有可能的子区间
for l in range(len(a)):
        # 初始化当前区间的按位或结果
        current_or = 0
        for r in range(l, len(a)):
            # 更新当前区间的按位或结果
            current_or |= a[r]
            # 将结果添加到集合中
            unique_values.add(current_or)
  • 返回集合的大小,即不同权值的数量
return len(unique_values)

完整代码演示

def solution(a):
    unique_values = set()
    
    for l in range(len(a)):
        current_or = 0
        for r in range(l, len(a)):
            current_or |= a[r]
            unique_values.add(current_or)
    
    return len(unique_values)

关键步骤解释

  1. 初始化集合unique_values = set() 用于存储不同的权值。
  2. 两层循环:外层循环遍历区间的起始位置 l,内层循环遍历区间的结束位置 r
  3. 按位或运算current_or |= a[r] 更新当前区间的按位或结果。
  4. 添加到集合unique_values.add(current_or) 将结果添加到集合中。
  5. 返回结果return len(unique_values) 返回集合的大小,即不同权值的数量。

总结

通过遍历所有子区间并计算按位或结果,我们可以使用集合来去重并统计不同权值的数量。这个方法的时间复杂度为 O(n^2),适用于大多数情况。