1. 程式人生 > 實用技巧 >【刷題-LeetCode】307. Range Sum Query - Mutable

【刷題-LeetCode】307. Range Sum Query - Mutable

  1. Range Sum Query - Mutable

Given an integer array nums, find the sum of the elements between indices i and j (ij), 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

Constraints:

  • The array is only modifiable by the update function.
  • You may assume the number of calls to update and sumRange function is distributed evenly.
  • 0 <= i <= j <= nums.length - 1

解法1 將查詢區間的數字直接求和

class NumArray {
public:
    vector<int>Array;
    NumArray(vector<int>& nums) {
        Array = nums;
    }
    
    void update(int i, int val) {
        Array[i] = val;
    }
    
    int sumRange(int i, int j) {
        int res = 0;
        for(int k = i; k <= j; ++k)res += Array[k];
        return res;
    }
};

解法2 求和陣列。先將陣列的前n項和計算出來,更新的時候將前k項和(k>= i)更新即可

class NumArray {
public:
    vector<int>S{0};
    vector<int>Array;
    NumArray(vector<int>& nums) {
        Array = nums;
        for(int i = 0; i < nums.size(); ++i){
            S.push_back(S.back() + nums[i]);
        }
    }
    
    void update(int i, int val) {
        int d = val - Array[i];
        Array[i] = val;
        for(int j = i + 1; j < S.size(); ++j)S[j] += d;
    }
    
    int sumRange(int i, int j) {
        return S[j+1] - S[i];
    }
};

解法3 分塊求和。解法2中update函式花費時間較多,更新的平均時間複雜度為\(O(n/2)\),為了控制更新的範圍,將陣列劃分為多個塊,更新控制在對應的塊內,將塊的尺寸取為\(\sqrt{n}\),更新的時間複雜度為\(O(\sqrt{n})\)

class NumArray {
public:
    int block_size;
    vector<int>Array;
    vector<int>S;
    NumArray(vector<int>& nums) {
        Array = nums;
        block_size = int(sqrt(nums.size()));
        int sum = 0;
        for(int i = 0; i < nums.size(); ++i){
            sum += nums[i];
            if((i+1) % block_size == 0 || i + 1 == nums.size()){
                S.push_back(sum);
                sum = 0;
            }
        }
    }
    
    void update(int i, int val) {
        S[i / block_size] += val - Array[i];
        Array[i] = val;
    }
    
    int sumRange(int i, int j) {
        int res = 0;
        int s_b = i / block_size, e_b = j / block_size;
        if(s_b == e_b){
            for(int k = i; k <= j; ++k)res += Array[k];
        }
        else{
            for(int k = i; k < (s_b+1)*block_size; ++k)res += Array[k];
            for(int b  =s_b + 1; b < e_b; ++b)res += S[b];
            for(int k = e_b*block_size; k <= j; ++k)res += Array[k];
        }
        return res;
    }
};

解法4 線段樹(不想看了。。。)