Range Sum Query - Mutable

Posted Just DO IT by luckygxf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Range Sum Query - Mutable相关的知识,希望对你有一定的参考价值。

Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.

The update(i, val) function modifies nums by updating the element at index i to val.

Example:

Given nums = [1, 3, 5]

sumRange(0, 2) -> 9
update(1, 2)
sumRange(0, 2) -> 8

Note:

  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.

题目大意:

给一个整数数组,对数组进行封装,提供对外接口

1.sumRange(i,j),求下标i到下标j之间所有元素之和

2.update(i, val),更新下标为i的元素为val值

思路一:

常规解法,便利[i,j]获取sum值,直接通过下标访问数组修改元素值,时间复杂度分别为O(N)和O(1)

 1 public class NumArray {
 2     private int nums[];
 3 
 4     public NumArray(int[] nums) {
 5         this.nums = new int[nums.length];
 6         for(int i = 0; i < nums.length; i++){
 7             this.nums[i] = nums[i];
 8         }
 9     }
10 
11     void update(int i, int val) {
12         if(positionIsValid(i))
13             nums[i] = val;
14     }
15 
16     public int sumRange(int i, int j) {
17         if(i > j || !positionIsValid(i) || !positionIsValid(j))
18             return -1;
19         int sum = 0;
20         for(int index = i; index <= j; index ++){
21             sum += nums[index];
22         }
23         
24         return sum;
25     }
26     
27     private boolean positionIsValid(int index){
28         return (index >= 0 && index < nums.length);
29     }
30 }

超时

思路二:

根据提示,可以用分段树(segement tree)或者叫区间树,没用过。参考

http://bookshadow.com/weblog/2015/08/13/segment-tree-set-1-sum-of-given-range/

https://github.com/nanwan03/leetcode/blob/master/Algorithm/Range%20Sum%20Query%20-%20Mutable%20-%20Segment%20Tree.java

 1 //分段树
 2 class SegmentTreeNode{
 3     public int start;
 4     public int end;
 5     public SegmentTreeNode left;
 6     public SegmentTreeNode right;
 7     public int sum;
 8     
 9     public SegmentTreeNode(int start, int end){
10         this.start = start;
11         this.end = end;
12         sum = 0;
13         left = null;
14         right = null;
15     }
16 }
17 
18 public class NumArray {
19     private SegmentTreeNode root;
20     
21     public NumArray(int[] nums) {
22         root = buildSegmentTree(nums, 0, nums.length - 1);
23     }
24     
25     //建造分段树
26     private SegmentTreeNode buildSegmentTree(int nums[], int start, int end){
27         if(start > end)
28             return null;
29         else{
30             SegmentTreeNode ret = new SegmentTreeNode(start, end);
31             if(start == end)
32                 ret.sum = nums[start];
33             else{
34                 int mid = start + (end - start) / 2;
35                 SegmentTreeNode left = buildSegmentTree(nums, start, mid);
36                 SegmentTreeNode right = buildSegmentTree(nums, mid + 1, end);
37                 ret.sum = left.sum + right.sum;
38                 ret.left = left;
39                 ret.right = right;
40             }//else
41             
42             return ret;
43         }//else
44     }//buildSegmentTree
45     
46     //更新分段树节点的值
47     private void update(SegmentTreeNode root, int position, int val){
48         if(root.start == root.end)
49             root.sum = val;
50         else{
51             int mid = root.start + (root.end - root.start) / 2;
52             if(position <= mid){
53                 update(root.left, position, val);
54             }//if
55             else{
56                 update(root.right, position, val);
57             } //else
58             
59             root.sum = root.left.sum + root.right.sum;
60         }//else
61     }//update segmentTree
62     
63     void update(int i, int val) {
64         update(root, i, val);
65     }
66     
67     private int sumRange(SegmentTreeNode root, int start, int end){
68         if(root.start == start && root.end == end)
69             return root.sum;
70         else{
71             int mid = root.start + (root.end - root.start) / 2;
72             if(mid >= end){
73                 return sumRange(root.left, start, end);
74             }else if(start >= mid + 1){
75                 return sumRange(root.right, start, end);
76             }else{
77                 return sumRange(root.left, start, mid) + sumRange(root.right, mid + 1, end);
78             }
79         }
80     }
81 
82     public int sumRange(int i, int j) {
83         return sumRange(root, i, j);
84     }
85 }//NumArray

时间复杂度都为O(logn)

思路三:

使用树状数组,(binary index tree)里面有些需要数学推导,可以不用理会。参考

http://blog.csdn.net/lulipeng_cpp/article/details/7816527#comments

https://leetcode.com/discuss/96367/three-implementations-binary-segment-array-segment-comments

 1 import java.util.Arrays;
 2 
 3 //树状数组
 4 public class NumArray {
 5     int arr[];
 6     int bit[];
 7     int n;
 8     
 9     public NumArray(int[] nums) {
10         n = nums.length;
11         arr = Arrays.copyOf(nums, n);
12         bit = new int[n + 1];
13         for(int i = 0; i < arr.length; i++){
14             updateBit(i + 1, arr[i]);
15         }
16     }
17 
18     void update(int i, int val) {
19         int diff = val - arr[i];
20         arr[i] = val;
21         updateBit(i + 1, diff);
22     }
23 
24     public int sumRange(int i, int j) {
25         return getSum(j + 1) - getSum(i);
26     }
27     
28     private void updateBit(int j, int diff){
29         while(j <= n){
30             bit[j] += diff;
31             j += j & (-j);
32         }
33     }
34     
35     private int getSum(int j){
36         int sum = 0;
37         while(j > 0){
38             sum += bit[j];
39             j -= j & (-j);
40         }//while
41         
42         return sum;
43     }
44 }//NumArray

时间复杂度都为O(logn)


 

以上是关于Range Sum Query - Mutable的主要内容,如果未能解决你的问题,请参考以下文章

Range Sum Query - Mutable

307. Range Sum Query - Mutable

307 Range Sum Query - Mutable

Range Sum Query - Mutable

308. Range Sum Query 2D - Mutable

307. Range Sum Query - Mutable