Range Sum Query - Mutable

Given an integer array nums, and then you need to implement two functions:

  • update(i, val) Modify the element whose index is i to val.
  • sumRange(l, r) Return the sum of elements whose indexes are in range of [l, r][l,r].

Example

Example 1:

Input: 
  nums = [1, 3, 5]
  sumRange(0, 2)
  update(1, 2)
  sumRange(0, 2)
Output:
  9
  8

Example 2:

Input:
  nums = [0, 9, 5, 7, 3]
  sumRange(4, 4)
  sumRange(2, 4)
  update(4, 5)
  update(1, 7)
  update(0, 8)
  sumRange(1, 2)
Output:
  3
  15
  12

Notice

  1. The array is only modifiable by the update function.
  2. You may assume the number of calls to update and sumRange function is distributed evenly.

思路:用segment tree,可以直接用array build tree,然后每个index modify成(i, nums[i]),然后按照模板写出segment tree即可;Time Build Tree O(N),  query , modify O(logN).

class NumArray {

    private SegmentTree tree;
    public NumArray(int[] nums) {
        tree = new SegmentTree(nums);
    }
    
    public void update(int i, int val) {
        tree.modify(i, val);
    }
    
    public int sumRange(int i, int j) {
        return tree.querySum(i, j);
    }
    
    private class SegmentTreeNode {
        public int start, end;
        public int sum;
        public SegmentTreeNode left, right;
        public SegmentTreeNode (int start, int end) {
            this.start = start;
            this.end = end;
        }
    }
    
    private class SegmentTree {
        public SegmentTreeNode root;
        public int size;
        public SegmentTree(int[] A) {
            this.size = A.length;
            this.root = buildTree(A, 0, size - 1);
        }
        
        private SegmentTreeNode buildTree(int[] A, int start, int end) {
            if(start > end) {
                return null;
            }
            SegmentTreeNode root = new SegmentTreeNode(start, end);
            if(start == end) {
                root.sum = A[start];
                return root;
            }
            int mid = start + (end - start) / 2;
            root.left = buildTree(A, start, mid);
            root.right = buildTree(A, mid + 1, end);
            root.sum = root.left.sum + root.right.sum;
            return root;
        }
        
        private int querySum(SegmentTreeNode root, int start, int end) {
            if(root.start == start && root.end == end) {
                return root.sum;
            }
            int mid = root.start + (root.end - root.start) / 2;
            int leftsum = 0, rightsum = 0;
            if(start <= mid) {
                leftsum = querySum(root.left, start, Math.min(mid, end));
            }
            if(end >= mid + 1) {
                rightsum = querySum(root.right, Math.max(start, mid + 1), end);
            }
            return leftsum + rightsum;
        }
        
        private void modify(SegmentTreeNode root, int index, int value) {
            if(root.start == root.end && root.end == index) {
                root.sum = value;
                return;
            }
            int mid = root.start + (root.end - root.start) / 2;
            if(index <= mid) {
                modify(root.left, index, value);
            } else {
                modify(root.right, index, value);
            }
            root.sum = root.left.sum + root.right.sum;
        }
        
        public int querySum(int start, int end) {
            return querySum(root, start, end);
        }
        
        public void modify(int index, int value) {
            modify(root, index, value);
        }
    }
}

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray obj = new NumArray(nums);
 * obj.update(i,val);
 * int param_2 = obj.sumRange(i,j);
 */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值