zoukankan      html  css  js  c++  java
  • LeetCode #307. Range Sum Query

    Description


    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:

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



    思路


    解法一

    暴力。

    时间复杂度:

    • 构造数组:O(n)
    • update操作:O(1)
    • sumRange操作:O(n)

    空间复杂度:O(n)

    耗时 216 ms, faster than 21%, Memory 16.6 MB

    class NumArray {
    public:
        NumArray(const vector<int> &numbers) : nums(numbers) {}
    
        void update(int i, int val) {
            nums[i] = val;
        }
    
        int sumRange(int i, int j) {
            int sum = 0;
            while (i <= j) {
                sum += nums[i];
                ++i;
            }
    
            return sum;
        }
    
    private:
        vector<int> nums;
    };
    
    /**
     * 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);
     */
    



    解法二

    线段树,本质是使用二分法拆分可变区间。

    线段树是一颗可以携带额外信息的满二叉树,比如携带子树的结点和,或者最大值,最小值等等,这样,当某个结点的值发生变化时,只需要更新一下其所有祖先结点的信息,而并不需要更新整棵树,这样就极大的提高了效率。

    这是我第一次实现线段树,比较吃力,解题思路参照的是这个博客:[LeetCode] 307. Range Sum Query - Mutable 区域和检索 - 可变

    时间复杂度:

    • 建树:O(n)
    • update操作:O(lgn)
    • sumRange操作:O(lgn)

    空间复杂度:O(n)

    耗时 48 ms, faster than 71.15%, Memory 16.7 MB

    // nums      1  3  5  7
    // tree      0 16  4 12  1  3  5  7
    //   i       0  1  2  3  4  5  6  7
    //
    //           1  3  5  7  9
    //           0 25 17  8 16  1  3  5  7  9
    //           0  1  2  3  4  5  6  7  8  9
    
    class NumArray {
    public:
        NumArray(const vector<int> &nums) {
            n = nums.size();
            tree.resize(2 * nums.size(), 0);
            build_seg_tree(nums);
        }
    
        void build_seg_tree(const vector<int> &nums) {
            for (int i = 0; i < nums.size(); ++i) {
                tree[i + n] = nums[i];
            }
    
            for (int i = n - 1; i > 0; --i) {
                tree[i] = tree[2 * i] + tree[2 * i + 1];
            }
        }
    
        void update(int i, int val) {
            int idx = n + i;  // position of nums[i] in tree
            if (tree[idx] == val) return;
    
            tree[idx] = val;
    
            // update value of parent node
            while (idx > 0 && idx / 2 != 0) {
                int another_son_idx = idx ^ 1;
                int parent_idx = idx / 2;
                tree[parent_idx] = tree[idx] + tree[another_son_idx];
    
                idx /= 2;
            }
        }
    
        int sumRange(int i, int j) {
            i += n;
            j += n;
            int sum = 0;
    
            while (i <= j) {
                if ((i & 1) == 1) {  // element is right son of subtree or parent node
                    sum += tree[i];
                    ++i;  // move to a subtree on the right
                }
    
                if ((j & 1) == 0) {  // element is left son of subtree or parent node
                    sum += tree[j];
                    --j;  // move to a subtree on the left
                }
    
                // move to the parent node
                i /= 2;
                j /= 2;
            }
    
            return sum;
        }
    
    private:
        int n;  // numbers of element in nums
        vector<int> tree;
    };
    
    
    /**
     * 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);
     */
    



    参考




  • 相关阅读:
    ACM 2的N次方
    文件默认打开方式 转
    java 的 一点记录
    zhuan 漫谈C语言及如何学习C语言
    eclipse
    code::blocks
    心态决定命运_no excuses, suck it up, obey your teacher
    uml_2_application and viso application
    paint conflict with lingoes
    stm learning record
  • 原文地址:https://www.cnblogs.com/Bw98blogs/p/12762484.html
Copyright © 2011-2022 走看看