segment树(线段树)
2015-11-20 10:22
316 查看
线段树(segment tree)是一种Binary Search Tree或者叫做ordered binary tree。对于线段树中的每一个非叶子节点[a,b],它的左子树表示的区间为[a,(a+b)/2],右子树表示的区间为[(a+b)/2+1,b]。如下图:
[0-2]
/ \
[0-1] [2-2]
/ \
[0-0] [1-1]
下面看一道leetcode上的题,求动态区间的和(Range Sum Query - Mutable),题目如下:
分析如下:
一、构造线段树节点:
二、建立线段树(根据数组nums,建立一个动态区间求和的线段树):
三、线段树的更新(更新int数组下标i的值为val):
四、线段树的查询(查询int数组下标 i 到 j 的元素之和):
综上所述,上面Range Sum Query - Mutable的AC代码如下:
[0-2]
/ \
[0-1] [2-2]
/ \
[0-0] [1-1]
下面看一道leetcode上的题,求动态区间的和(Range Sum Query - Mutable),题目如下:
Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. The update(i, val) function modifies nums by updating the element at index i to val. Example: Given nums = [1, 3, 5] sumRange(0, 2) -> 9 update(1, 2) sumRange(0, 2) -> 8 Note: The array is only modifiable by the update function. You may assume the number of calls to update and sumRange function is distributed evenly
分析如下:
一、构造线段树节点:
class SegmentTreeNode { int start, end; int sum; SegmentTreeNode ltree, rtree; public SegmentTreeNode(int s, int e) { start = s; end = e; } }
二、建立线段树(根据数组nums,建立一个动态区间求和的线段树):
public SegmentTreeNode buildTree(int[] nums, int left, int right) { SegmentTreeNode root = new SegmentTreeNode(left, right); if (left == right) { root.sum = nums[left]; } else { int mid = left + (right - left)/2; root.ltree = buildTree(nums, left, mid); root.rtree = buildTree(nums, mid+1, right); root.sum = root.ltree.sum + root.rtree.sum; } return root; }
三、线段树的更新(更新int数组下标i的值为val):
private void update(SegmentTreeNode root, int i, int val) { if (root.start == root.end) { root.sum = val; } else { int mid = root.start + (root.end-root.start)/2; if (i <= mid) { update(root.ltree, i, val); } else { update(root.rtree, i, val); } root.sum = root.ltree.sum + root.rtree.sum; } }
四、线段树的查询(查询int数组下标 i 到 j 的元素之和):
private int sumRange(SegmentTreeNode root, int i, int j) { if (root.start == i && root.end == j) { return root.sum; } else { int mid = root.start + (root.end - root.start)/2; if (j <= mid) { return sumRange(root.ltree, i, j); } else if (i > mid) { return sumRange(root.rtree, i, j); } else { return sumRange(root.ltree, i, root.ltree.end) + sumRange(root.rtree, root.rtree.start, j); } } }
综上所述,上面Range Sum Query - Mutable的AC代码如下:
class SegmentTreeNode { int start, end; int sum; SegmentTreeNode ltree, rtree; public SegmentTreeNode(int s, int e) { start = s; end = e; } } public class NumArray { SegmentTreeNode root = null; public NumArray(int[] nums) { if(nums == null || nums.length == 0) { return; } root = buildTree(nums, 0, nums.length-1); } public SegmentTreeNode buildTree(int[] nums, int left, int right) { SegmentTreeNode root = new SegmentTreeNode(left, right); if (left == right) { root.sum = nums[left]; } else { int mid = left + (right - left)/2; root.ltree = buildTree(nums, left, mid); root.rtree = buildTree(nums, mid+1, right); root.sum = root.ltree.sum + root.rtree.sum; } return root; } void update(int i, int val) { update(root, i, val); } private void update(SegmentTreeNode root, int i, int val) { if (root.start == root.end) { root.sum = val; } else { int mid = root.start + (root.end-root.start)/2; if (i <= mid) { update(root.ltree, i, val); } else { update(root.rtree, i, val); } root.sum = root.ltree.sum + root.rtree.sum; } } public int sumRange(int i, int j) { return sumRange(root, i, j); } private int sumRange(SegmentTreeNode root, int i, int j) { if (root.start == i && root.end == j) { return root.sum; } else { int mid = root.start + (root.end - root.start)/2; if (j <= mid) { return sumRange(root.ltree, i, j); } else if (i > mid) { return sumRange(root.rtree, i, j); } else { return sumRange(root.ltree, i, root.ltree.end) + sumRange(root.rtree, root.rtree.start, j); } } } }
相关文章推荐
- select框默认样式去除(ie中隐藏默认下拉图标)
- Maven 与 IntelliJ IDEA 的完美结合
- FastDFS文件系统(一) fastdfs是什么?
- 话说“TCP长连接与短连接”
- Linux下USB suspend/resume源码分析【转】
- 周月季判断
- 将actionbar menu放下面
- Java最全文件操作实例汇总
- 工作中用到的英语汇总
- IO - 同步,异步,阻塞,非阻塞
- HttpClient 讲解 (3) 智能拼装
- Java中的static关键字解析
- php中var_export与var_dump的区别分析
- printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf - 输出格式转换函数
- GO方便的类型系统
- .xyz域名总量TOP12:西部数码域名激增 强势问鼎
- 距离传感器
- 继承、实现、依赖、关联、聚合、组合的联系与区别
- Android 最火框架XUtils之注解机制详解
- 科技进步,新型通信技术,改变工作环境