Talentd
FleetCode
Make and follow sheets.Sign in

Range Sum Query - Mutable solution and explanation

MediumArrayBinary Indexed TreeDesignSegment Tree6 min read43.9% acceptanceUpdated 9 Apr 2026
Range Sum Query - Mutable | Leetcode 307 | Segment tree construction and updateTechdose · 26:32 · 70K viewsWatch on YouTube
9 more videos on this problem
  1. Range Sum Query - Mutable | Leetcode 307 | Segment tree construction and updateTechdose · 26:32 · 70K views
  2. Range Sum Query - Mutable | Leetcode 307 | Segment Tree Concepts & Qns | Video 8 | codestorywithMIKcodestorywithMIK · 17:18 · 15K views
  3. Segment Tree Basics Range Sum Query - Mutable | Leetcode 307 | Live coding sessionCoding Decoded · 15:51 · 9K views
  4. LeetCode 307. Range Sum Query - MutableHappy Coding · 33:30 · 4K views
  5. Fenwick Tree (BIT Tree) Leetcode 307 | Range Sum Query - MutableNideesh Terapalli · 29:33 · 3K views
  6. Leetcode - Range Sum Query - Mutable (Python)Timothy H Chang · 8:29 · 3K views
  7. Daily Leetcode #852: Jul 31, 2022 - 307. Range Sum Query - MutableProgramming Live with Larry · 7:27 · 1K views
  8. Daily Leetcode #444: Jun 18, 2021 - 307. Range Sum Query - MutableProgramming Live with Larry · 24:04 · 386 views
  9. 【Binary Indexed Tree】307. Range Sum Query - Mutablehappygirlzt · 15:59 · 285 views
  10. LeetCode - 307. Range Sum Query - Mutable | Binary Indexed Tree | JavaOrkhan Gasanov · 10:54 · 270 views

The problem

Given an integer array nums, handle multiple queries of the following types:

  1. Update the value of an element in nums.
  2. Calculate the sum of the elements of 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.
  • void update(int index, int val) Updates the value of nums[index] to be val.
  • 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", "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] <= 100
  • 0 <= index < nums.length
  • -100 <= val <= 100
  • 0 <= left <= right < nums.length
  • At most 3 * 104 calls will be made to update and sumRange.

Approach overview

Problem Overview: You need to design a data structure that supports two operations on an integer array: update the value at a specific index and return the sum of elements within a range [left, right]. The challenge comes from handling frequent updates efficiently while still answering range queries quickly.

Approach 1: Brute Force - Simple Array Modification (Update O(1), Query O(n))

The simplest design stores the numbers directly in an array. When update(index, val) is called, you replace the value at that index in O(1) time. For sumRange(left, right), iterate from left to right and accumulate the sum. This approach works because array access is constant time, but every query requires scanning part of the array. Time complexity becomes O(n) per query and O(1) per update, with O(n) space for the array. It works for small inputs or when queries are rare, but it becomes slow when many range queries are executed.

Approach 2: Segment Tree (Update O(log n), Query O(log n))

A segment tree stores aggregated sums of subranges in a binary tree structure. Each node represents the sum of a segment of the array, and its children represent smaller segments. Building the tree takes O(n) time. When you update a value, the change propagates from the leaf node up to the root, updating all affected segment sums in O(log n) time. For sumRange(left, right), the query walks the tree and combines sums from nodes that fully cover parts of the requested range, also in O(log n) time.

This structure avoids scanning the array repeatedly. Instead of recalculating sums from scratch, it reuses precomputed segment sums. Segment trees are ideal when the array is frequently modified and queries are frequent. They provide a balanced tradeoff: logarithmic time for both operations and O(n) memory.

Another common alternative is a Binary Indexed Tree (Fenwick Tree), which also supports prefix sums and updates in O(log n). Many engineers prefer it for simpler implementation, but segment trees provide more flexibility for advanced range operations. Both approaches rely on understanding prefix aggregation over an array.

Recommended for interviews: Start by explaining the brute force array solution to show baseline reasoning. Then move to the segment tree optimization. Interviewers expect a logarithmic-time data structure because the problem mixes updates and range queries. Demonstrating how updates propagate through the tree and how queries combine partial segments shows strong understanding of range query data structures.

Approach 1: Brute Force - Simple Array Modification

This approach utilizes a simple array to store the elements, implementing updates directly and calculating the range sum by iterating through the specified range.

The update operation runs in constant time as it simply replaces a value at a given index. However, the sum operation runs in O(n) time, where n is the size of the query range, as it sums elements one by one.

class NumArray:
    def __init__(self, nums):
        self.nums = nums

    def update(self, index, val):
        self.nums[index] = val

    def sumRange(self, left, right):
        return sum(self.nums[left:right+1])
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;
    }
}
#include <vector>
using namespace std;

