Skip to content

Commit c7929ac

Browse files
committed
更新数据结构部分
1 parent 3c673c3 commit c7929ac

File tree

6 files changed

+439
-3
lines changed

6 files changed

+439
-3
lines changed

notes/data-structures-and-algorithms/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
https://leetcode-cn.com/problemset/all
2222

23-
- 牛客网-找工作神器|笔试题库|面试经验|实习招聘内推,求职就业一站解决_牛客网
23+
- 牛客网 - 找工作神器|笔试题库|面试经验|实习招聘内推,求职就业一站解决
2424

2525
https://www.nowcoder.com/
2626

55.9 KB
Loading
55.9 KB
Loading
55.9 KB
Loading
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
## [307. 区域和检索 - 数组可修改](https://leetcode-cn.com/problems/range-sum-query-mutable/)
2+
3+
给你一个数组 `nums` ,请你完成两类查询,其中一类查询要求更新数组下标对应的值,另一类查询要求返回数组中某个范围内元素的总和。
4+
5+
实现 `NumArray` 类:
6+
7+
- `NumArray(int[] nums)` 用整数数组 `nums` 初始化对象
8+
- `void update(int index, int val)``nums[index]` 的值更新为 `val`
9+
- `int sumRange(int left, int right)` 返回子数组 `nums[left, right]` 的总和(即,`nums[left] + nums[left + 1], ..., nums[right]`
10+
11+
12+
13+
**示例:**
14+
15+
```
16+
输入:
17+
["NumArray", "sumRange", "update", "sumRange"]
18+
[[[1, 3, 5]], [0, 2], [1, 2], [0, 2]]
19+
输出:
20+
[null, 9, null, 8]
21+
22+
解释:
23+
NumArray numArray = new NumArray([1, 3, 5]);
24+
numArray.sumRange(0, 2); // 返回 9 ,sum([1,3,5]) = 9
25+
numArray.update(1, 2); // nums = [1,2,5]
26+
numArray.sumRange(0, 2); // 返回 8 ,sum([1,2,5]) = 8
27+
```
28+
29+
30+
31+
**提示:**
32+
33+
- `1 <= nums.length <= 3 * 104`
34+
- `-100 <= nums[i] <= 100`
35+
- `0 <= index < nums.length`
36+
- `-100 <= val <= 100`
37+
- `0 <= left <= right < nums.length`
38+
- 最多调用 `3 * 104``update``sumRange` 方法
39+
40+
41+
42+
**提交代码:**
43+
44+
```java
45+
class NumArray {
46+
public class SegmentTree<E> {
47+
48+
private E[] tree;
49+
private E[] data;
50+
private Merger<E> merger;
51+
52+
public SegmentTree(E[] arr, Merger<E> merger){
53+
54+
this.merger = merger;
55+
56+
data = (E[])new Object[arr.length];
57+
for(int i = 0 ; i < arr.length ; i ++)
58+
data[i] = arr[i];
59+
60+
tree = (E[])new Object[4 * arr.length];
61+
buildSegmentTree(0, 0, arr.length - 1);
62+
}
63+
64+
// 在treeIndex的位置创建表示区间[l...r]的线段树
65+
private void buildSegmentTree(int treeIndex, int l, int r){
66+
67+
if(l == r){
68+
tree[treeIndex] = data[l];
69+
return;
70+
}
71+
72+
int leftTreeIndex = leftChild(treeIndex);
73+
int rightTreeIndex = rightChild(treeIndex);
74+
75+
// int mid = (l + r) / 2;
76+
int mid = l + (r - l) / 2;
77+
buildSegmentTree(leftTreeIndex, l, mid);
78+
buildSegmentTree(rightTreeIndex, mid + 1, r);
79+
80+
tree[treeIndex] = merger.merge(tree[leftTreeIndex], tree[rightTreeIndex]);
81+
}
82+
83+
public int getSize(){
84+
return data.length;
85+
}
86+
87+
public E get(int index){
88+
if(index < 0 || index >= data.length)
89+
throw new IllegalArgumentException("Index is illegal.");
90+
return data[index];
91+
}
92+
93+
// 返回完全二叉树的数组表示中,一个索引所表示的元素的左孩子节点的索引
94+
private int leftChild(int index){
95+
return 2*index + 1;
96+
}
97+
98+
// 返回完全二叉树的数组表示中,一个索引所表示的元素的右孩子节点的索引
99+
private int rightChild(int index){
100+
return 2*index + 2;
101+
}
102+
103+
// 返回区间[queryL, queryR]的值
104+
public E query(int queryL, int queryR){
105+
106+
if(queryL < 0 || queryL >= data.length ||
107+
queryR < 0 || queryR >= data.length || queryL > queryR)
108+
throw new IllegalArgumentException("Index is illegal.");
109+
110+
return query(0, 0, data.length - 1, queryL, queryR);
111+
}
112+
113+
// 在以treeIndex为根的线段树中[l...r]的范围里,搜索区间[queryL...queryR]的值
114+
private E query(int treeIndex, int l, int r, int queryL, int queryR){
115+
116+
if(l == queryL && r == queryR)
117+
return tree[treeIndex];
118+
119+
int mid = l + (r - l) / 2;
120+
// treeIndex的节点分为[l...mid]和[mid+1...r]两部分
121+
122+
int leftTreeIndex = leftChild(treeIndex);
123+
int rightTreeIndex = rightChild(treeIndex);
124+
if(queryL >= mid + 1)
125+
return query(rightTreeIndex, mid + 1, r, queryL, queryR);
126+
else if(queryR <= mid)
127+
return query(leftTreeIndex, l, mid, queryL, queryR);
128+
129+
E leftResult = query(leftTreeIndex, l, mid, queryL, mid);
130+
E rightResult = query(rightTreeIndex, mid + 1, r, mid + 1, queryR);
131+
return merger.merge(leftResult, rightResult);
132+
}
133+
134+
// 将index位置的值,更新为e
135+
public void set(int index, E e){
136+
137+
if(index < 0 || index >= data.length)
138+
throw new IllegalArgumentException("Index is illegal");
139+
140+
data[index] = e;
141+
set(0, 0, data.length - 1, index, e);
142+
}
143+
144+
// 在以treeIndex为根的线段树中更新index的值为e
145+
private void set(int treeIndex, int l, int r, int index, E e){
146+
147+
if(l == r){
148+
tree[treeIndex] = e;
149+
return;
150+
}
151+
152+
int mid = l + (r - l) / 2;
153+
// treeIndex的节点分为[l...mid]和[mid+1...r]两部分
154+
155+
int leftTreeIndex = leftChild(treeIndex);
156+
int rightTreeIndex = rightChild(treeIndex);
157+
if(index >= mid + 1)
158+
set(rightTreeIndex, mid + 1, r, index, e);
159+
else // index <= mid
160+
set(leftTreeIndex, l, mid, index, e);
161+
162+
tree[treeIndex] = merger.merge(tree[leftTreeIndex], tree[rightTreeIndex]);
163+
}
164+
165+
@Override
166+
public String toString(){
167+
StringBuilder res = new StringBuilder();
168+
res.append('[');
169+
for(int i = 0 ; i < tree.length ; i ++){
170+
if(tree[i] != null)
171+
res.append(tree[i]);
172+
else
173+
res.append("null");
174+
175+
if(i != tree.length - 1)
176+
res.append(", ");
177+
}
178+
res.append(']');
179+
return res.toString();
180+
}
181+
}
182+
183+
public interface Merger<E> {
184+
E merge(E a, E b);
185+
}
186+
187+
private SegmentTree<Integer> segTree;
188+
189+
public NumArray(int[] nums) {
190+
191+
if(nums.length != 0){
192+
Integer[] data = new Integer[nums.length];
193+
for(int i = 0 ; i < nums.length ; i ++)
194+
data[i] = nums[i];
195+
segTree = new SegmentTree<>(data, (a, b) -> a + b);
196+
}
197+
}
198+
199+
public void update(int i, int val) {
200+
if(segTree == null)
201+
throw new IllegalArgumentException("Error");
202+
segTree.set(i, val);
203+
}
204+
205+
public int sumRange(int i, int j) {
206+
if(segTree == null)
207+
throw new IllegalArgumentException("Error");
208+
return segTree.query(i, j);
209+
}
210+
}
211+
```

0 commit comments

Comments
 (0)