[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 };

 

转载于:https://www.cnblogs.com/zhizhiyu/p/10181635.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值