Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default defineConfig({
nav: [
{ text: '首页', link: '/' },
{ text: '📖 题解', link: '/docs/list/array/1.two-sum' },
{ text: '📖 专题', link: '/docs/topic/0.introduction' }
{ text: '📖 专题', link: '/docs/topic/introduction' }
],

sidebar,
Expand Down
125 changes: 125 additions & 0 deletions src/Unknown/2196.根据描述创建二叉树.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* @lc app=leetcode.cn id=2196 lang=typescript
*
* [2196] 根据描述创建二叉树
*
* https://leetcode.cn/problems/create-binary-tree-from-descriptions/description/
*
* algorithms
* Medium (73.68%)
* Likes: 68
* Dislikes: 0
* Total Accepted: 16.1K
* Total Submissions: 21.2K
* Testcase Example: '[[20,15,1],[20,17,0],[50,20,1],[50,80,0],[80,19,1]]'
*
* 给你一个二维整数数组 descriptions ,其中 descriptions[i] = [parenti, childi, isLefti] 表示
* parenti 是 childi 在 二叉树 中的 父节点,二叉树中各节点的值 互不相同 。此外:
*
*
* 如果 isLefti == 1 ,那么 childi 就是 parenti 的左子节点。
* 如果 isLefti == 0 ,那么 childi 就是 parenti 的右子节点。
*
*
* 请你根据 descriptions 的描述来构造二叉树并返回其 根节点 。
*
* 测试用例会保证可以构造出 有效 的二叉树。
*
*
*
* 示例 1:
*
*
*
*
* 输入:descriptions = [[20,15,1],[20,17,0],[50,20,1],[50,80,0],[80,19,1]]
* 输出:[50,20,80,15,17,19]
* 解释:根节点是值为 50 的节点,因为它没有父节点。
* 结果二叉树如上图所示。
*
*
* 示例 2:
*
*
*
*
* 输入:descriptions = [[1,2,1],[2,3,0],[3,4,1]]
* 输出:[1,2,null,null,3,4]
* 解释:根节点是值为 1 的节点,因为它没有父节点。
* 结果二叉树如上图所示。
*
*
*
* 提示:
*
*
* 1 <= descriptions.length <= 10^4
* descriptions[i].length == 3
* 1 <= parenti, childi <= 10^5
* 0 <= isLefti <= 1
* descriptions 所描述的二叉树是一棵有效二叉树
*
*
*/

// @lc code=start
/**
* Definition for a binary tree node.
* class TreeNode {
* val: number
* left: TreeNode | null
* right: TreeNode | null
* constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
* }
*/

function createBinaryTree(descriptions: number[][]): TreeNode | null {
const nodeMap: Map<number, TreeNode> = new Map();
const parents = new Set<number>();
const childs = new Set<number>();

for (let i = 0; i < descriptions.length; i++) {
const [parent, child, isLeft] = descriptions[i];

parents.add(parent);
childs.add(child);

if (!nodeMap.has(parent)) {
nodeMap.set(parent, new TreeNode(parent));
}
if (!nodeMap.has(child)) {
nodeMap.set(child, new TreeNode(child));
}
const parentNode = nodeMap.get(parent);
const childNode = nodeMap.get(child);
if (isLeft) {
parentNode.left = childNode;
} else {
parentNode.right = childNode;
}
}

for (const p of parents) {
if (!childs.has(p)) {
return nodeMap.get(p)!;
}
}
return null;
}
// @lc code=end

(() => {
const normalize = (root: TreeNode | null): Array<number | null> =>
JSON.parse(Tree.serialize(root)).map((value: number | string | null) =>
value === 'null' || value === null ? null : value
);

LCT.func(createBinaryTree).auto({
judge: (actual: TreeNode | null, expected: Array<number | null>) =>
JSON.stringify(normalize(actual)) === JSON.stringify(expected)
});
})();
83 changes: 63 additions & 20 deletions src/array/42.接雨水.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,34 +48,77 @@

// @lc code=start
function trap(height: number[]): number {
const len = height.length;
const lMax = Array(len).fill(0);
const rMax = Array(len).fill(0);
let res = 0;
const stack: number[] = [];

// base case
lMax[0] = height[0];
rMax[len - 1] = height[len - 1];
for (let i = 0; i < height.length; i++) {
while (stack.length && height[stack[stack.length - 1]] < height[i]) {
const cur = stack.pop();
if (!stack.length) break;
const l = stack[stack.length - 1];
const r = i;
const h = Math.min(height[l], height[r]) - height[cur];
res += (r - l - 1) * h;
}

// Get left max height and right max height for each one
for (let i = 1; i < len; i++) {
lMax[i] = Math.max(height[i], lMax[i - 1]);
}
for (let i = len - 2; i >= 0; i--) {
rMax[i] = Math.max(height[i], rMax[i + 1]);
}

// Calculate
let sum = 0;
// exclude both sides
for (let i = 1; i < len - 1; i++) {
sum += Math.min(lMax[i], rMax[i]) - height[i];
stack.push(i);
}

return sum;
return res;
}
// @lc code=end

(() => {
const height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1];
console.log(trap(height));
})();

// function trap(height: number[]): number {
// let res = 0;
// let l = 0;
// let r = height.length - 1;

// let lMax = 0;
// let rMax = 0;

// while (l < r) {
// lMax = Math.max(lMax, height[l]);
// rMax = Math.max(rMax, height[r]);

// if (lMax < rMax) {
// res += lMax - height[l];
// l++;
// } else {
// res += rMax - height[r];
// r--;
// }
// }
// return res;
// }

// function trap(height: number[]): number {
// const len = height.length;
// const lMax = Array(len).fill(0);
// const rMax = Array(len).fill(0);

// // base case
// lMax[0] = height[0];
// rMax[len - 1] = height[len - 1];

// // Get left max height and right max height for each one
// for (let i = 1; i < len; i++) {
// lMax[i] = Math.max(height[i], lMax[i - 1]);
// }
// for (let i = len - 2; i >= 0; i--) {
// rMax[i] = Math.max(height[i], rMax[i + 1]);
// }

// // Calculate
// let sum = 0;
// // exclude both sides
// for (let i = 1; i < len - 1; i++) {
// sum += Math.min(lMax[i], rMax[i]) - height[i];
// }

// return sum;
// }
36 changes: 30 additions & 6 deletions src/backtracking/22.括号生成.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,21 @@ function generateParenthesis(n: number): string[] {
backtrack('', 0, 0);
return res;

function backtrack(str: string, left: number, right: number) {
if (left === n && right === n) {
// str存已放入的括号串,l, r 表示已经放入左括号和右括号的数量
function backtrack(str: string, l: number, r: number) {
if (l === n && r === n) {
res.push(str);
return;
}
if (left < n) {
backtrack(str + '(', left + 1, right);

// 选择放左括号,条件是还剩左括号可以放
if (l < n) {
backtrack(str + '(', l + 1, r);
}
if (right < left) {
backtrack(str + ')', left, right + 1);
// 选择放右括号, 条件是还剩右括号可以放且子串里已经有多余的左括号了(即右括号比左括号少)
// r<n && r<l 但由于l < n,所以可以简化
if (r < l) {
backtrack(str + ')', l, r + 1);
}
}
}
Expand All @@ -65,3 +71,21 @@ function generateParenthesis(n: number): string[] {
const n = 3;
console.log(generateParenthesis(n));
})();

// function generateParenthesis(n: number): string[] {
// const res: string[] = [];
// backtrack('', 0, 0);
// return res;

// function backtrack(str: string, left: number, right: number) {
// if (left === n && right === n) {
// res.push(str);
// }
// if (left < n) {
// backtrack(str + '(', left + 1, right);
// }
// if (right < left) {
// backtrack(str + ')', left, right + 1);
// }
// }
// }
68 changes: 51 additions & 17 deletions src/backtracking/79.单词搜索.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,44 +66,34 @@
function exist(board: string[][], word: string): boolean {
const m = board.length;
const n = board[0].length;
const wordLen = word.length;
const visited: number[][] = Array(m)
.fill(0)
.map(x => Array(n).fill(0));

for (let i = 0; i < m; i++) {
for (let j = 0; j < n; j++) {
const flag = backtrack(i, j, 0);
// 剪枝:当找到了一次匹配时,不继续进行遍历了
if (flag) return true;
}
}
return false;

function backtrack(i: number, j: number, index: number): boolean {
// 剪枝:数组越界或者被访问过,直接 return
if (i < 0 || i >= m || j < 0 || j >= n || visited[i][j] !== 0) return false;
// 剪枝:当前节点与目标不匹配,直接 return

if (board[i][j] !== word[index]) return false;

// 已经比对到 word 最后一个字符,且当前节点与目标匹配,则说明找到了答案,直接返回true。
if (index === wordLen - 1) {
return true;
}
if (index === word.length - 1) return true;

// 做选择
visited[i][j] = 1;
// 递归
// 剪枝:当发现其中一条路径已经走通,则不进行下面的递归了。
const result =
backtrack(i + 1, j, index + 1) ||
backtrack(i - 1, j, index + 1) ||
const res =
backtrack(i, j + 1, index + 1) ||
backtrack(i, j - 1, index + 1);
// 撤销选择
backtrack(i, j - 1, index + 1) ||
backtrack(i + 1, j, index + 1) ||
backtrack(i - 1, j, index + 1);
visited[i][j] = 0;

return result;
return res;
}
}
// @lc code=end
Expand All @@ -117,3 +107,47 @@ function exist(board: string[][], word: string): boolean {
word = 'ABCB';
console.log(exist(board, word));
})();

// function exist(board: string[][], word: string): boolean {
// const m = board.length;
// const n = board[0].length;
// const wordLen = word.length;
// const visited: number[][] = Array(m)
// .fill(0)
// .map(x => Array(n).fill(0));

// for (let i = 0; i < m; i++) {
// for (let j = 0; j < n; j++) {
// const flag = backtrack(i, j, 0);
// // 剪枝:当找到了一次匹配时,不继续进行遍历了
// if (flag) return true;
// }
// }
// return false;

// function backtrack(i: number, j: number, index: number): boolean {
// // 剪枝:数组越界或者被访问过,直接 return
// if (i < 0 || i >= m || j < 0 || j >= n || visited[i][j] !== 0) return false;
// // 剪枝:当前节点与目标不匹配,直接 return
// if (board[i][j] !== word[index]) return false;

// // 已经比对到 word 最后一个字符,且当前节点与目标匹配,则说明找到了答案,直接返回true。
// if (index === wordLen - 1) {
// return true;
// }

// // 做选择
// visited[i][j] = 1;
// // 递归
// // 剪枝:当发现其中一条路径已经走通,则不进行下面的递归了。
// const result =
// backtrack(i + 1, j, index + 1) ||
// backtrack(i - 1, j, index + 1) ||
// backtrack(i, j + 1, index + 1) ||
// backtrack(i, j - 1, index + 1);
// // 撤销选择
// visited[i][j] = 0;

// return result;
// }
// }
Loading
Loading