Given an integer array nums
, handle multiple queries of the following type:
nums
between indices left
and right
inclusive where left <= right
.Implement the NumArray
class:
NumArray(int[] nums)
Initializes the object with the integer array nums
.int sumRange(int left, int right)
Returns the sum of the elements of nums
between indices left
and right
inclusive (i.e. nums[left] + nums[left + 1] + ... + nums[right]
).Example 1:
Input ["NumArray", "sumRange", "sumRange", "sumRange"] [[[-2, 0, 3, -5, 2, -1]], [0, 2], [2, 5], [0, 5]] Output [null, 1, -1, -3] Explanation NumArray numArray = new NumArray([-2, 0, 3, -5, 2, -1]); numArray.sumRange(0, 2); // return (-2) + 0 + 3 = 1 numArray.sumRange(2, 5); // return 3 + (-5) + 2 + (-1) = -1 numArray.sumRange(0, 5); // return (-2) + 0 + 3 + (-5) + 2 + (-1) = -3
Constraints:
1 <= nums.length <= 104
-105 <= nums[i] <= 105
0 <= left <= right < nums.length
104
calls will be made to sumRange
.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach to answering the sum of a range is very simple. We directly calculate the sum for the specific range given. This means we look at each number within the range and add them together.
Here's how the algorithm would work step-by-step:
class NumArray:
def __init__(self, numbers):
self.numbers = numbers
def sumRange(self, left_index, right_index):
range_sum = 0
# Iterate from left_index up to right_index (inclusive)
for current_index in range(left_index, right_index + 1):
# Add each number in the range to the total
range_sum += self.numbers[current_index]
return range_sum
# Your NumArray object will be instantiated and called as such:
# numbers = [ -2, 0, 3, -5, 2, -1 ]
# obj = NumArray(numbers)
# param_1 = obj.sumRange(0,2)
Instead of recalculating the sum for every query, we will do some pre-processing to make lookups faster. This pre-processing will allow us to answer each query in a constant amount of time.
Here's how the algorithm would work step-by-step:
class NumArray:
def __init__(self, nums):
self.original_array = nums
self.cumulative_sum_array = [0] * (len(nums) + 1)
# Create cumulative sum array for O(1) queries.
for index in range(len(nums)):
self.cumulative_sum_array[index + 1] = self.cumulative_sum_array[index] + nums[index]
def sumRange(self, left_index, right_index):
# Subtract sum before left from sum at right.
return self.cumulative_sum_array[right_index + 1] - self.cumulative_sum_array[left_index]
# Your NumArray object will be instantiated and called as such:
# numArray = NumArray(nums)
# numArray.sumRange(0, 1)
# numArray.sumRange(1, 2)
Case | How to Handle |
---|---|
Null or empty input array 'nums' | Throw an IllegalArgumentException or return 0 to indicate invalid input in the constructor. |
left > right | Return 0 or throw an IllegalArgumentException, as the range is invalid. |
left or right are out of bounds (left < 0 or right >= nums.length) | Throw an IndexOutOfBoundsException or adjust the indices to the valid range (e.g., clamp to array boundaries). |
Large input array 'nums' (e.g., millions of elements) | Prefix sum approach ensures O(1) time complexity for sumRange, providing good scalability. |
Input array contains only negative numbers | The prefix sum approach works correctly regardless of negative values. |
Input array contains extreme values (Integer.MAX_VALUE, Integer.MIN_VALUE) | Use long data type for prefix sums to avoid integer overflow during summation. |
left == right (single element range) | The algorithm should correctly return the value of nums[left]. |
Integer overflow in sum calculation if using int for prefix sum with extremely large array values and range | Use long to store prefix sums to prevent integer overflow in sum calculations. |