Segment-Tree 介紹
主要用來找區間最大值或區間總和。由於我是為了這題所以以區間總和做介紹。下面陣列是應對區間總和,每個 node 紀錄的有起始點, 結束點及區間總和,EXAMPLE: [0,4] 代表 index 0 ~ 4 的總和,其總和為 10,[0,0] 代表 index 0~0 也就是 nums[0] 的本身值。至於樹為什麼長這樣跟 Build tree 有關。
Segment-Tree 實作
-
Build Tree
這邊我用 c++ 概略作介紹。基本上是 top-down 的 build 法,時間複雜度為 O(n)。
class segTreeNode {
public:
int begin, end, sum;
segTreeNode * left = NULL;
segTreeNode * right = NULL;
segTreeNode(int s, int e, int m):begin(s), end(e), sum(m) {}
};
segTreeNode* buildSegTree(int begin, int end, vector& nums) {
if (begin == end) {
auto node = new segTreeNode(begin, begin, nums[begin]);
return node;
}
int mid = (begin + end) / 2;
auto left = buildSegTree(begin, mid, nums);
auto right = buildSegTree(mid+1, end, nums);
auto node = new segTreeNode(begin, end, left->sum + right->sum);
node->left = left;
node->right = right;
return node;
}
-
Update tree
時間複雜度為 O(log n)。
void updateSegTree(segTreeNode* node, int index, int val) {
if (node->begin == index && node->end == index) {
node->sum = val;
return;
}
int mid = (node->begin + node->end) / 2;
if (index > mid)
updateSegTree(node->right, index, val);
else
updateSegTree(node->left, index, val);
node->sum = node->left->sum + node->right->sum;
}
-
Sum
時間複雜度為 O(log n + k)。
int sumSegTree(segTreeNode* node, int left, int right) {
if (node->begin == left && node->end == right)
return node->sum;
int mid = (node->begin + node->end) / 2;
if (right <= mid)
return sumSegTree(node->left, left, right);
else if (left > mid)
return sumSegTree(node->right, left, right);
else
return sumSegTree(node->left, left, mid) +
sumSegTree(node->right, mid+1, right);
}
參考資料 :
1.leetcode/hg3994 answer
2.youtube 中文講解
0 意見:
張貼留言