题目

https://leetcode.com/problems/range-sum-query-mutable/


吐槽官方题解

这题的 英文版官方题解,配图和代码不一致,而且描述不清;力扣国内版题解完全照搬英文的,机翻让人看不懂。

而且,答案里有一个我没有想明白的细节,就是当数组为奇数的时候,按照它的解法构造的树,就不是一个线段树了,而且 tree 数组节点个数为 n*2,它作为一棵满二叉树,节点个数本应为 n*2-1,空出第 0 个元素本来不应该有含义,但题解的代码却可以计算出一个确定的值,没有理解表示的是什么,而且这个值的正确与否会影响最终结果的正确性。

评论有人说,数组为奇数的情况下,构造出的是一组完全二叉树,但我还是没有懂。


总的来说,题解的代码没有问题(在一些我不懂的地方很巧妙),但细节比较 trick,无法理解是怎么运作的。

(当然也可能是因为我太菜,如果有明白的大佬,求多多指教~~)


线段树详解

官方题解看不懂,就另辟蹊径了。参考了灯神的视频:【数据结构】线段树(Segment Tree),然后关了视频自己实现了一遍,代码和他的过程有一些不同的地方(一方面是不完全记得视频的思路了,一方面是自己的想法对我来说更好懂一点),不过最后总算 AC 了。

1、构造线段树 construct


用空值填充剩余节点,使之成为完全二叉树

2、修改树中的元素 update

3、范围求和 sumRange


直接 return 0 的情况:需要计算的范围在当前查询的左右边界之外

4、代码

public class NumArray {int[] nums;int[] tree;public NumArray(int[] nums) {this.nums = nums;tree = new int[2 * 2 * 3 * 10000]; // tree数组长度的确定:变成完全二叉树是2倍,考虑最后一层可能有空余填充所以再乘个2倍construct(tree, nums, 0, 0, nums.length - 1);}public void construct(int[] tree, int[] nums, int index, int left, int right) {if (left == right) {tree[index] = nums[left];} else {int mid = (left + right) / 2;construct(tree, nums, 2 * index + 1, left, mid);construct(tree, nums, 2 * index + 2, mid + 1, right);tree[index] = tree[2 * index + 1] + tree[2 * index + 2];}}public void update(int index, int val) {// 找到原数组在线段树中对应的位置int left = 0;int right = nums.length - 1;int treeIndex = 0;while (left != right) {int mid = (left + right) / 2;if (index <= mid) { // 走左子树right = mid;treeIndex = treeIndex * 2 + 1;} else { // 走右子树left = mid + 1;treeIndex = treeIndex * 2 + 2;}}// 从下向上更新,类似于堆调整,只不过计算的是“差值”,这是与视频思路不一样的地方int dif = val - nums[index];while (treeIndex > 0) {tree[treeIndex] += dif;treeIndex = (treeIndex - 1) / 2;}tree[0] += dif;nums[index] = val; // 题目中一系列操作是累计的,所以别忘了改原数组。。}public int sumRange(int left, int right) {return sum(tree, 0, 0, nums.length - 1, left, right);}// 在线段树从begin到end的范围内,找left到right的累加和public int sum(int[] tree, int index, int begin, int end, int left, int right) {if (begin > right || end < left) return 0;if (begin == end || begin >= left && end <= right) return tree[index];int mid = (begin + end) / 2;return sum(tree, 2 * index + 1, begin, mid, left, right) +sum(tree, 2 * index + 2, mid + 1, end, left, right);}
}/*** Your NumArray object will be instantiated and called as such:* NumArray obj = new NumArray(nums);* obj.update(index,val);* int param_2 = obj.sumRange(left,right);*/

307. Range Sum Query - Mutable | 307. 区域和检索 - 数组可修改(数据结构:线段树,图文详解)相关推荐

  1. leetcode 303. Range Sum Query - Immutable | 303. 区域和检索 - 数组不可变(一维前缀和问题)

