LeetCode 303 区域和检索 - 数组不可变
有勇气的牛排
30
算法
2025-08-09 22:17:41
题目
标签:设计、数组、前缀和
给定一个整数数组 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
方法
前缀和 方法
思路
-
先计算前缀和数组 prefix_num
,其中:
prefix[k]=nums[0]+nums[1]+...+nums[k−1]
注意:prefix_sum[0]=[0]
-
区间 [i, j]
的和可以通过公式快速得到:
sumRange(i,j)=prefixsum[j+1]−prefixsim[i]
案例
nums = [-2, 0, 3, -5, 2, -1]
prefix_sum = [0, -2, -2, 1, -4, -2, -3]
题目:
sumRange(2, 5)
= prefix_sum[6] - prefix_sum[2]
= (-3)-(-2)
= -1
时间复杂度:
空间复杂度:O(n)
python实现
class NumArray:
def __init__(self, nums):
self.prefix_sum = [0]
for num in nums:
self.prefix_sum.append(self.prefix_sum[-1] + num)
def sumRange(self, i, j):
return self.prefix_sum[j+1]-self.prefix_sum[i]
numArray = NumArray([-2, 0, 3, -5, 2, -1])
print(numArray.sumRange(0, 2))
print(numArray.sumRange(2, 5))
print(numArray.sumRange(0, 5))
<h2><a id="_0"></a>题目</h2>
<p>标签:设计、数组、前缀和</p>
<p>给定一个整数数组 <code>nums</code>,处理以下类型的多个查询:</p>
<ol>
<li>计算索引 <code>left</code> 和 <code>right</code> (包含 <code>left</code> 和 <code>right</code>)之间的 <code>nums</code> 元素的 <strong>和</strong> ,其中 <code>left <= right</code></li>
</ol>
<p>实现 <code>NumArray</code> 类:</p>
<ul>
<li><code>NumArray(int[] nums)</code> 使用数组 <code>nums</code> 初始化对象</li>
<li><code>int sumRange(int i, int j)</code> 返回数组 <code>nums</code> 中索引 <code>left</code> 和 <code>right</code> 之间的元素的 <strong>总和</strong> ,包含 <code>left</code> 和 <code>right</code> 两点(也就是 <code>nums[left] + nums[left + 1] + ... + nums[right]</code> )</li>
</ul>
<p><strong>示例 1:</strong></p>
<pre><div class="hljs"><code class="lang-Python">输入:
[<span class="hljs-string">"NumArray"</span>, <span class="hljs-string">"sumRange"</span>, <span class="hljs-string">"sumRange"</span>, <span class="hljs-string">"sumRange"</span>]
[[[-<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">3</span>, -<span class="hljs-number">5</span>, <span class="hljs-number">2</span>, -<span class="hljs-number">1</span>]], [<span class="hljs-number">0</span>, <span class="hljs-number">2</span>], [<span class="hljs-number">2</span>, <span class="hljs-number">5</span>], [<span class="hljs-number">0</span>, <span class="hljs-number">5</span>]]
输出:
[null, <span class="hljs-number">1</span>, -<span class="hljs-number">1</span>, -<span class="hljs-number">3</span>]
解释:
NumArray numArray = new NumArray([-<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">3</span>, -<span class="hljs-number">5</span>, <span class="hljs-number">2</span>, -<span class="hljs-number">1</span>]);
numArray.sumRange(<span class="hljs-number">0</span>, <span class="hljs-number">2</span>); // <span class="hljs-keyword">return</span> <span class="hljs-number">1</span> ((-<span class="hljs-number">2</span>) + <span class="hljs-number">0</span> + <span class="hljs-number">3</span>)
numArray.sumRange(<span class="hljs-number">2</span>, <span class="hljs-number">5</span>); // <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span> (<span class="hljs-number">3</span> + (-<span class="hljs-number">5</span>) + <span class="hljs-number">2</span> + (-<span class="hljs-number">1</span>))
numArray.sumRange(<span class="hljs-number">0</span>, <span class="hljs-number">5</span>); // <span class="hljs-keyword">return</span> -<span class="hljs-number">3</span> ((-<span class="hljs-number">2</span>) + <span class="hljs-number">0</span> + <span class="hljs-number">3</span> + (-<span class="hljs-number">5</span>) + <span class="hljs-number">2</span> + (-<span class="hljs-number">1</span>))
</code></div></pre>
<p><strong>提示:</strong></p>
<ul>
<li><code>1 <= nums.length <= 104</code></li>
<li><code>-105 <= nums[i] <= 105</code></li>
<li><code>0 <= i <= j < nums.length</code></li>
<li>最多调用 <code>104</code> 次 <code>sumRange</code> 方法</li>
</ul>
<h2><a id="__42"></a>前缀和 方法</h2>
<h3><a id="_44"></a>思路</h3>
<ol>
<li>
<p>先计算前缀和数组 <code>prefix_num</code>,其中:</p>
<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>p</mi><mi>r</mi><mi>e</mi><mi>f</mi><mi>i</mi><mi>x</mi><mo>[</mo><mi>k</mi><mo>]</mo><mo>=</mo><mi>n</mi><mi>u</mi><mi>m</mi><mi>s</mi><mo>[</mo><mn>0</mn><mo>]</mo><mo>+</mo><mi>n</mi><mi>u</mi><mi>m</mi><mi>s</mi><mo>[</mo><mn>1</mn><mo>]</mo><mo>+</mo><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mi mathvariant="normal">.</mi><mo>+</mo><mi>n</mi><mi>u</mi><mi>m</mi><mi>s</mi><mo>[</mo><mi>k</mi><mo>−</mo><mn>1</mn><mo>]</mo></mrow><annotation encoding="application/x-tex">prefix[k]=nums[0]+nums[1]+...+nums[k-1]
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="strut" style="height:0.75em;"></span><span class="strut bottom" style="height:1em;vertical-align:-0.25em;"></span><span class="base"><span class="mord mathit">p</span><span class="mord mathit" style="margin-right:0.02778em;">r</span><span class="mord mathit">e</span><span class="mord mathit" style="margin-right:0.10764em;">f</span><span class="mord mathit">i</span><span class="mord mathit">x</span><span class="mopen">[</span><span class="mord mathit" style="margin-right:0.03148em;">k</span><span class="mclose">]</span><span class="mrel">=</span><span class="mord mathit">n</span><span class="mord mathit">u</span><span class="mord mathit">m</span><span class="mord mathit">s</span><span class="mopen">[</span><span class="mord mathrm">0</span><span class="mclose">]</span><span class="mbin">+</span><span class="mord mathit">n</span><span class="mord mathit">u</span><span class="mord mathit">m</span><span class="mord mathit">s</span><span class="mopen">[</span><span class="mord mathrm">1</span><span class="mclose">]</span><span class="mbin">+</span><span class="mord mathrm">.</span><span class="mord mathrm">.</span><span class="mord mathrm">.</span><span class="mbin">+</span><span class="mord mathit">n</span><span class="mord mathit">u</span><span class="mord mathit">m</span><span class="mord mathit">s</span><span class="mopen">[</span><span class="mord mathit" style="margin-right:0.03148em;">k</span><span class="mbin">−</span><span class="mord mathrm">1</span><span class="mclose">]</span></span></span></span></span></p>
<p>注意:prefix_sum[0]=[0]</p>
</li>
<li>
<p>区间 <code>[i, j]</code> 的和可以通过公式快速得到:</p>
<p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>s</mi><mi>u</mi><mi>m</mi><mi>R</mi><mi>a</mi><mi>n</mi><mi>g</mi><mi>e</mi><mo>(</mo><mi>i</mi><mo separator="true">,</mo><mi>j</mi><mo>)</mo><mo>=</mo><mi>p</mi><mi>r</mi><mi>e</mi><mi>f</mi><mi>i</mi><msub><mi>x</mi><mi>s</mi></msub><mi>u</mi><mi>m</mi><mo>[</mo><mi>j</mi><mo>+</mo><mn>1</mn><mo>]</mo><mo>−</mo><mi>p</mi><mi>r</mi><mi>e</mi><mi>f</mi><mi>i</mi><msub><mi>x</mi><mi>s</mi></msub><mi>i</mi><mi>m</mi><mo>[</mo><mi>i</mi><mo>]</mo></mrow><annotation encoding="application/x-tex">sumRange(i, j) = prefix_sum[j+1]-prefix_sim[i]
</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="strut" style="height:0.75em;"></span><span class="strut bottom" style="height:1em;vertical-align:-0.25em;"></span><span class="base"><span class="mord mathit">s</span><span class="mord mathit">u</span><span class="mord mathit">m</span><span class="mord mathit" style="margin-right:0.00773em;">R</span><span class="mord mathit">a</span><span class="mord mathit">n</span><span class="mord mathit" style="margin-right:0.03588em;">g</span><span class="mord mathit">e</span><span class="mopen">(</span><span class="mord mathit">i</span><span class="mpunct">,</span><span class="mord mathit" style="margin-right:0.05724em;">j</span><span class="mclose">)</span><span class="mrel">=</span><span class="mord mathit">p</span><span class="mord mathit" style="margin-right:0.02778em;">r</span><span class="mord mathit">e</span><span class="mord mathit" style="margin-right:0.10764em;">f</span><span class="mord mathit">i</span><span class="mord"><span class="mord mathit">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathit mtight">s</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"></span></span></span></span></span><span class="mord mathit">u</span><span class="mord mathit">m</span><span class="mopen">[</span><span class="mord mathit" style="margin-right:0.05724em;">j</span><span class="mbin">+</span><span class="mord mathrm">1</span><span class="mclose">]</span><span class="mbin">−</span><span class="mord mathit">p</span><span class="mord mathit" style="margin-right:0.02778em;">r</span><span class="mord mathit">e</span><span class="mord mathit" style="margin-right:0.10764em;">f</span><span class="mord mathit">i</span><span class="mord"><span class="mord mathit">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathit mtight">s</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"></span></span></span></span></span><span class="mord mathit">i</span><span class="mord mathit">m</span><span class="mopen">[</span><span class="mord mathit">i</span><span class="mclose">]</span></span></span></span></span></p>
</li>
</ol>
<p>案例</p>
<p>nums = [-2, 0, 3, -5, 2, -1]<br />
prefix_sum = [0, -2, <strong>-2</strong>, 1, -4, -2, <strong>-3</strong>]</p>
<pre><div class="hljs"><code class="lang-shell">题目:
sumRange(2, 5)
= prefix_sum[6] - prefix_sum[2]
= (-3)-(-2)
= -1
</code></div></pre>
<p>时间复杂度:</p>
<ul>
<li>初始化:O(n)</li>
<li>每次查询:O(1)</li>
</ul>
<p>空间复杂度:O(n)</p>
<h3><a id="python_79"></a>python实现</h3>
<pre><div class="hljs"><code class="lang-python"><span class="hljs-comment"># -*- coding: utf-8 -*-</span>
<span class="hljs-keyword">class</span> <span class="hljs-title class_">NumArray</span>:
<span class="hljs-keyword">def</span> <span class="hljs-title function_">__init__</span>(<span class="hljs-params">self, nums</span>):
<span class="hljs-comment"># 构造前缀和数组</span>
self.prefix_sum = [<span class="hljs-number">0</span>]
<span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> nums:
self.prefix_sum.append(self.prefix_sum[-<span class="hljs-number">1</span>] + num)
<span class="hljs-keyword">def</span> <span class="hljs-title function_">sumRange</span>(<span class="hljs-params">self, i, j</span>):
<span class="hljs-comment"># 区间和 = 前缀和差</span>
<span class="hljs-keyword">return</span> self.prefix_sum[j+<span class="hljs-number">1</span>]-self.prefix_sum[i]
numArray = NumArray([-<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, <span class="hljs-number">3</span>, -<span class="hljs-number">5</span>, <span class="hljs-number">2</span>, -<span class="hljs-number">1</span>])
<span class="hljs-built_in">print</span>(numArray.sumRange(<span class="hljs-number">0</span>, <span class="hljs-number">2</span>)) <span class="hljs-comment"># 1</span>
<span class="hljs-built_in">print</span>(numArray.sumRange(<span class="hljs-number">2</span>, <span class="hljs-number">5</span>)) <span class="hljs-comment"># -1</span>
<span class="hljs-built_in">print</span>(numArray.sumRange(<span class="hljs-number">0</span>, <span class="hljs-number">5</span>)) <span class="hljs-comment"># -3</span>
</code></div></pre>
评论区