地址 https://leetcode-cn.com/problems/range-sum-query-mutable/node
題目描述
給定一個整數數組 nums,求出數組從索引 i 到 j (i ≤ j) 範圍內元素的總和,包含 i, j 兩點。算法
update(i, val) 函數能夠經過將下標爲 i 的數值更新爲 val,從而對數列進行修改。數組
示例: Given nums = [1, 3, 5] sumRange(0, 2) -> 9 update(1, 2) sumRange(0, 2) -> 8 說明: 數組僅能夠在 update 函數下進行修改。 你能夠假設 update 函數與 sumRange 函數的調用次數是均勻分佈的。
算法1
區間求和 天然使用 線段樹 或者線段數組
這裏以線段樹爲例
以 空間換時間 記錄線段之間的和 最大最小值等
因爲是樹 即便其中一部分元素改變或者某一個元素改變 更改記錄也只是log(n)的複雜度函數
class SegmentTreeNode { public: SegmentTreeNode(int start,int end,int sum, SegmentTreeNode* left = nullptr, SegmentTreeNode* right = nullptr): start(start), end(end), sum(sum), left(left), right(right){} SegmentTreeNode(const SegmentTreeNode&) = delete; SegmentTreeNode& operator=(const SegmentTreeNode&) = delete; ~SegmentTreeNode() { delete left; delete right; left = right = nullptr; } int start; int end; int sum; SegmentTreeNode* left; SegmentTreeNode* right; }; class NumArray { public: NumArray(vector<int> nums) { nums_.swap(nums); if (!nums_.empty()) root_.reset(buildTree(0, nums_.size() - 1)); } void update(int i, int val) { updateTree(root_.get(), i, val); } int sumRange(int i, int j) { return sumRange(root_.get(), i, j); } private: vector<int> nums_; std::unique_ptr<SegmentTreeNode> root_; SegmentTreeNode* buildTree(int start, int end) { if (start == end) { return new SegmentTreeNode(start, end, nums_[start]); } int mid = start + (end - start) / 2; auto left = buildTree(start, mid); auto right = buildTree(mid + 1, end); auto node = new SegmentTreeNode(start, end, left->sum + right->sum, left, right); return node; } void updateTree(SegmentTreeNode* root, int i, int val) { if (root->start == i && root->end == i) { root->sum = val; return; } int mid = root->start + (root->end - root->start) / 2; if (i <= mid) { updateTree(root->left, i, val); } else { updateTree(root->right, i, val); } root->sum = root->left->sum + root->right->sum; } int sumRange(SegmentTreeNode* root, int i, int j) { if (i == root->start && j == root->end) { return root->sum; } int mid = root->start + (root->end - root->start) / 2; if (j <= mid) { return sumRange(root->left, i, j); } else if (i > mid) { return sumRange(root->right, i, j); } else { return sumRange(root->left, i, mid) + sumRange(root->right, mid + 1, j); } } };