class NumArray {
private:
    vector<int> nums;
public:
    NumArray(vector<int>& nums) : nums(nums) {}

    void update(int index, int val) {
        nums[index] = val;
    }

    int sumRange(int left, int right) {
        int sum = 0;
        for (int i = left; i <= right; ++i) {
            sum += nums[i];
        }
        return sum;
    }
};
class NumArray {
    constructor(nums) {
        this.nums = nums;
    }

    update(index, val) {
        this.nums[index] = val;
    }

    sumRange(left, right) {
        let sum = 0;
        for (let i = left; i <= right; i++) {
            sum += this.nums[i];
        }
        return sum;
    }
}
#include <stdlib.h>

typedef struct {
    int* nums;
    int size;
} NumArray;

NumArray* numArrayCreate(int* nums, int numsSize) {
    NumArray* numArray = (NumArray*) malloc(sizeof(NumArray));
    numArray->nums = (int*) malloc(numsSize * sizeof(int));
    numArray->size = numsSize;
    for (int i = 0; i < numsSize; i++) {
        numArray->nums[i] = nums[i];
    }
    return numArray;
}

void numArrayUpdate(NumArray* obj, int index, int val) {
    obj->nums[index] = val;
}

int numArraySumRange(NumArray* obj, int left, int right) {
    int sum = 0;
    for (int i = left; i <= right; i++) {
        sum += obj->nums[i];
    }
    return sum;
}

void numArrayFree(NumArray* obj) {
    free(obj->nums);
    free(obj);
}
public 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;
    }
}

In this Python solution, we define a list self.nums to store the numbers. The update method modified a specific index with a new value, while sumRange calculates the sum of numbers between indices left and right (inclusive) by using Python's built-in sum() function.

Complexity

Time Complexity: O(1) for update, O(n) for sumRange where n is the number of elements between left and right.

Space Complexity: O(1) - additional space usage is minimal.

Try this approach in the editor

Approach 2: Optimized with Segment Tree

A segment tree provides a more efficient solution for this problem, reducing the time complexity for both update and sum operations. Segment trees are ideal for scenarios where an array undergoes frequent updates and queries, as they allow modifications and range sum queries to be done in logarithmic time.

class NumArray:
    def __init__(self, nums):
        self.nums = nums
        self.n = len(nums)
        self.tree = [0] * (2 * self.n)
        self.buildSegmentTree()

    def buildSegmentTree(self):
        # Build the segment tree
        for i in range(self.n):
            self.tree[self.n + i] = self.nums[i]
        for i in range(self.n - 1, 0, -1):
            self.tree[i] = self.tree[2 * i] + self.tree[2 * i + 1]

    def update(self, pos, value):
        pos += self.n
        self.tree[pos] = value
        while pos > 1:
            pos //= 2
            self.tree[pos] = self.tree[2 * pos] + self.tree[2 * pos + 1]

    def sumRange(self, left, right):
        left += self.n
        right += self.n
        sum_ = 0
        while left <= right:
            if left % 2 == 1:
                sum_ += self.tree[left]
                left += 1
            if right % 2 == 0:
                sum_ += self.tree[right]
                right -= 1
            left //= 2
            right //= 2
        return sum_
#include <vector>
using namespace std;

class NumArray {
private:
    vector<int> tree;
    int n;
public:
    NumArray(vector<int>& nums) {
        n = nums.size();
        tree.resize(2 * n);
        buildSegmentTree(nums);
    }

    void buildSegmentTree(vector<int>& nums) {
        for (int i = 0; i < n; i++) {
            tree[n + i] = nums[i];
        }
        for (int i = n - 1; i > 0; i--) {
            tree[i] = tree[2 * i] + tree[2 * i + 1];
        }
    }

    void update(int index, int val) {
        index += n;
        tree[index] = val;
        while (index > 1) {
            index /= 2;
            tree[index] = tree[2 * index] + tree[2 * index + 1];
        }
    }

    int sumRange(int left, int right) {
        left += n;
        right += n;
        int sum = 0;
        while (left <= right) {
            if (left % 2 == 1) sum += tree[left++];
            if (right % 2 == 0) sum += tree[right--];
            left /= 2;
            right /= 2;
        }
        return sum;
    }
};

This Python solution utilizes a segment tree, which allows the program to efficiently handle the updates and sum queries. The tree is represented with a flat array. The buildSegmentTree constructively sets up the tree, update modifies a value while updating the tree structure, and sumRange calculates the range sum over the tree.

Complexity

Time Complexity: O(log n) for both update and sumRange.

Space Complexity: O(n) for the segment tree storage.

Try this approach in the editor

Approach 3: Default Approach

class BinaryIndexedTree {
    private n: number;
    private c: number[];

    constructor(n: number) {
        this.n = n;
        this.c = Array(n + 1).fill(0);
    }

