“题目解析#209 | 豆包MarsCode AI 刷题”

94 阅读3分钟

题目解析:计算数组子区间的不同权值

在编程竞赛和算法学习中,处理区间问题常常会遇到求解子区间的一些特性。在本题中,我们的任务是计算出给定数组中所有可能子区间的不同权值。权值是通过对区间内所有元素进行按位或运算得到的。为了更好地理解这个问题,我们将从思路、具体实现、图解以及个人思考几个方面详细阐述。

一、问题理解

给定一个长度为 n 的数组 a,所有子区间 [l, r] 的权值定义为:

权值=a[l]∣a[l+1]∣...∣a[r]权值=a[l]∣a[l+1]∣...∣a[r]

我们需要计算出数组存在的所有不同权值的数量。

示例

假设数组 a = [1, 2, 3],我们可以列出其所有子区间以及对应的权值:

  • 子区间 [0, 0],权值为 1
  • 子区间 [0, 1],权值为 1 | 2 = 3
  • 子区间 [0, 2],权值为 1 | 2 | 3 = 3
  • 子区间 [1, 1],权值为 2
  • 子区间 [1, 2],权值为 2 | 3 = 3
  • 子区间 [2, 2],权值为 3

从中我们可以看到,权值集合为 {1, 2, 3},所以不同权值的数量为 3。

二、思路与实现

我们可以利用双重循环遍历所有子区间,并通过按位或运算来计算权值。由于权值是通过按位或得到的,这一过程可以在遍历的同时完成。每次更新当前的按位或值,并将其存入集合中,以确保权值的唯一性。最终,我们只需返回集合的大小。

以下是代码实现:

python

def solution(a):
    unique_values = set()  # 使用集合存储不同的权值
    n = len(a)

    for l in range(n):
        current_or = 0  # 初始化当前子区间的或值

        for r in range(l, n):
            current_or |= a[r]  # 更新当前的按位或值
            unique_values.add(current_or)  # 将当前按位或值加入集合

    return len(unique_values)  # 返回集合中不同值的数量

代码详解

  1. 初始化集合和变量

    • unique_values 是一个集合,用于存储所有不同的权值。
    • n 是数组的长度。
  2. 遍历每个子区间

    • 外层循环选择子区间的起点 l,内层循环选择终点 r。每次内层循环更新当前的按位或值。
  3. 更新按位或值

    • 每次将当前的数组元素 a[r] 与之前的 current_or 进行按位或运算。更新后的值代表当前子区间的权值。
  4. 将权值存入集合

    • 使用集合 unique_values ,可以自动去重,只存储不同的权值。
  5. 返回结果

    • 最后,返回集合的大小,即为不同权值的数量。

三、个人思考与分析

复杂度分析

该算法的时间复杂度为 O(n²),因为对于每一个可能的子区间,我们都进行了一次 O(n) 的按位或运算。在最坏的情况下,空间复杂度为 O(n),那是因为我们可能会存储所有可能的权值。

优化思考

此算法在实际数组长度较小的情况下非常有效。同时,我们观察到由于按位或具有幂等性(a | a = a),并且对于相同的 l,随着 r 的增加,current_or 的值只可能增加或者保持不变,这意味着我们不需要对已经计算过的情况重复遍历。

一个可能的优化方向是:利用滑动窗口技术或其他数据结构(如线段树),以期在较大的数据范围内减少运算量。然而,考虑到按位运算的特性和实际使用场景,现有的 O(n²) 实现能够满足大多数需求。

在后续的学习和实践中,我将继续探索更多关于区间问题的解法和优化技巧,并尝试将具体实现与相关数据结构的应用结合起来,提升我的编程能力和解题思维。