    题目 https://leetcode.com/problems/range-sum-query-immutable/ 题解 标准的前缀和问题,简单题,不多说,直接上代码 import java.ut ...

  2. [LC] 307. Range Sum Query - Mutable

    这一题比起来304https://blog.csdn.net/chaochen1407/article/details/86572593就难多了.这一题首先是一维数组,那题是二维的.但是这题加入了一个 ...

  3. 数据结构线段树介绍与笔试算法题-LeetCode 307. Range Sum Query - Mutable--Java解法

    此文首发于我的个人博客:zhang0peter的个人博客 LeetCode题解文章分类:LeetCode题解文章集合 LeetCode 所有题目总结:LeetCode 所有题目总结 线段树(Segme ...

  4. LeetCode Range Sum Query - Mutable(树状数组、线段树)

    问题:给出一个整数数组,求出数组从索引i到j范围内元素的总和.update(i,val)将下标i的数值更新为val 思路:第一种方式是直接根据定义,计算总和时直接计算从i到j的和 第二种方式是使用树状 ...

  5. C练题笔记之:Leetcode-307. 区域和检索 - 数组可修改

    题目: 给你一个数组 nums ,请你完成两类查询. 其中一类查询要求 更新 数组 nums 下标对应的值 另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的n ...

  6. leetcode307. Range Sum Query - Mutable

    题目要求 Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), incl ...

  7. LeetCode中等题之区域和检索 - 数组可修改

    题目 给你一个数组 nums ,请你完成两类查询. 其中一类查询要求 更新 数组 nums 下标对应的值 另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nu ...

  8. leetcode 304. Range Sum Query 2D - Immutable |304. 二维区域和检索 - 矩阵不可变(二维前缀和问题)

    题目 https://leetcode.com/problems/range-sum-query-2d-immutable/ 题解 本题是 medium 难度,二维前缀和问题.相似题目有: Easy: ...

  9. LeetCode 303. 区域和检索 - 数组不可变(前缀和)

    1. 题目 给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点. 示例: 给定 nums = [-2, 0, 3, -5, 2, -1],求 ...

最新文章

  1. 二叉树类型笔试面试题大总结(含代码)
  2. 计算机二级c语言2010,全国计算机二级c语言2010历年真题及答案.doc
  3. .NET中的DES对称加密
  4. 手工查杀myplayer病毒
  5. Pandas DataFrame loc []访问一组行和列
  6. 单机环境下(双机或是分布式系统不用考虑这个问题),app_offline.htm是个不错的选择...
  7. android textview api,Android API中文文档TextView
  8. 高斯光束的简单matlab仿真
  9. table 表格如何设置单元格固定长度
  10. 微服务分布式构架开发实战PDF,阿里架构师推荐,快快收藏吧
  11. 固有的不可移植的特征之volatile限定符
  12. 数据库空间管理-学习笔记
  13. MATLAB弹出对话框的使用
  14. 沪铅上市十周年 “铅华”与本色尽显
  15. @Transactional子事务单独提交
  16. RAD0.1 RB.1/.2
  17. NBA篮球英语专业术语
  18. 完全卸载vscode
  19. 云计算与虚拟化技术核心是什么?
  20. C# 批量重命名文件

热门文章

  1. CodeForces - 1313C2 Skyscrapers (hard version)(单调栈+dp/分治)
  2. CodeForces - 618D Hamiltonian Spanning Tree(思维+贪心)
  3. 通过条件判断文本框是否隐藏_如何通过风速来判断高效过滤器是否达到更换要求...
  4. 安卓入门系列-04常见布局之LinearLayout(线性布局)
  5. linux安装tensorflow教程,Ubuntu 16.04 安装 TensorFlow(GPU支持)
  6. php 做积分策略,积分策略
  7. [PKUWC2018][loj2537]Minimax
  8. TIME_WAIT简介
  9. Shell break和continue命令
  10. 【Boost】boost库中thread多线程详解2——mutex与lock