• Range Sum Query


    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)

    
    

     

  • 相关阅读:
    安装 elasticsearch For LINUX
    java 读取文件最佳实践
    mysql alter 语句用法,添加、修改、删除字段等
    Linux type命令
    在mahout安装目录下输入mahout 提示 ERROR: Could not find mahout-examples-*.job
    Ubuntu中安装eclipse ,双击eclipse出现invalid configuration location问题
    Ubuntu中查看32还是64
    转载--JAVA读取文件最佳实践
    Ubuntu中添加eclipse
    Hadoop 如何查看是否32位
  • 原文地址:https://www.cnblogs.com/luckygxf/p/5605142.html
Copyright © 2020-2023  润新知