题目:对一个数组重复的随机的找一段连续数据进行求和(query)以及重复的随机的改(updata)某一个位置处的值
第一种解法:再开一个数组,这个数组用来存和,图如下:
void Sum_arr(int *arr,int len1, int *sum_arr)
{
int i=0,j=0;
while(i < len1)
{
if(i == 0)
{
sum_arr[i] = arr[i];
i++;
}
sum_arr[i] = sum_arr[i-1] + arr[i];
i++;
}
}
第二种方法,就是把这个数组中的数用近似满二叉树的方式存起来
思想就是,这棵树的根存的是整个数组的和,即在存储的时候有因为数的特性我们将它们分开存储,树有左右子树,那么数组就从中间P开然后分别计算和
所以代码如下:时间复杂度O(lgn)
void build_tree(int *arr, int tree[], int node, int strat,int end)
{
if(strat == end)
{
tree[node] = arr[strat];
}
else
{
int mid = (strat + end) / 2;
int left_node = 2 * node + 1;
int right_node = 2 * node + 2;
build_tree(arr,tree,left_node,strat,mid);
build_tree(arr,tree,right_node,mid+1,end);
tree[node] = tree[left_node] + tree[right_node];
}
}
当更新某一个结点值的时候也采用类似的方法:更新完值之后要记得改arr和tree中的值
void update_tree(int *arr,int *tree,int node, int start,int end,int idx,int val) //将下标为idx处的值改为val
{
if(start == end)
{
arr[idx] = val;
tree[node] = val;
}
else
{
int mid = (start + end) / 2;
int left_node = 2 * node + 1;
int right_node = 2*node + 2;
if(idx >= start && idx <= mid)
{
update_tree(arr,tree,left_node,start,mid,idx,val);
}
else
{
update_tree(arr,tree,right_node,mid+1,end,idx,val);
}
tree[node] = tree[left_node] + tree[right_node];
}
}
思路:根据要改变的这个位置判断是在树的左边还是右边,然后沿着这条路径一直往下走直到找到这个结点,然后更改值,最后还需要把tree和arr中的值改过来
求某一段的和代码如下:时间复杂度:O(lgn)
int query_tree(int *arr, int *tree, int node, int start, int end, int L,int R)
{
if(R < start || L > end)
{
return 0;
}
else if(L <= start && end <= R)
{
return tree[node];
}
else if(start == end)
{
return tree[node];
}
else
{
int mid = (start + end) / 2;
int left_node = 2 * node + 1;
int right_node = 2 *node + 2;
int sum_left = query_tree(arr,tree,left_node,start,mid,L,R);
int sum_right = query_tree(arr,tree,right_node,mid+1,end,L,R);
return sum_left + sum_right;
}
}