当前位置: 首页 > news >正文

Vue3项目中的前缀和

文章目录

  • 一、为什么需要前缀和?
  • 二、前缀和核心原理
    • 1. 空间换时间的艺术
    • 2. 数学之美
  • 三、Vue3 中的实现
    • 1. Composition API 封装
    • 2. 在组件中使用
  • 四、应用场景
    • 1. 动态数据仪表盘
    • 2. 大数据量滚动加载
    • 3. 动态规划优化
  • 五、性能对比实测
  • 六、注意事项
    • 1. 索引偏移陷阱
    • 2. 动态更新处理
    • 3. 内存优化技巧
  • 七、总结

一、为什么需要前缀和?

在开发可视化仪表盘时会遇到这样的请求:

// 每秒更新 100,000 条交易数据的区间统计
const transactions = ref(new Array(100000).fill(0))

需要实时计算 [2000, 5000] 区间的交易总额,之间遍历会导致:

// 时间复杂度 O(n) 的暴力解法
function sumRange(start, end) {
  let sum = 0
  for (let i = start; i <= end; i++) {
    sum += transactions.value[i]
  }
  return sum // 每调用一次就遍历一次,性能灾难!
}

二、前缀和核心原理

前缀和(Prefix Sum)是一种预处理数组的技术,通过构建辅助数组快速计算原数组任意区间的和。
数学表达:
原数组:nums[0], nums[1], nums[2],…,nums[n - 1]
前缀和数组:preSum[0],preSum[1], preSum[2],…,preSum[n]
其中 preSum[i] = nums[0] + nums[1] + … + nums[i - 1]
构建过程:
初始化:preSum[0] = 0 (空数组的和)
递推公式:preSum[i] = preSum[i - 1] + nums[i - 1]
区间和计算:
计算区间[left, right]的和:
sum(nums[left…right]) = preSum[right + 1] - preSum[left]

1. 空间换时间的艺术

// 预处理阶段(O(n))
const preSum = reactive([])
preSum[0] = 0
for (let i = 1; i <= transactions.value.length; i++) {
  preSum[i] = preSum[i - 1] + transactions.value[i - 1]
}

// 查询阶段 (O(1)的复杂度)
function optimizedSum(start, end) {
  return preSum[end + 1] - preSum[start]
}

2. 数学之美

在这里插入图片描述

三、Vue3 中的实现

1. Composition API 封装

// usePrefixSum.ts
import { ref, reactive, watchEffect } from 'vue'

export function usePrefixSum(sourceArray: Ref<number[]>) {
  const preSum = reactive<number[]>([])

  watchEffect(() => {
    preSum.length = 0
    preSum.push(0)
    sourceArray.value.forEach((num, index) => {
      preSum[index + 1] = preSum[index] + num
    })
  })

  const getRangeSum = (start: number, end: number) => {
    return preSum[end + 1] - preSum[start]
  }

  return { preSum, getRangeSum }
}

2. 在组件中使用

<script setup lang="ts">
  import { ref, computed } from 'vue'
  import { usePrefixSum } form './usePrefixSum'
  const data = ref([10, 20, 30, 40, 50])
  const { getRangeSum } = usePrefixSum(data)

  // 实时响应式计算
  const currentSum = computed(() => getRangeSum(1, 3)) // 20 + 30 + 40 = 90
</script>

四、应用场景

1. 动态数据仪表盘

// 实时更新股票波动区间统计
watch(stockData, (newVal) => {
  data.value = newVal.map((item) => item.price)
})

2. 大数据量滚动加载

<template>
  <!-- 显示当前可视区域的数据总和 -->
  <div v-for="(chunk, i) in visibleChunks" :key="i">
    区块{{i}}总和:{{getRangeSum(...getChunkRange(i))}}
  </div>
</template>

3. 动态规划优化

// 最长子数组和问题优化
function maxSubArray(nums: number[]) {
  const preSum = [0]
  let minSum = 0
  let max = -Infinity
  nums.forEach((num, index) => {
    preSum[i + 1] = preSum[i] + num
    max = Math.max(max, preSum[i + 1] - minSum)
    minSum = Math.min(minSum, preSum[i + 1])
  })
  return max
}

五、性能对比实测

测试数据:100,000 个元素的数组

方法初始化耗时10万次查询总耗时
暴力求和0ms1250ms
前缀和15ms3ms

结论 ​​:在频繁查询场景下,前缀和的性能提升可达 400 倍!

六、注意事项

1. 索引偏移陷阱

记住 preSum[n]表示前 n 项和:

// 正确写法
sumRange(a,b) => preSum[b + 1] - preSum[a]

2. 动态更新处理

当原始数组变化时:

// 使用 watchEffect 自动重建前缀和
watchEffect(updatePreSum)

3. 内存优化技巧

对大数组使用 Int32Array:

const preSum = new Int32Array(data.length + 1)

七、总结

除了上述的应用场景外,我们还可以进行其他的扩展思考,比如说,差分数组:前缀和的逆运算,适合区间更新场景;树状数组:动态前缀和的更优解,支持单点修改等等。

相关文章:

  • C++ ------ 智能指针
  • 2025年常见渗透测试面试题-webshell免杀思路(题目+回答)
  • 抓包神器,自研EtherCAT抓包工具
  • Next.js/Nuxt.js 服务端渲染优化
  • 1.1 初识AI
  • C语言进阶之字符函数和字符串函数
  • AcWing 5972. 科学记数法
  • 【游戏安全】强制交互类风险
  • Magnet 库的技术架构与核心机制解析
  • Docker部署SpringBoot项目(完整版)
  • 重载“<<”操作符
  • 基于多通道降压稳压器的机器人关节供电系统设计
  • 人工智能day03
  • 设计模式总章
  • UE5 添加随机弹道
  • 【linux知识】web服务环境搭建(一):用户以及开发环境初始化
  • 有一个服务器能做什么?
  • 程序化广告行业(82/89):解锁行业术语,开启专业交流之门
  • 格瑞普Tattu正式成为2025年中国无人机竞速联赛官方赞助商!
  • 【家政平台开发(42)】筑牢家政平台安全防线:安全测试与漏洞修复指南
  • 30平米的无障碍酒吧里,我们将偏见折叠又摊开
  • 山东:小伙为救同学耽误考试属实,启用副题安排考试
  • 陕西河南山西等地将现“干热风”灾害,小麦产区如何防范?
  • 外交部亚洲司司长刘劲松会见印度驻华大使罗国栋
  • 习近平在中拉论坛第四届部长级会议开幕式的主旨讲话(全文)
  • 中央结算公司:减免境外央行类机构账户开户费用