在这里插入图片描述

前缀和与差分数组是数组操作中的基础技巧,通过预处理实现 O(1) 时间的区间查询和区间更新。前缀和与差分数组计算器提供这两个数组的自动计算、验证与应用示例,帮助理解其原理与工程应用。

本案例基于 Kotlin Multiplatform(KMP)与 OpenHarmony,实现了一个前缀和与差分数组计算器

  • 前缀和数组:O(1) 时间计算任意区间和,适合频繁区间查询。
  • 差分数组:O(1) 时间完成区间更新,适合批量区间修改。
  • 自动验证:从差分数组还原原数组,验证算法正确性。
  • 应用示例:展示区间求和与区间更新的实际应用。

一、问题背景与典型场景

典型场景:

  1. 区间求和查询:频繁查询数组某个区间的元素和,使用前缀和可优化到 O(1)。
  2. 区间批量更新:需要给某个区间的所有元素加上同一个值,使用差分数组可优化到 O(1)。
  3. 指标累加统计:在监控系统中,快速计算某个时间段的指标总和。
  4. 数据预处理:在算法竞赛与数据处理中,前缀和是常见的基础技巧。

优势:

  • 时间复杂度优化:区间查询/更新从 O(n) 优化到 O(1)。
  • 空间复杂度:仅需 O(n) 额外空间存储前缀和或差分数组。
  • 易于实现:算法简单,代码量少,易于理解和维护。
  • 应用广泛:在算法、数据分析、监控系统等领域广泛应用。

二、前缀和与差分数组原理拆解

1. 前缀和数组 (Prefix Sum)

定义:前缀和数组 prefixSum[i] 表示原数组从索引 0 到索引 i 的所有元素之和。

原数组: arr = [1, 3, 5, 7, 9, 11]
前缀和: prefixSum = [1, 4, 9, 16, 25, 36]

其中:
  prefixSum[0] = arr[0] = 1
  prefixSum[1] = arr[0] + arr[1] = 1 + 3 = 4
  prefixSum[2] = arr[0] + arr[1] + arr[2] = 1 + 3 + 5 = 9
  ...

构建方法

val prefixSum = mutableListOf<Double>()
var sum = 0.0
for (i in 0 until n) {
    sum += arr[i]
    prefixSum += sum
}

时间复杂度:O(n),空间复杂度:O(n)

区间求和

