[LeetCode] 370. Range Addition 范圍相加


 

Assume you have an array of length n initialized with all 0's and are given k update operations.

Each operation is represented as a triplet: [startIndex, endIndex, inc] which increments each element of subarray A[startIndex ... endIndex] (startIndex and endIndex inclusive) with inc.

Return the modified array after all k operations were executed.

Example:

Given:

    length = 5,
    updates = [
        [1,  3,  2],
        [2,  4,  3],
        [0,  2, -2]
    ]

Output:

    [-2, 0, 3, 5, 3]

Explanation:

Initial state:
[ 0, 0, 0, 0, 0 ]

After applying operation [1, 3, 2]:
[ 0, 2, 2, 2, 0 ]

After applying operation [2, 4, 3]:
[ 0, 2, 5, 5, 3 ]

After applying operation [0, 2, -2]:
[-2, 0, 3, 5, 3 ]

Hint:

  1. Thinking of using advanced data structures? You are thinking it too complicated.
  2. For each update operation, do you really need to update all elements between i and j?
  3. Update only the first and end element is sufficient.
  4. The optimal time complexity is O(k + n) and uses O(1) extra space.

Credits:
Special thanks to @vinod23 for adding this problem and creating all test cases.

 

這道題剛添加的時候我就看到了,當時只有1個提交,0個接受,於是我趕緊做,提交成功后發現我是第一個提交成功的,哈哈,頭一次做沙發啊,有點小激動~ 這道題的提示說了我們肯定不能把范圍內的所有數字都更新,而是只更新開頭結尾兩個數字就行了,那該怎么做呢?假設我們的數組范圍是 [0, n),需要更新的區間是 [start, end],更新值是 inc,那么將區間 [start, end] 中每個數字加上 inc,等同於將區間 [start, n) 內的數字都加上 inc,然后將 [end+1, n) 區間內數字都減去 inc,明白了可以這樣轉換之后,我們還是不能每次都更新區間內所有的值,所以需要換一種標記方式,做法就是在開頭坐標 start 位置加上 inc,而在結束位置 end 加1的地方加上 -inc。就比如說需要將新區間 [1, 3] 內數字都加2,那么我們在1的位置加2,在4的位置減2,於是數組就變成了 [0, 2, 0, 0, -2]。假如就只有這一個操作,如何得到最終的結果呢,答案是建立累加和數組,變成 [0, 2, 2, 2, 0],我們發現正好等同於直接將區間 [1, 3] 內的數字都加2。進一步分析,建立累加和數組的操作實際上是表示當前的數字對之后的所有位置上的數字都有影響,那么我們在 start 位置上加了2,表示在 [start, n) 區間范圍內每個數字都加了2,而實際上只有 [start, end] 區間內的數字才需要加2,為了消除這種影響,我們需要將 [end+1, n) 區間內的數字都減去2,所以才在 end+1 位置上減去了2,那么建立累加和數組的時候就相當於后面所有的數字都減去了2。需要注意的是這里 end 可能等於 n-1,則 end+1 可能會越界,所以我們初始化數組的長度為 n+1,就可以避免越界了。那么根據題目中的例子,我們可以得到一個數組,nums = {-2, 2, 3, 2, -2, -3},然后對其做累加和就是我們要求的結果 result = {-2, 0, 3, 5, 3},參見代碼如下:

 

解法一:

class Solution {
public:
    vector<int> getModifiedArray(int length, vector<vector<int>>& updates) {
        vector<int> res, nums(length + 1, 0);
        for (int i = 0; i < updates.size(); ++i) {
            nums[updates[i][0]] += updates[i][2];
            nums[updates[i][1] + 1] -= updates[i][2];
        }
        int sum = 0;
        for (int i = 0; i < length; ++i) {
            sum += nums[i];
            res.push_back(sum);
        }
        return res;
    }
}; 

 

我們可以在空間上稍稍優化下上面的代碼,用 res 來代替 nums,最后把 res 中最后一個數字去掉即可,參見代碼如下:

 

解法二:

class Solution {
public:
    vector<int> getModifiedArray(int length, vector<vector<int>>& updates) {
        vector<int> res(length + 1);
        for (auto a : updates) {
            res[a[0]] += a[2];
            res[a[1] + 1] -= a[2];
        }
        for (int i = 1; i < res.size(); ++i) {
            res[i] += res[i - 1];
        }
        res.pop_back();
        return res;
    }
}

 

Github 同步地址:

https://github.com/grandyang/leetcode/issues/370

 

類似題目:

Range Addition II

 

參考資料:

https://leetcode.com/problems/range-addition/

https://leetcode.com/problems/range-addition/discuss/84223/My-Simple-C%2B%2B-Solution

https://leetcode.com/problems/range-addition/discuss/84217/Java-O(K-%2B-N)time-complexity-Solution

https://leetcode.com/problems/range-addition/discuss/84219/Java-O(n%2Bk)-time-O(1)-space-with-algorithm-explained

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM