Range Sum Query - Mutable
MedPrompt
Given an integer array nums, handle multiple queries of the following types:
- Update the value of an element in
nums. - Calculate the sum of the elements of
numsbetween indicesleftandrightinclusive whereleft <= right.
Implement the NumArray class:
NumArray(int[] nums)Initializes the object with the integer arraynums.void update(int index, int val)Updates the value ofnums[index]to beval.int sumRange(int left, int right)Returns the sum of the elements ofnumsbetween indicesleftandrightinclusive (i.e.nums[left] + nums[left + 1] + ... + nums[right]).
Example 1:
Input
["NumArray", "sumRange", "update", "sumRange"]
[[[1, 3, 5]], [0, 2], [1, 2], [0, 2]]
Output
[null, 9, null, 8]
Explanation
NumArray numArray = new NumArray([1, 3, 5]);
numArray.sumRange(0, 2); // return 1 + 3 + 5 = 9
numArray.update(1, 2); // nums = [1, 2, 5]
numArray.sumRange(0, 2); // return 1 + 2 + 5 = 8
Constraints:
1 <= nums.length <= 3 * 104-100 <= nums[i] <= 1000 <= index < nums.length-100 <= val <= 1000 <= left <= right < nums.length- At most
3 * 104calls will be made toupdateandsumRange.
Approaches
4 approaches with complexity analysis and trade-offs.
The most straightforward approach is to simulate the operations directly on the array. We store a copy of the input array nums. When an update is requested, we modify the element at the specific index. When a sum range is requested, we iterate through the given range and calculate the sum on the fly.
Algorithm
- Constructor
NumArray(int[] nums):- Initialize a member variable, an integer array, with the values from the input
nums.
- Initialize a member variable, an integer array, with the values from the input
- Update
update(int index, int val):- Directly access the element at the given
indexin the stored array and set its value toval.
- Directly access the element at the given
- Sum Range
sumRange(int left, int right):- Initialize a variable
sumto 0. - Loop from
lefttoright(inclusive). - In each iteration, add the value of the element
nums[i]tosum. - Return the final
sum.
- Initialize a variable
Walkthrough
In this approach, the NumArray class holds a copy of the integer array. The update operation is efficient as it only involves a single array modification, which is a constant time operation. However, the sumRange operation requires iterating through all the elements from the left index to the right index. In the worst-case scenario, where the range covers the entire array, this iteration takes time proportional to the size of the array, N.
class NumArray { private int[] nums; public NumArray(int[] nums) { this.nums = nums; } public void update(int index, int val) { nums[index] = val; } public int sumRange(int left, int right) { int sum = 0; for (int i = left; i <= right; i++) { sum += nums[i]; } return sum; }}Complexity
Time
* **Constructor**: O(N) to create a copy of the input array. * **`update`**: O(1) as it's a direct array access. * **`sumRange`**: O(N) in the worst case, as we might need to iterate through the entire array.
Space
O(N), where N is the number of elements in the input array. This space is used to store the copy of the array.
Trade-offs
Pros
Very simple to understand and implement.
The
updateoperation is extremely fast, taking O(1) time.Requires minimal extra space, just enough to store the array itself.
Cons
The
sumRangeoperation is very slow, with a time complexity of O(N) in the worst case.This approach will likely result in a 'Time Limit Exceeded' error for large inputs and a high number of
sumRangequeries, as specified in the problem constraints.
Solutions
Solution
class BinaryIndexedTree { private int n ; private int [] c ; public BinaryIndexedTree ( int n ) { this . n = n ; c = new int [ n + 1 ]; } public void Update ( int x , int delta ) { while ( x <= n ) { c [ x ] += delta ; x += x & - x ; } } public int Query ( int x ) { int s = 0 ; while ( x > 0 ) { s += c [ x ]; x -= x & - x ; } return s ; } } public class NumArray { private BinaryIndexedTree tree ; public NumArray ( int [] nums ) { int n = nums . Length ; tree = new BinaryIndexedTree ( n ); for ( int i = 0 ; i < n ; ++ i ) { tree . Update ( i + 1 , nums [ i ]); } } public void Update ( int index , int val ) { int prev = SumRange ( index , index ); tree . Update ( index + 1 , val - prev ); } public int SumRange ( int left , int right ) { return tree . Query ( right + 1 ) - tree . Query ( left ); } } /** * Your NumArray object will be instantiated and called as such: * NumArray obj = new NumArray(nums); * obj.Update(index,val); * int param_2 = obj.SumRange(left,right); */Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.