lintcode-线段树
来源:互联网 发布:网络直播需要什么设备 编辑:程序博客网 时间:2024/06/06 04:02
本文对线段树做总结,主要给出基本概念以及相应的实际问题。
主要参考了这篇博客[一步一步理解线段树]
基本概念
线段树
线段树,类似区间树,它在各个节点保存一条线段(数组中的一段子数组),主要用于高效解决连续区间的动态查询问题,由于二叉结构的特性,它基本能保持每个操作的复杂度为O(logn)。
线段树的每个节点表示一个区间,子节点则分别表示父节点的左右半区间,例如父亲的区间是[a,b],那么(c=(a+b)/2)左儿子的区间是[a,c],右儿子的区间是[c+1,b]。
例子
下面我们从一个经典的例子来了解线段树,问题描述如下:从数组arr[0…n-1]中查找某个数组某个区间内的最小值,其中数组大小固定,但是数组中的元素的值可以随时更新。
一般解法
对这个问题一个简单的解法是:遍历数组区间找到最小值,时间复杂度是O(n),额外的空间复杂度O(1)。当数据量特别大,而查询操作很频繁的时候,耗时可能会不满足需求。
另一种解法:
另一种解法:使用一个二维数组来保存提前计算好的区间[i,j]内的最小值,那么预处理时间为O(n^2),查询耗时O(1), 但是需要额外的O(n^2)空间,当数据量很大时,这个空间消耗是庞大的,而且当改变了数组中的某一个值时,更新二维数组中的最小值也很麻烦。
我们可以用线段树来解决这个问题:
复杂度如下:
- 预处理耗时O(n),因为对于含有N元素的线段树而言,大概要生成2n个节点。
- 查询、更新操作O(logn),这是优于O(N)的。
- 需要额外的空间O(n)
操作
创建线段树
题目:[创建线段树-I]
/** * Definition of SegmentTreeNode: * class SegmentTreeNode { * public: * int start, end; * SegmentTreeNode *left, *right; * SegmentTreeNode(int start, int end) { * this->start = start, this->end = end; * this->left = this->right = NULL; * } * } */class Solution {public: /** *@param start, end: Denote an segment / interval *@return: The root of Segment Tree */ SegmentTreeNode * build(int start, int end) { // write your code here if( start > end ) return NULL; SegmentTreeNode* root = new SegmentTreeNode( start, end ); if(start == end) return root; int mid = (start+end)/2; root->left = build( start, mid ); root->right = build( mid + 1, end ); return root; }};
题目:[创建线段树-II]
/** * Definition of SegmentTreeNode: * class SegmentTreeNode { * public: * int start, end, max; * SegmentTreeNode *left, *right; * SegmentTreeNode(int start, int end, int max) { * this->start = start; * this->end = end; * this->max = max; * this->left = this->right = NULL; * } * } */class Solution {public: /** *@param A: a list of integer *@return: The root of Segment Tree */ SegmentTreeNode * build(vector<int>& A) { // write your code here int sz = A.size(); if(!sz) return NULL; return build(A, 0, sz-1 ); }private: SegmentTreeNode* build(vector<int>& A, int start, int end ){ if(start > end) return NULL; SegmentTreeNode* root = new SegmentTreeNode(start, end, 0); if( start == end ){ root->max = A[start]; } else{ int mid = (start + end)/2; root->left = build(A, start, mid); root->right = build(A, mid+1, end); root->max = std::max( root->left->max, root->right->max ); } return root; }};
0 0
- lintcode-线段树
- LintCode:线段树的构造
- LintCode:线段树的查询
- LintCode:线段树的修改
- lintcode线段树的应用
- lintcode -- 线段树的构造
- 线段树的构造-LintCode
- 线段树的查询-LintCode
- 线段树的修改-LintCode
- 线段树查询 II-LintCode
- lintcode-线段树的构造-201
- lintcode-线段树的查询-202
- lintcode-线段树的修改-203
- lintcode-线段树查询II-247
- LintCode:线段树的构造 II
- LintCode:线段树的查询II
- lintcode(247)线段树查询 II
- 线段树的构造 II-LintCode
- readline的使用
- Netty实现简单网络通信
- LoadRunner性能测试初步认识
- jQuery中得到所有id为xxx开头的input
- 盈鹏飞嵌入式---【IMX6UL开发板试用体验】上手试用与资源使用
- lintcode-线段树
- Android 启动引导页面的实现
- C/C++ 混合编译之extern C的使用
- 实现Comparator接口为什么不用实现Equals方法
- python中文单字符处理
- GDB Quick Guide
- MATLAB图像压缩编码
- 浅析Android如何编译生成apk
- 新IT运维时代 | Docker运维之最佳实践-上篇