    update(x: number, delta: number): void {
        while (x <= this.n) {
            this.c[x] += delta;
            x += x & -x;
        }
    }

    query(x: number): number {
        let s = 0;
        while (x > 0) {
            s += this.c[x];
            x -= x & -x;
        }
        return s;
    }
}

class NumArray {
    private tree: BinaryIndexedTree;

    constructor(nums: number[]) {
        const n = nums.length;
        this.tree = new BinaryIndexedTree(n);
        for (let i = 0; i < n; ++i) {
            this.tree.update(i + 1, nums[i]);
        }
    }

    update(index: number, val: number): void {
        const prev = this.sumRange(index, index);
        this.tree.update(index + 1, val - prev);
    }

    sumRange(left: number, right: number): number {
        return this.tree.query(right + 1) - this.tree.query(left);
    }
}

/**
 * Your NumArray object will be instantiated and called as such:
 * var obj = new NumArray(nums)
 * obj.update(index,val)
 * var param_2 = obj.sumRange(left,right)
 */
type BinaryIndexedTree struct {
	n int
	c []int
}

func newBinaryIndexedTree(n int) *BinaryIndexedTree {
	c := make([]int, n+1)
	return &BinaryIndexedTree{n, c}
}

func (t *BinaryIndexedTree) update(x, delta int) {
	for ; x <= t.n; x += x & -x {
		t.c[x] += delta
	}
}

func (t *BinaryIndexedTree) query(x int) (s int) {
	for ; x > 0; x -= x & -x {
		s += t.c[x]
	}
	return s
}

type NumArray struct {
	tree *BinaryIndexedTree
}

func Constructor(nums []int) NumArray {
	tree := newBinaryIndexedTree(len(nums))
	for i, v := range nums {
		tree.update(i+1, v)
	}
	return NumArray{tree}
}

func (t *NumArray) Update(index int, val int) {
	prev := t.SumRange(index, index)
	t.tree.update(index+1, val-prev)
}

func (t *NumArray) SumRange(left int, right int) int {
	return t.tree.query(right+1) - t.tree.query(left)
}

/**
 * Your NumArray object will be instantiated and called as such:
 * obj := Constructor(nums);
 * obj.Update(index,val);
 * param_2 := obj.SumRange(left,right);
 */
Try this approach in the editor

Complexity comparison

ApproachComplexity
Brute Force - Simple Array Modification

Time Complexity: O(1) for update, O(n) for sumRange where n is the number of elements between left and right.

Space Complexity: O(1) - additional space usage is minimal.

Optimized with Segment Tree

Time Complexity: O(log n) for both update and sumRange.

Space Complexity: O(n) for the segment tree storage.

Default Approach–

Complexity analysis

ApproachTimeSpaceWhen to Use
Brute Force ArrayUpdate: O(1), Query: O(n)O(n)Simple implementation when the array is small or range queries are infrequent
Segment TreeUpdate: O(log n), Query: O(log n)O(n)Best choice when updates and range queries both occur frequently

Frequently asked questions

Is Range Sum Query - Mutable easy or hard?

The problem is rated Medium because it requires designing a data structure rather than writing a simple algorithm. Understanding Segment Trees or Fenwick Trees is necessary to reach the optimal O(log n) solution.

Range Sum Query - Mutable Python/Java solution

Typical implementations build a Segment Tree class with update and query methods. Python and Java solutions both maintain a tree array where each node stores the sum of a segment, allowing O(log n) updates and queries.

How to solve Range Sum Query - Mutable in O(log n)?

Use a Segment Tree or Binary Indexed Tree. Store prefix or segment sums in a tree structure so updates propagate through log n nodes. Range queries combine partial sums from relevant nodes, giving O(log n) complexity.

What is the best approach for Range Sum Query - Mutable?

Segment Tree is the most common optimal solution. It supports both update and range sum queries in O(log n) time. The tree stores sums of segments so queries combine only relevant nodes instead of scanning the array.

Is Range Sum Query - Mutable asked at Google/Amazon/Meta?

Range query data structure problems like this frequently appear in interviews at companies such as Google, Amazon, and Meta. Variations involving Segment Trees or Fenwick Trees are common in system design style coding rounds.

What data structure is used in Range Sum Query - Mutable?

Segment Tree and Binary Indexed Tree (Fenwick Tree) are the main data structures. Both maintain partial sums that allow fast updates and range queries without recomputing sums from scratch.

What is the time complexity of Range Sum Query - Mutable?

Using a Segment Tree, both update(index, val) and sumRange(left, right) run in O(log n) time. Building the tree initially takes O(n). The brute force array method has O(1) updates but O(n) query time.

Comments

Now write it yourselfClose this page and solve Range Sum Query - Mutable in the editor, without looking.
Practise Range Sum Query - Mutable