您的位置:首页 > 其它

lintcode--区间求和 I

2017-10-18 17:42 393 查看
给定一个整数数组(下标由 0 到 n-1,其中 n 表示数组的规模),以及一个查询列表。每一个查询列表有两个整数 [start, end] 。 对于每个查询,计算出数组中从下标 start 到 end 之间的数的总和,并返回在结果列表中。

样例

对于数组 [1,2,7,8,5],查询[(1,2),(0,4),(2,4)], 返回 [9,23,20]

思路分析:

这里首先看到的第一想法就是暴力法直接将其对应的范围之间的数加在一起,然后将添加进向量器中,但是这样时间会是个问题,果然程序运行到91%的时候,显示时间不够。然后根据注意事项提示,选择用线段树来进行计算,线段树的构造的时间复杂度是o(n),查找时间复杂度是log(n),这样时间就会减少很多。这里主要的函数只有两个一个是构造线段树,一个是查找线段树。构造的时候这里添加了一个sum成员存储某一段的值,构造是用递归的方法,如果是叶子结点就将其对应数组中的值赋给sum,如果不是叶子结点就将左右节点sum值的和赋给该节点的sum。这样就构造成功了。查找的时候,就按照上面建立线段树的过程查找也是利用递归,但是这里可能会有一点点不同,就是如果区间在某一个节点的两边,我们就需要将区间分为两段在进行查找。如果查找的范围线段树里刚好有就直接返回。如果没有就将其对应的不同线段的和加在一起就得到了查找的结果。

代码如下:

/**
* Definition of Interval:
* classs Interval {
*     int start, end;
*     Interval(int start, int end) {
*         this->start = start;
*         this->end = end;
*     }
*/

class SegmentTreeNode1{
public:
int start, end;
long long sum;
SegmentTreeNode1 *left, *right;
SegmentTreeNode1(int start, int end) {
this->start = start;
this->end = end;
this->sum = 0;
this->left = this->right = NULL;
}
};

class Solution {
public:
/*
* @param A: An integer list
* @param queries: An query list
* @return: The result list
*/
vector<long long> intervalSum(vector<int> &A, vector<Interval> &queries) {
// write your code here
vector<long long>res;

SegmentTreeNode1 *head=build(A,0,A.size()-1);

for(int i=0;i<queries.size();i++)
{
res.push_back(query(head,queries[i].start,queries[i].end));
}
return res;
}
//线段树的构建
SegmentTreeNode1 * build(vector<int> &A,int start, int end) {
// write your code here
SegmentTreeNode1 * head=new SegmentTreeNode1(start,end);

if(start==end)
{
head->sum=A[start];
return head;
}

head->left=build(A,start,(start+end)/2);
head->right=build(A,(start+end)/2+1,end);

head->sum=head->left->sum+head->right->sum;
return head;
}
//区间查找
long long query(SegmentTreeNode1 * root, int start, int end) {
// write your code here
if(!root)
return INT_MIN;
if(start==root->start&&end==root->end)
{
return root->sum;
}
int mid=(root->start+root->end)/2;

if(mid<start)
{
return query(root->right,start,end);
}
else if(end<mid+1)
{
return query(root->left,start,end);
}
else
{
return query(root->left,start,mid)+query(root->right,mid+1,end);
}
}

};


注意点:

返回值的范围一定要注意,因为这里返回值的类型是long long类型,所以记得将查找区间的结果的返回类型设为long long
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: