303. 区域和检索 - 数组不可变
- 区域和检索 - 数组不可变
给定一个整数数组 nums,处理以下类型的多个查询:
计算索引 left 和 right (包含 left 和 right)之间的 nums 元素的 和 ,其中 left <= right
实现 NumArray 类:
NumArray(int[] nums) 使用数组 nums 初始化对象
int sumRange(int i, int j) 返回数组 nums 中索引 left 和 right 之间的元素的 总和 ,包含 left 和 right 两点(也就是 nums[left] + nums[left + 1] + … + nums[right] )
示例 1:
输入:
[“NumArray”, “sumRange”, “sumRange”, “sumRange”]
[[[-2, 0, 3, -5, 2, -1]], [0, 2], [2, 5], [0, 5]]
输出:
[null, 1, -1, -3]
解释:
NumArray numArray = new NumArray([-2, 0, 3, -5, 2, -1]);
numArray.sumRange(0, 2); // return 1 ((-2) + 0 + 3)
numArray.sumRange(2, 5); // return -1 (3 + (-5) + 2 + (-1))
numArray.sumRange(0, 5); // return -3 ((-2) + 0 + 3 + (-5) + 2 + (-1))
提示:
1 <= nums.length <= 104
-105 <= nums[i] <= 105
0 <= i <= j < nums.length
最多调用 104 次 sumRange 方法
通过次数
294K
提交次数
371.8K
通过率
79.1%
这道题描述的有点复杂,其实想要我们的做的是在一段长度中,寻求任意一段区间的和
我们需要想办法处理这个数组让我们能够一次性得到和,降低算法复杂度
第一次我用了暴力解答,系统显示内部错误,戏剧性的是力扣今晚出bug了
嘀咕了下不可能简单成这样,后面我重新提交了优化后的解答,也就是此方法
发现之前暴力做的居然又显示过了,可能是之前cpu没有今日这么好,今日暴力也能过了
以前老电脑大概率是过不了的,但前缀和才是这道题想要我们学习的地方~
class NumArray {
public:
vector<int> nums_pre;
NumArray(vector<int>& nums)
{
nums_pre.resize(nums.size()); //此处记得扩大nums_pre的容量
nums_pre[0] = nums[0];
// 创建一个新数组储存num数组的前缀和
for(int i=1;i<nums.size();i++)
{
nums_pre[i] = nums_pre[i - 1] + nums[i];
//新数组第i位的数为旧数组前i位数相加的总和
}
}
int sumRange(int left, int right)
{
int sum = 0;
//有了前缀和数组,想要求两个位置间的总和,只需要用新数组right位置减去left位置
if(left==0)//特殊处理left为0的情况
{
sum = nums_pre[right];
}
else
{
sum = nums_pre[right] - nums_pre[left - 1];
//直接减掉一次就好了,大大降低了复杂度
}
return sum;
}
};
/**
* Your NumArray object will be instantiated and called as such:
* NumArray* obj = new NumArray(nums);
* int param_1 = obj->sumRange(left,right);
*/