307. Range Sum Query - Mutable | 307. 区域和检索 - 数组可修改(数据结构:线段树,图文详解)
题目
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. 区域和检索 - 数组可修改(数据结构:线段树,图文详解)相关推荐
- leetcode 303. Range Sum Query - Immutable | 303. 区域和检索 - 数组不可变(一维前缀和问题)
题目 https://leetcode.com/problems/range-sum-query-immutable/ 题解 标准的前缀和问题,简单题,不多说,直接上代码 import java.ut ...
- [LC] 307. Range Sum Query - Mutable
这一题比起来304https://blog.csdn.net/chaochen1407/article/details/86572593就难多了.这一题首先是一维数组,那题是二维的.但是这题加入了一个 ...
- 数据结构线段树介绍与笔试算法题-LeetCode 307. Range Sum Query - Mutable--Java解法
此文首发于我的个人博客:zhang0peter的个人博客 LeetCode题解文章分类:LeetCode题解文章集合 LeetCode 所有题目总结:LeetCode 所有题目总结 线段树(Segme ...
- LeetCode Range Sum Query - Mutable(树状数组、线段树)
问题:给出一个整数数组,求出数组从索引i到j范围内元素的总和.update(i,val)将下标i的数值更新为val 思路:第一种方式是直接根据定义,计算总和时直接计算从i到j的和 第二种方式是使用树状 ...
- C练题笔记之:Leetcode-307. 区域和检索 - 数组可修改
题目: 给你一个数组 nums ,请你完成两类查询. 其中一类查询要求 更新 数组 nums 下标对应的值 另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的n ...
- leetcode307. Range Sum Query - Mutable
题目要求 Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), incl ...
- LeetCode中等题之区域和检索 - 数组可修改
题目 给你一个数组 nums ,请你完成两类查询. 其中一类查询要求 更新 数组 nums 下标对应的值 另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nu ...
- leetcode 304. Range Sum Query 2D - Immutable |304. 二维区域和检索 - 矩阵不可变(二维前缀和问题)
题目 https://leetcode.com/problems/range-sum-query-2d-immutable/ 题解 本题是 medium 难度,二维前缀和问题.相似题目有: Easy: ...
- LeetCode 303. 区域和检索 - 数组不可变(前缀和)
1. 题目 给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点. 示例: 给定 nums = [-2, 0, 3, -5, 2, -1],求 ...
最新文章
- 二叉树类型笔试面试题大总结(含代码)
- 计算机二级c语言2010,全国计算机二级c语言2010历年真题及答案.doc
- .NET中的DES对称加密
- 手工查杀myplayer病毒
- Pandas DataFrame loc []访问一组行和列
- 单机环境下(双机或是分布式系统不用考虑这个问题),app_offline.htm是个不错的选择...
- android textview api,Android API中文文档TextView
- 高斯光束的简单matlab仿真
- table 表格如何设置单元格固定长度
- 微服务分布式构架开发实战PDF,阿里架构师推荐,快快收藏吧
- 固有的不可移植的特征之volatile限定符
- 数据库空间管理-学习笔记
- MATLAB弹出对话框的使用
- 沪铅上市十周年 “铅华”与本色尽显
- @Transactional子事务单独提交
- RAD0.1 RB.1/.2
- NBA篮球英语专业术语
- 完全卸载vscode
- 云计算与虚拟化技术核心是什么?
- C# 批量重命名文件
热门文章
- CodeForces - 1313C2 Skyscrapers (hard version)(单调栈+dp/分治)
- CodeForces - 618D Hamiltonian Spanning Tree(思维+贪心)
- 通过条件判断文本框是否隐藏_如何通过风速来判断高效过滤器是否达到更换要求...
- 安卓入门系列-04常见布局之LinearLayout(线性布局)
- linux安装tensorflow教程,Ubuntu 16.04 安装 TensorFlow(GPU支持)
- php 做积分策略,积分策略
- [PKUWC2018][loj2537]Minimax
- TIME_WAIT简介
- Shell break和continue命令
- 【Boost】boost库中thread多线程详解2——mutex与lock