一、题目描述:
leetcode 307. Range Sum Query - Mutable:给定一个数组nums和两种类型的查询,能在其中更新数组中索引的值,并检索数组中范围的和。
- 实现
NumArray类:NumArray(int[]nums)用整数数组nums初始化对象。 void update(int index,int val)将nums[index]的值更新为val。int sumRange(int left,int right)返回子数组nums[left,right](即nums[left]+nums[left+1],…,nums[right])之和。
二、思路分析:
1.类别
线段树
2.做题思路
这题可以说是线段树的模板题,关于查找和线段树见第四点。
三、AC 代码:
void buildTree(int *tree, vector<int> &nums, int left, int right, int node)
{
if (left == right)
tree[node] = nums[left];
else
{
int middle = (left + right) / 2;
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
buildTree(tree, nums, left, middle, left_node);
buildTree(tree, nums, middle + 1, right, right_node);
tree[node] = tree[left_node]+tree[right_node];
}
}
void updateTree(int i, int val, int left, int right, int node, int *tree)
{
if (left == right)
{
tree[node] = val;
return;
}
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
int middle = (left + right) / 2;
if (i <= middle && i >= left) //注意边界条件
updateTree(i, val, left, middle, left_node, tree);
else //if(i>middle && i<=right)
updateTree(i, val, middle + 1, right, right_node, tree);
tree[node] = tree[left_node] + tree[right_node];
}
int searchTree(int L, int R, int left, int right, int node, int *tree)
{
if (R < left || L > right)
return 0;
if (L <= left && R >= right)
return tree[node];
if (left == right)
return tree[node];
int middle = (left + right) / 2;
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
int leftpart = searchTree(L, R, left, middle, left_node, tree);
int rightpart = searchTree(L, R, middle + 1, right, right_node, tree);
return leftpart + rightpart;
}
class NumArray
{
public:
int tree[1000000];
int length=0;
NumArray(vector<int> &nums)
{
length = nums.size();
if(length!=0)
{
buildTree(tree, nums, 0, length - 1, 0);
for(int i=0;i<length;i++)
update(i,nums[i]);
}
}
void update(int i, int val)
{
updateTree(i, val, 0, length-1, 0, tree);
}
int sumRange(int i, int j)
{
int result = searchTree(i, j, 0, length-1, 0, tree);
return result;
}
};
四、总结
线段树
- 在各个节点保存一条线段(数组中的一段子数组)
- 用于高效解决连续区间的动态查询问题
- 基本能保持每个操作的复杂度为O(logN)。
线段树用于查询区间,查找单个点有以下几种方法:
1.动态查找方法
- 二叉排序树
- 二叉平衡树
2.静态查找方法
-
顺序查找
- 时间复杂度: O(N)
-
折半查找
- 必须采用顺序存储,不能用于链表
- 最坏情况 =平均情况=O(lgN)
- 查找不成功时,最多需要比较的次数不超过树的深度 为lgN(向下取整)+1
-
分块查找
- 分子表,块间有序,块内无序,这时候块间进行索引查找,块内进行顺序查找。
- O(lgN)和O(N)之间
-
散列结构
-
平均查找长度:每个关键字要查找的次数之和/关键字的个数
-
每个余数相同的树取对应的数组元素里面找
-
时间复杂度 O(1)
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情
-