Skip to content

Commit

Permalink
差分数组 review
Browse files Browse the repository at this point in the history
  • Loading branch information
yk committed Feb 21, 2024
1 parent 6441364 commit 51a0025
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 32 deletions.
11 changes: 8 additions & 3 deletions content/posts/algorithm/data structure/数组-前缀和数组.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@ categories: [algorithm]
核心思路:开辟新数组 `preSum[i]` 来存储原数组 `nums[0..i-1] `的累加和,`preSum[0] = 0`。这样,当求原数组区间和就比较容易了,区间 `[i..j]` 的和等于 `preSum[j+1] - preSum[i]` 的结果值。

```JavaScript
const preSum = [0]
preSum[i] = preSum[i - 1] + nums[i - 1]
// 查询
const preSum = [0] // 一般可使用虚拟 0 节点,来避免边界条件

for(let i = 0; i < arr.length; ++i) {
preSum[i + 1] = preSum[i] + nums[i] // 构建前缀和数组
}


// 查询 sum([i..j])
preSum[j + 1] - preSum[i]
```

Expand Down
70 changes: 41 additions & 29 deletions content/posts/algorithm/data structure/数组-差分数组.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,41 @@
---
title: '数组-差(cha)分数组'
date: 2023-02-19T16:02:32+08:00
lastmod: 2024-02-20
tags: [Array]
series: [data structure, trick]
categories: [algorithm]
---

> 前缀和数组是应对数组区间被频繁访问求和查询
> 差分数组是为了应对区间内元素的频繁加减修改。
> 前缀和数组 是应对数组区间被频繁访问求和查询
> 差分数组 是为了应对区间内元素的频繁加减修改
## 构造
## 概念

```JavaScript
const diff = [nums[0]]

diff[i] = nums[i] - nums[i - 1]
for(let i = 1; i < arr.length; ++i) {
diff[i] = nums[i] - nums[i - 1] // 构建差分数组
}
```

对区间 `[i..j]` 进行加减 val 操作只需要对差分数组 `diff[i] += val`, `diff[j+1] -= val` 最后依据差分数组进行还原即可
对区间 `[i..j]` 进行加减 val 操作只需要对差分数组 **`diff[i] += val`, `diff[j+1] -= val`** 进行更新,然后依据更新后的差分数组还原出最终数组即可

```JavaScript
nums[i] = diff[i] + nums[i - 1]
nums[0] = diff[0]
for(let i = 1; i < diff[i]; ++i) {
nums[i] = diff[i] + nums[i - 1]
}
```

### [370. 区间加法](https://leetcode.cn/problems/range-addition/)
原理也很简单:

- `diff[i] += val`,等于对 `[i...]` 之后的所有元素都加了 val
- `diff[j+1] -=val`,等于对 `[j+1...]` 之后的所有元素都减了 val

这样就使用了常数级的时间对区间 `[i..j]` 内的元素进行了修改,最后一次性还原即可。

### lc.370 区间加法 vip

假设你有一个长度为  n  的数组,初始情况下所有的数字均为  0,你将会被给出  k​​​​​​​ 个更新的操作。

Expand Down Expand Up @@ -71,20 +83,19 @@ var getModifiedArray = function (length, updates) {
* @return {boolean}
*/
var carPooling = function(trips, capacity) {
const diff = Array(10001).fill(0)
for(let i = 0; i < trips.length; ++i) {
const trip = trips[i]
const [num, start, end] = trip
diff[start] += num
if(end < 1001) diff[end] -= num // 注意乘客在车上的区间是 end - 1 差分数组 end - 1 + 1
// 1. 因为初始都为 0 所以差分数组也都为 0
// 2. 初始化差分数组的容量时,根据题意来即可,不用遍历
const diff = Array(1001).fill(0)
for(const [people, from, to] of trips) {
diff[from] += people
diff[to] -= people // 根据题意,乘客在车上的区间是 [form..to - 1],即需要变动的区间
}
const res = [diff[0]]
// 不要忘记判断第一个站台res[0]
if(res[0] > capacity) return false;

for(let i = 1; i < diff.length; ++i) {
res[i] = res[i-1] + diff[i]
if(res[i] > capacity) return false
if(diff[0] > capacity) return false
let arr = [diff[0]]
for(let i = 1; i < diff.length; ++i){
arr[i] = arr[i - 1] + diff[i]
if(arr[i] > capacity) return false
}
return true
};
Expand All @@ -99,17 +110,18 @@ var carPooling = function(trips, capacity) {
* @return {number[]}
*/
var corpFlightBookings = function(bookings, n) {
// 1. 初始化预定记录都为 0,所以差分数组也都为 0
// 2. 根据题意,需要变动的区间为 [first...last]
const diff = Array(n + 1).fill(0)
for(let i = 0; i < bookings.length; ++i) {
const travel = bookings[i]
const [start, end, num] = travel
diff[start] += num
if(end + 1 < diff.length) diff[end + 1] -= num
for(const [from, to, seat] of bookings) {
diff[from] += seat
console.log(diff, to + 1)
if(to + 1 < diff.length) diff[to + 1] -= seat // 确保 diff 的容量大小 不要越界影响后续还原时的计算
}
const res = [0]
for(let i = 1; i < diff.length; ++i) {
res[i] = diff[i] + res[i-1]
const ans = [diff[0]]
for(let i = 1; i < diff.length; ++i){
ans[i] = ans[i - 1] + diff[i]
}
return res.slice(1)
return ans.slice(1)
};
```

0 comments on commit 51a0025

Please sign in to comment.