[Leetcode] 第307题 区域和检索-数组可修改

Posted 龙场驿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Leetcode] 第307题 区域和检索-数组可修改相关的知识,希望对你有一定的参考价值。

参考博客:(LeetCode 307) Range Sum Query - Mutable(Segment Tree)

一、题目描述

给定一个整数数组  nums,求出数组从索引 到 j  (i ≤ j) 范围内元素的总和,包含 i,  j 两点。

update(i, val) 函数可以通过将下标为 的数值更新为 val,从而对数列进行修改。

示例:

Given nums = [1, 3, 5]

sumRange(0, 2) -> 9
update(1, 2)
sumRange(0, 2) -> 8

说明:

  1. 数组仅可以在 update 函数下进行修改。
  2. 你可以假设 update 函数与 sumRange 函数的调用次数是均匀分布的。

二、题目解析

像连续区间动态更新和查询这种问题,常常用线段树,树状数组等方法

很强大!!值得记录!

三、AC代码

 1 class NumArray {
 2 public:
 3     NumArray(vector<int> nums) {
 4         root = buildTree(nums, 0, nums.size() - 1);
 5     }
 6 
 7     void update(int i, int val) {
 8         update(root, i, val);
 9     }
10 
11     int sumRange(int i, int j) {
12         return sumRange(root, i, j);
13     }
14 private:
15     struct SegmentNode {
16         int start;
17         int end;
18         int sum;
19         SegmentNode* left;
20         SegmentNode* right;
21         SegmentNode(int start, int end) :start(start), end(end), sum(0) {}
22     };
23     SegmentNode *root;
24     SegmentNode* buildTree(vector<int>&nums, int start, int end) {//构建树
25         if (end < start)return NULL;
26         SegmentNode *node = new SegmentNode(start, end);
27         if (start == end) {
28             node->sum = nums[start];
29             return node;
30         }
31         int mid = start + (end - start) / 2;
32         node->left = buildTree(nums, start, mid);
33         node->right = buildTree(nums, mid + 1, end);
34         node->sum = node->left->sum + node->right->sum;
35         return node;
36     }
37     void update(SegmentNode *node, int pos, int val) {
38         if (node->start == node->end&&node->start == pos) {//叶子节点
39             node->sum = val;
40             return;
41         }
42         if (pos<node->start || pos>node->end)return;
43         int mid = node->start + (node->end - node->start) / 2;
44         if (pos <= mid) {
45             update(node->left, pos, val);//划分区间的时候,mid划分在左边
46         }
47         else {
48             update(node->right, pos, val);
49         }
50         node->sum = node->left->sum + node->right->sum;//更新sum
51     }
52     int sumRange(SegmentNode *node, int start, int end) {
53         if (node->start == start&&node->end == end) {
54             return node->sum;
55         }
56         int mid = node->start + (node->end - node->start)/2;
57         if (end <= mid)return sumRange(node->left, start, end);//左子树中包含结果
58         if (start > mid)return sumRange(node->right, start, end);//右子树中包含结果,注意没有等号
59         else return sumRange(node->left, start, mid) + sumRange(node->right, mid + 1, end);
60     }
61 };

 

以上是关于[Leetcode] 第307题 区域和检索-数组可修改的主要内容,如果未能解决你的问题,请参考以下文章

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

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

LeetCode 744. 寻找比目标字母大的最小字母 / 307. 区域和检索 - 数组可修改 / 762. 二进制表示中质数个计算置位

LeetCode307 区域和检索-数组可修改[线段树] HERODING的LeetCode之路

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

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