LC-307.区域和检索-数组可修改

题目描述

leetcode 中等题

给你一个数组 nums ,请你完成两类查询。

  1. 其中一类查询要求 更新 数组 nums 下标对应的值
  2. 另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 ,其中 left <= right
    实现 NumArray 类:
  • NumArray(int[] nums) 用整数数组 nums 初始化对象
  • void update(int index, int val) 将 nums[index] 的值 更新 为 val
  • int sumRange(int left, int right) 返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 (即,nums[left] + nums[left + 1], …, nums[right])

示例1:

1
2
3
4
5
6
7
8
9
10
11
输入:
["NumArray", "sumRange", "update", "sumRange"]
[[[1, 3, 5]], [0, 2], [1, 2], [0, 2]]
输出:
[null, 9, null, 8]

解释:
NumArray numArray = new NumArray([1, 3, 5]);
numArray.sumRange(0, 2); // 返回 1 + 3 + 5 = 9
numArray.update(1, 2); // nums = [1,2,5]
numArray.sumRange(0, 2); // 返回 1 + 2 + 5 = 8

提示1:

1
2
3
4
5
6
1 <= nums.length <= 3 * 10^4
-100 <= nums[i] <= 100
0 <= index < nums.length
-100 <= val <= 100
0 <= left <= right < nums.length
调用 update 和 sumRange 方法次数不大于 3 * 10^4

树状数组

这是一道树状数组和线段树的模板题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class NumArray {
int[] org;
FenwickTree fenwickTree;

public NumArray(int[] nums) {
this.org = nums;
fenwickTree = new FenwickTree(org);
}

public void update(int index, int val) {
int delta = val - org[index];
org[index] = val;
fenwickTree.update(index + 1, delta);
}

public int sumRange(int left, int right) {
return fenwickTree.query(right + 1) - fenwickTree.query(left);
}
}

class FenwickTree{
int[] arr;
int size;

public FenwickTree(int size) {
arr = new int[size];
this.size = size;
}

public FenwickTree(int[] org) {
arr = new int[org.length + 1];
this.size = arr.length;
for (int i = 1; i < size; i++) {
update(i, org[i - 1]);
}
}

public void update(int index, int delta) {
while (index < size) {
arr[index] += delta;
index += lowBit(index);
}
}

public int query(int index) {
int sum = 0;
while (index > 0) {
sum += arr[index];
index -= lowBit(index);
}
return sum;
}

private int lowBit(int i) {
return i & -i;
}
}

线段树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
class NumArray {
int[] org;
SegTree segTree;

public NumArray(int[] nums) {
this.org = nums;
segTree = new SegTree(nums);
}

public void update(int index, int val) {
int delta = val - org[index];
org[index] = val;
segTree.update(index, index, delta, 0, org.length - 1, 1);
}

public int sumRange(int left, int right) {
return segTree.query(left, right, 0, org.length - 1, 1);
}
}

class SegTree {
int[] arr;
int[] lazyTag;
int[] org;

public SegTree(int[] org) {
this.org = org;
this.arr = new int[org.length * 4];
this.lazyTag = new int[org.length * 4];
build(0, org.length - 1, 1);
}

private void build(int s, int t, int p) {
if (s == t) {
arr[p] = org[s];
return;
}
int mid = s + (t - s >> 1);
build(s, mid, p * 2);
build(mid + 1, t, p * 2 + 1);
arr[p] = arr[p * 2] + arr[p * 2 + 1];
}

public void update(int l, int r, int c, int s, int t, int p){
if (l <= s && r >= t) {
arr[p] += (t - s + 1) * c;
lazyTag[p] += c;
return;
}
int mid = s + (t - s >> 1);
if (lazyTag[p] != 0) {
arr[p * 2] += (mid - s + 1) * lazyTag[p];
arr[p * 2 + 1] += (t - mid) * lazyTag[p];
lazyTag[p * 2] += lazyTag[p];
lazyTag[p * 2 + 1] += lazyTag[p];
lazyTag[p] = 0;
}
if (l <= mid) {
update(l, r, c, s, mid, p * 2);
}
if (r >= mid + 1) {
update(l, r, c, mid + 1, t, p * 2 + 1);
}
arr[p] = arr[p * 2] + arr[p * 2 + 1];
}

public int query(int l, int r, int s, int t, int p){
if (l <= s && r >= t) {
return arr[p];
}
int mid = s + (t - s >> 1);
if (lazyTag[p] != 0) {
arr[p * 2] += (mid - s + 1) * lazyTag[p];
arr[p * 2 + 1] += (t - mid) * lazyTag[p];
lazyTag[p * 2] += lazyTag[p];
lazyTag[p * 2 + 1] += lazyTag[p];
lazyTag[p] = 0;
}
int sum = 0;
if (l <= mid) {
sum += query(l, r, s, mid, p * 2);
}
if (r >= mid + 1) {
sum += query(l, r, mid + 1, t, p * 2 + 1);
}
return sum;
}

}

LC-307.区域和检索-数组可修改
https://wecgwm.github.io/2023/02/17/LC-307-区域和检索-数组可修改/
作者
yichen
发布于
2023年2月17日
许可协议