From 97cd84d47870a8ab2aad30838b9ebc1a9a450099 Mon Sep 17 00:00:00 2001 From: zcxzcxzcx <18810692826@163.com> Date: Sun, 2 Jan 2022 22:16:26 +0800 Subject: [PATCH 1/5] =?UTF-8?q?Create=200093.=E5=A4=8D=E5=8E=9FIP=E5=9C=B0?= =?UTF-8?q?=E5=9D=80.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 优化时间复杂度,更好地剪枝(java版本) --- problems/0093.复原IP地址.md | 42 +++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/problems/0093.复原IP地址.md b/problems/0093.复原IP地址.md index 3e7cd1ad..67bb1bbe 100644 --- a/problems/0093.复原IP地址.md +++ b/problems/0093.复原IP地址.md @@ -304,6 +304,48 @@ class Solution { return true; } } + +//方法二:比上面的方法时间复杂度低,更好地剪枝,优化时间复杂度 +class Solution { + List result = new ArrayList(); + StringBuilder stringBuilder = new StringBuilder(); + + public List restoreIpAddresses(String s) { + restoreIpAddressesHandler(s, 0, 0); + return result; + } + + // number表示stringbuilder中ip段的数量 + public void restoreIpAddressesHandler(String s, int start, int number) { + // 如果start等于s的长度并且ip段的数量是4,则加入结果集,并返回 + if (start == s.length() && number == 4) { + result.add(stringBuilder.toString()); + return; + } + // 如果start等于s的长度但是ip段的数量不为4,或者ip段的数量为4但是start小于s的长度,则直接返回 + if (start == s.length() || number == 4) { + return; + } + // 剪枝:ip段的长度最大是3,并且ip段处于[0,255] + for (int i = start; i < s.length() && i - start < 3 && Integer.parseInt(s.substring(start, i + 1)) >= 0 + && Integer.parseInt(s.substring(start, i + 1)) <= 255; i++) { + // 如果ip段的长度大于1,并且第一位为0的话,continue + if (i + 1 - start > 1 && s.charAt(start) - '0' == 0) { + continue; + } + stringBuilder.append(s.substring(start, i + 1)); + // 当stringBuilder里的网段数量小于3时,才会加点;如果等于3,说明已经有3段了,最后一段不需要再加点 + if (number < 3) { + stringBuilder.append("."); + } + number++; + restoreIpAddressesHandler(s, i + 1, number); + number--; + // 删除当前stringBuilder最后一个网段,注意考虑点的数量的问题 + stringBuilder.delete(start + number, i + number + 2); + } + } +} ``` ## python From 71dd3eab9e9a005eec5669bfc25ba3cd4d27fb2f Mon Sep 17 00:00:00 2001 From: Luo <82520819+Jerry-306@users.noreply.github.com> Date: Fri, 11 Feb 2022 11:26:14 +0800 Subject: [PATCH 2/5] =?UTF-8?q?0059=20=20=E8=9E=BA=E6=97=8B=E7=9F=A9?= =?UTF-8?q?=E9=98=B5II=20=20=E9=A2=98=E7=9B=AE=E9=94=99=E8=AF=AF=E7=BA=A0?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0059.螺旋矩阵II.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0059.螺旋矩阵II.md b/problems/0059.螺旋矩阵II.md index 3f7a59ca..ff654358 100644 --- a/problems/0059.螺旋矩阵II.md +++ b/problems/0059.螺旋矩阵II.md @@ -10,7 +10,7 @@ [力扣题目链接](https://leetcode-cn.com/problems/spiral-matrix-ii/) -给定一个正整数 n,生成一个包含 1 到 $n^2$ 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。 +给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。 示例: From fbf52ee2bf0cad8c4231311ef2d87fc383a49a3c Mon Sep 17 00:00:00 2001 From: Luo <82520819+Jerry-306@users.noreply.github.com> Date: Fri, 11 Feb 2022 16:57:22 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E7=AE=97=E6=B3=95=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20typescript=20=E7=89=88=E6=9C=AC=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/算法模板.md | 265 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 264 insertions(+), 1 deletion(-) diff --git a/problems/算法模板.md b/problems/算法模板.md index a4136511..789d8f80 100644 --- a/problems/算法模板.md +++ b/problems/算法模板.md @@ -394,7 +394,7 @@ var postorder = function (root, list) { ```javascript var preorderTraversal = function (root) { let res = []; - if (root === null) return rs; + if (root === null) return res; let stack = [root], cur = null; while (stack.length) { @@ -536,6 +536,269 @@ function backtracking(参数) { } ``` +TypeScript: + +## 二分查找法 + +使用左闭右闭区间 + +```typescript +var search = function (nums: number[], target: number): number { + let left: number = 0, right: number = nums.length - 1; + // 使用左闭右闭区间 + while (left <= right) { + let mid: number = left + Math.floor((right - left)/2); + if (nums[mid] > target) { + right = mid - 1; // 去左面闭区间寻找 + } else if (nums[mid] < target) { + left = mid + 1; // 去右面闭区间寻找 + } else { + return mid; + } + } + return -1; +}; +``` + +使用左闭右开区间 + +```typescript +var search = function (nums: number[], target: number): number { + let left: number = 0, right: number = nums.length; + // 使用左闭右开区间 [left, right) + while (left < right) { + let mid: number = left + Math.floor((right - left)/2); + if (nums[mid] > target) { + right = mid; // 去左面闭区间寻找 + } else if (nums[mid] < target) { + left = mid + 1; // 去右面闭区间寻找 + } else { + return mid; + } + } + return -1; +}; +``` + +## KMP + +```typescript +var kmp = function (next: number[], s: number): void { + next[0] = -1; + let j: number = -1; + for(let i: number = 1; i < s.length; i++){ + while (j >= 0 && s[i] !== s[j + 1]) { + j = next[j]; + } + if (s[i] === s[j + 1]) { + j++; + } + next[i] = j; + } +} +``` + +## 二叉树 + +### 深度优先遍历(递归) + +二叉树节点定义: + +```typescript +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) + } +} +``` + +前序遍历(中左右): + +```typescript +var preorder = function (root: TreeNode | null, list: number[]): void { + if (root === null) return; + list.push(root.val); // 中 + preorder(root.left, list); // 左 + preorder(root.right, list); // 右 +} +``` + +中序遍历(左中右): + +```typescript +var inorder = function (root: TreeNode | null, list: number[]): void { + if (root === null) return; + inorder(root.left, list); // 左 + list.push(root.val); // 中 + inorder(root.right, list); // 右 +} +``` + +后序遍历(左右中): + +```typescript +var postorder = function (root: TreeNode | null, list: number[]): void { + if (root === null) return; + postorder(root.left, list); // 左 + postorder(root.right, list); // 右 + list.push(root.val); // 中 +} +``` + +### 深度优先遍历(迭代) + +前序遍历(中左右): + +```typescript +var preorderTraversal = function (root: TreeNode | null): number[] { + let res: number[] = []; + if (root === null) return res; + let stack: TreeNode[] = [root], + cur: TreeNode | null = null; + while (stack.length) { + cur = stack.pop(); + res.push(cur.val); + cur.right && stack.push(cur.right); + cur.left && stack.push(cur.left); + } + return res; +}; +``` + +中序遍历(左中右): + +```typescript +var inorderTraversal = function (root: TreeNode | null): number[] { + let res: number[] = []; + if (root === null) return res; + let stack: TreeNode[] = []; + let cur: TreeNode | null = root; + while (stack.length !== 0 || cur !== null) { + if (cur !== null) { + stack.push(cur); + cur = cur.left; + } else { + cur = stack.pop(); + res.push(cur.val); + cur = cur.right; + } + } + return res; +}; +``` + +后序遍历(左右中): + +```typescript +var postorderTraversal = function (root: TreeNode | null): number[] { + let res: number[] = []; + if (root === null) return res; + let stack: TreeNode[] = [root]; + let cur: TreeNode | null = null; + while (stack.length) { + cur = stack.pop(); + res.push(cur.val); + cur.left && stack.push(cur.left); + cur.right && stack.push(cur.right); + } + return res.reverse() +}; +``` + +### 广度优先遍历(队列) + +```typescript +var levelOrder = function (root: TreeNode | null): number[] { + let res: number[] = []; + if (root === null) return res; + let queue: TreeNode[] = [root]; + while (queue.length) { + let n: number = queue.length; + let temp: number[] = []; + for (let i: number = 0; i < n; i++) { + let node: TreeNode = queue.shift(); + temp.push(node.val); + node.left && queue.push(node.left); + node.right && queue.push(node.right); + } + res.push(temp); + } + return res; +}; +``` + +### 二叉树深度 + +```typescript +var getDepth = function (node: TreNode | null): number { + if (node === null) return 0; + return 1 + Math.max(getDepth(node.left), getDepth(node.right)); +} +``` + +### 二叉树节点数量 + +```typescript +var countNodes = function (root: TreeNode | null): number { + if (root === null) return 0; + return 1 + countNodes(root.left) + countNodes(root.right); +} +``` + +## 回溯算法 + +```typescript +function backtracking(参数) { + if (终止条件) { + 存放结果; + return; + } + + for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) { + 处理节点; + backtracking(路径,选择列表); // 递归 + 回溯,撤销处理结果 + } +} + +``` + +## 并查集 + +```typescript + let n: number = 1005; // 根据题意而定 + let father: number[] = new Array(n).fill(0); + + // 并查集初始化 + function init () { + for (int i: number = 0; i < n; ++i) { + father[i] = i; + } + } + // 并查集里寻根的过程 + function find (u: number): number { + return u === father[u] ? u : father[u] = find(father[u]); + } + // 将v->u 这条边加入并查集 + function join(u: number, v: number) { + u = find(u); + v = find(v); + if (u === v) return ; + father[v] = u; + } + // 判断 u 和 v是否找到同一个根 + function same(u: number, v: number): boolean { + u = find(u); + v = find(v); + return u === v; + } +``` + Java: From 3652d00e542fc251d479a66eb676c8e1ac910f45 Mon Sep 17 00:00:00 2001 From: Luo <82520819+Jerry-306@users.noreply.github.com> Date: Thu, 24 Feb 2022 17:49:15 +0800 Subject: [PATCH 4/5] =?UTF-8?q?0104=20=E4=BA=8C=E5=8F=89=E6=A0=91=E6=9C=80?= =?UTF-8?q?=E5=A4=A7=E6=B7=B1=E5=BA=A6=20=E9=83=A8=E5=88=86=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E4=B9=A6=E5=86=99=E9=94=99=E8=AF=AF=E7=BA=A0=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 函数错误,逻辑错误 --- problems/0104.二叉树的最大深度.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/problems/0104.二叉树的最大深度.md b/problems/0104.二叉树的最大深度.md index 3eecdc92..2229a854 100644 --- a/problems/0104.二叉树的最大深度.md +++ b/problems/0104.二叉树的最大深度.md @@ -523,8 +523,8 @@ func maxdepth(root *treenode) int { ```javascript var maxdepth = function(root) { - if (!root) return root - return 1 + math.max(maxdepth(root.left), maxdepth(root.right)) + if (root === null) return 0; + return 1 + Math.max(maxdepth(root.left), maxdepth(root.right)) }; ``` @@ -541,7 +541,7 @@ var maxdepth = function(root) { //3. 确定单层逻辑 let leftdepth=getdepth(node.left); let rightdepth=getdepth(node.right); - let depth=1+math.max(leftdepth,rightdepth); + let depth=1+Math.max(leftdepth,rightdepth); return depth; } return getdepth(root); @@ -591,7 +591,9 @@ var maxDepth = function(root) { count++ while(size--) { let node = queue.shift() - node && (queue = [...queue, ...node.children]) + for (let item of node.children) { + item && queue.push(item); + } } } return count From 14f91a53702d8df5e1a587e757f739b5df55bb8f Mon Sep 17 00:00:00 2001 From: Luo <82520819+Jerry-306@users.noreply.github.com> Date: Fri, 25 Feb 2022 10:37:17 +0800 Subject: [PATCH 5/5] =?UTF-8?q?0404=20=E5=B7=A6=E5=8F=B6=E5=AD=90=E4=B9=8B?= =?UTF-8?q?=E5=92=8C=20=20=E5=B7=A6=E5=8F=B6=E5=AD=90=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problems/0404.左叶子之和.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problems/0404.左叶子之和.md b/problems/0404.左叶子之和.md index 09272052..691c0f37 100644 --- a/problems/0404.左叶子之和.md +++ b/problems/0404.左叶子之和.md @@ -19,7 +19,7 @@ **首先要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。** -因为题目中其实没有说清楚左叶子究竟是什么节点,那么我来给出左叶子的明确定义:**如果左节点不为空,且左节点没有左右孩子,那么这个节点就是左叶子** +因为题目中其实没有说清楚左叶子究竟是什么节点,那么我来给出左叶子的明确定义:**如果左节点不为空,且左节点没有左右孩子,那么这个节点的左节点就是左叶子** 大家思考一下如下图中二叉树,左叶子之和究竟是多少?