区间 [L, R] 的和 = prefixSum[R] - prefixSum[L-1](当 L=0 时为 prefixSum[R]

示例:求区间 [1, 3] 的和
  原数组: arr = [1, 3, 5, 7, 9, 11]
  区间 [1,3]: arr[1] + arr[2] + arr[3] = 3 + 5 + 7 = 15

  使用前缀和:
    prefixSum[3] = 16  (arr[0..3] 的和)
    prefixSum[0] = 1   (arr[0] 的和)
    区间 [1,3] 的和 = prefixSum[3] - prefixSum[0] = 16 - 1 = 15 ✓

复杂度对比

  • 朴素方法:每次区间查询 O(n),m 次查询 O(mn)
  • 前缀和方法:预处理 O(n),每次查询 O(1),m 次查询 O(n + m)
2. 差分数组 (Difference Array)

定义:差分数组 diff[i] 表示原数组相邻元素的差值。

原数组: arr = [1, 3, 5, 7, 9, 11]
差分数组: diff = [1, 2, 2, 2, 2, 2]

其中:
  diff[0] = arr[0] = 1
  diff[1] = arr[1] - arr[0] = 3 - 1 = 2
  diff[2] = arr[2] - arr[1] = 5 - 3 = 2
  ...

构建方法

val diff = mutableListOf<Double>()
diff += arr[0]
for (i in 1 until n) {
    diff += arr[i] - arr[i - 1]
}

时间复杂度:O(n),空间复杂度:O(n)

从差分数组还原原数组

还原过程:
  arr[0] = diff[0] = 1
  arr[1] = arr[0] + diff[1] = 1 + 2 = 3
  arr[2] = arr[1] + diff[2] = 3 + 2 = 5
  ...

区间更新

给区间 [L, R] 的所有元素加上值 c:

diff[L] += c
if (R + 1 < n) {
    diff[R + 1] -= c
}

然后从差分数组还原,即可得到更新后的数组。

示例:给区间 [1, 3] 的所有元素加上 5

  原数组: arr = [1, 3, 5, 7, 9, 11]
  差分数组: diff = [1, 2, 2, 2, 2, 2]

  更新操作:
    diff[1] += 5  → diff = [1, 7, 2, 2, 2, 2]
    diff[4] -= 5  → diff = [1, 7, 2, 2, -3, 2]

  还原数组:
    arr[0] = 1
    arr[1] = 1 + 7 = 8
    arr[2] = 8 + 2 = 10
    arr[3] = 10 + 2 = 12
    arr[4] = 12 + (-3) = 9
    arr[5] = 9 + 2 = 11

  结果: [1, 8, 10, 12, 9, 11]
  验证: 索引 1,2,3 的元素都增加了 5 ✓

复杂度对比

  • 朴素方法:每次区间更新 O(n),m 次更新 O(mn)
  • 差分数组方法:预处理 O(n),每次更新 O(1),m 次更新后还原 O(n),总复杂度 O(n + m)
3. 前缀和与差分数组的关系

前缀和与差分数组是互逆操作

  • 对原数组求前缀和,再对前缀和求差分,可还原原数组。
  • 对原数组求差分,再对差分求前缀和,也可还原原数组。

三、Kotlin 前缀和与差分数组引擎

1. 输入格式设计

统一文本输入:

series=1,3,5,7,9,11
  • series:数值序列,逗号/空格/分号分隔。
2. 核心算法实现 (prefixSumAndDifferenceCalculator)
@JsExport
fun prefixSumAndDifferenceCalculator(inputData: String): String {
    // 解析输入
    val values = mutableListOf<Double>()
    // ... 解析逻辑 ...
    
    // 计算前缀和数组
    val prefixSum = mutableListOf<Double>()
    var sum = 0.0
    for (i in 0 until n) {
        sum += values[i]
        prefixSum += sum
    }
    
    // 计算差分数组
    val diff = mutableListOf<Double>()
    diff += values[0]
    for (i in 1 until n) {
        diff += values[i] - values[i - 1]
    }
    
    // 从差分数组还原原数组(验证用)
    val restored = mutableListOf<Double>()
    restored += diff[0]
    for (i in 1 until n) {
        restored += restored[i - 1] + diff[i]
    }
    
    // 生成报告...
}

实现要点:

  • 前缀和计算:遍历数组累加,时间复杂度 O(n)。
  • 差分数组计算:计算相邻元素差值,时间复杂度 O(n)。
  • 还原验证:从差分数组还原原数组,验证算法正确性。
  • 应用示例:展示区间求和与区间更新的实际应用。
3. 输出格式

报告包含:

  1. 原始数组:完整的输入数据序列。
  2. 前缀和数组:每个位置的前缀和值。
  3. 差分数组:每个位置的差分值。
  4. 验证结果:从差分数组还原原数组,确认匹配。
  5. 应用示例
    • 快速区间求和示例
    • 快速区间更新示例
  6. 统计摘要:数组总和、平均值、最大值、最小值等。

示例输出:

🔢 前缀和与差分数组计算报告
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
数组长度: 6

📊 原始数组
索引: 0 | 1 | 2 | 3 | 4 | 5
数值: 1 | 3 | 5 | 7 | 9 | 11

📈 前缀和数组
定义: prefixSum[i] = sum(arr[0..i])
索引: 0 | 1 | 2 | 3 | 4 | 5
数值: 1 | 4 | 9 | 16 | 25 | 36

📉 差分数组
定义: diff[0] = arr[0], diff[i] = arr[i] - arr[i-1] (i>0)
索引: 0 | 1 | 2 | 3 | 4 | 5
数值: 1 | 2 | 2 | 2 | 2 | 2

✅ 验证:从差分数组还原原数组
匹配: ✓ 正确

💡 应用示例
1️⃣ 快速区间求和 [前缀和的应用]
   区间 [1, 3] 的和 = 15
   验证: 3 + 5 + 7 = 15

2️⃣ 快速区间更新 [差分数组的应用]
   给区间 [1, 3] 加上 5
   原数组: 1, 3, 5, 7, 9, 11
   更新后: 1, 8, 10, 12, 9, 11

四、ArkTS 前端布局与交互(pages/Index.ets

1. 布局设计

采用左右分栏布局,与之前的垂直堆叠布局形成对比:

  • 左侧输入区域
    • 绿色主题(#4CAF50)
    • 输入说明与格式示例
    • 文本输入框
    • 快速填充按钮(三个示例)
    • 执行按钮
    • 加载状态指示
  • 右侧结果区域
    • 计算结果展示
    • 可滚动文本区域
    • 空状态提示
2. 交互功能
  • 快速填充示例
    • “📋 示例1”:基础等差数列
    • “📋 示例2”:递增序列
    • “📋 示例3”:偶数序列
  • 实时执行:点击"🚀 开始计算"后,异步调用 Kotlin 函数并显示结果。
  • 状态反馈:加载中显示进度条,执行完成显示详细结果。
3. 调用方式
import { prefixSumAndDifferenceCalculator } from './hellokjs'

private executeCase() {
  this.isLoading = true
  setTimeout(() => {
    try {
      let output: string = prefixSumAndDifferenceCalculator(this.inputValue)
      this.result = output
    } catch (error) {
      this.result = `❌ 执行出错: ${error}`
    } finally {
      this.isLoading = false
    }
  }, 100)
}

布局改动侧重:

  • 左右分栏:输入与结果并排展示,提升空间利用率。
  • 绿色主题:采用绿色系(#4CAF50)作为主色调,与数学工具特性呼应。
  • 简洁设计:专注于核心功能,减少干扰元素。
  • 响应式布局:适配不同屏幕尺寸,左右栏可灵活调整。

五、工程化落地建议

  1. 前缀和应用场景

    • 区间求和查询:频繁查询数组区间和时,预处理前缀和数组。
    • 二维前缀和:扩展到二维数组,计算矩形区域和。
    • 指标累加:在监控系统中,快速计算某个时间段的指标总和。
  2. 差分数组应用场景

    • 区间批量更新:需要给某个区间的所有元素加上同一个值时使用。
    • 日程安排:在日程系统中,标记某个时间段的占用情况。
    • 资源分配:在资源管理中,标记某个时间段的资源使用。
  3. 性能优化

    • 对于固定数组,可预计算前缀和,支持 O(1) 查询。
    • 对于动态数组,使用树状数组或线段树维护前缀和。
  4. 扩展功能

    • 二维前缀和:扩展到二维数组,计算矩形区域和。
    • 前缀积:计算区间乘积(注意处理 0 和负数)。
    • 前缀异或:计算区间异或和。
  5. 错误处理

    • 空数组检查:数组长度至少为 1。
    • 数值验证:确保输入为有效数值。
    • 边界检查:区间索引不能越界。
  6. 可视化建议

    • 绘制原数组、前缀和数组、差分数组的对比图。
    • 标注区间查询/更新的范围,直观展示操作效果。
  7. 真实场景对接

    • 从监控系统提取时序数据。
    • 使用前缀和快速计算某个时间段的指标总和。
    • 使用差分数组批量更新指标值。

六、算法变种与应用

1. 二维前缀和

扩展到二维数组,计算矩形区域和:

// 构建二维前缀和
prefixSum[i][j] = sum of rectangle from (0,0) to (i,j)

// 查询矩形区域 [x1,y1] 到 [x2,y2] 的和
sum = prefixSum[x2][y2] - prefixSum[x1-1][y2] 
      - prefixSum[x2][y1-1] + prefixSum[x1-1][y1-1]
2. 前缀积

计算区间乘积(注意处理 0 和负数):

prefixProduct[i] = product of arr[0..i]
3. 前缀异或

计算区间异或和:

prefixXor[i] = xor of arr[0..i]
4. 应用场景扩展
  • 算法竞赛:区间查询与区间更新的经典技巧。
  • 数据分析:快速计算数据区间的统计值。
  • 监控系统:快速计算某个时间段的指标总和。
  • 资源管理:标记某个时间段的资源使用情况。

七、快速检查清单

  • 输入格式正确:series=数值序列
  • 数组长度验证:数组长度至少为 1。
  • 前缀和计算准确:prefixSum[i] = sum(arr[0..i])
  • 差分数组计算准确:diff[0] = arr[0], diff[i] = arr[i] - arr[i-1]
  • 还原验证通过:从差分数组还原原数组,确认匹配。
  • 区间求和示例正确:使用前缀和快速计算区间和。
  • 区间更新示例正确:使用差分数组快速完成区间更新。
  • 统计信息完整:提供数组总和、平均值、最大值、最小值等。
  • UI 布局清晰:左右分栏,绿色主题,信息流清晰。
  • 示例加载功能正常:快速填充预设测试数据。

八、总结

前缀和与差分数组计算器通过预处理实现了高效的区间操作,帮助我们:

  • 快速区间查询:使用前缀和实现 O(1) 时间的区间求和。
  • 快速区间更新:使用差分数组实现 O(1) 时间的区间批量更新。
  • 理解算法原理:通过可视化展示,深入理解前缀和与差分数组的关系。
  • 工程化应用:在算法、数据分析、监控系统等领域广泛应用。

结合 KMP 与 OpenHarmony,我们实现了轻量级的前缀和与差分数组计算器,为数组操作提供了有力的工具支持。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