活跃农民
- 积分
- 511
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2013-6-5
- 最后登录
- 1970-1-1
|
0103 4. Falling Squares
/**
* @param {number[][]} positions
* @return {number[]}
*/
var fallingSquares = function(positions) {
class TreeNode {
constructor (start, end) {
this.start = start;
this.end = end;
this.left = this.right = null;
this.max = 0;
}
}
if (positions == null || positions.length === 0) {
return [];
}
// first, discretize the positions into a list of points, AND sort them
const points = positions.map(([start, len]) => [start, start + len - 1]).reduce((prev, curr) => [...prev, ...curr]).sort((a, b) => a - b);
const map = new Map(points.map((value, index) => [value, index]));
// build a segment tree from the points
const buildTree = (start, end) => {
const node = new TreeNode(start, end);
if (start === end) {
return node;
} else {
const mid = start + Math.trunc( (end - start) / 2 );
node.left = buildTree(start, mid);
node.right = buildTree(mid + 1, end);
return node;
}
}
const root = buildTree(0, points.length - 1);
// now get all the points loop them and update the tree
const updateTree = (node, start, end, val) => {
node.max = Math.max(node.max, val);
if (node.start == node.end && start == end && start == node.start) { // leaf, stop
node.max = val;
return;
} else { // not leaf, go left, right, or both
const mid = node.start + Math.trunc( (node.end - node.start) / 2 ); // !!!! node.start, node.end, not start and end
if (end <= mid) {
// on the left
updateTree(node.left, start, end, val);
} else if (start > mid) {
// on the right
updateTree(node.right, start, end, val);
} else {
// spans both
updateTree(node.left, start, mid, val);
updateTree(node.right, mid + 1, end, val);
}
}
}
const queryTree = (node, start, end) => {
// need a full match to guarantee
if (node.start === start && node.end === end) {
return node.max;
} else {
const mid = node.start + Math.trunc( (node.end - node.start) / 2 ); // !!!! start + , not end +, this could cause errors, 得不偿失,一定要熟悉才用。
if (end <= mid) {
// on the left
return queryTree(node.left, start, end);
} else if (start > mid) {
// on the right
return queryTree(node.right, start, end);
} else {
// both
const leftVal = queryTree(node.left, start, mid);
const rightVal = queryTree(node.right, mid + 1, end);
return Math.max(leftVal, rightVal);
}
}
}
// we might need a map to get the index from the points values
const ans = [];
for (let [startPos, len] of positions) {
// !!!! map values to indexed values !!!! index compression!!!
const endPos = startPos + len - 1;
const start = map.get(startPos);
const end = map.get(endPos);
// first, query the value to get the real value
const val = len;
const oldVal = queryTree(root, start, end);
const newVal = oldVal + val;
updateTree(root, start, end, newVal);
ans.push(root.max);
}
return ans;
};
Learn more about lazy propagation |
|