Merge pull request #2524 from awsome-knowledge/master

refactor
This commit is contained in:
程序员Carl
2024-05-10 10:13:34 +08:00
committed by GitHub
9 changed files with 301 additions and 180 deletions

View File

@ -22,10 +22,12 @@
输入head = [1,2,3,4,5], n = 2 输入head = [1,2,3,4,5], n = 2
输出:[1,2,3,5] 输出:[1,2,3,5]
示例 2 示例 2
输入head = [1], n = 1 输入head = [1], n = 1
输出:[] 输出:[]
示例 3 示例 3
输入head = [1,2], n = 1 输入head = [1,2], n = 1
@ -192,16 +194,18 @@ func removeNthFromEnd(head *ListNode, n int) *ListNode {
* @param {number} n * @param {number} n
* @return {ListNode} * @return {ListNode}
*/ */
var removeNthFromEnd = function(head, n) { var removeNthFromEnd = function (head, n) {
let ret = new ListNode(0, head), // 创建哨兵节点,简化解题逻辑
slow = fast = ret; let dummyHead = new ListNode(0, head);
while(n--) fast = fast.next; let fast = dummyHead;
while (fast.next !== null) { let slow = dummyHead;
fast = fast.next; while (n--) fast = fast.next;
slow = slow.next while (fast.next !== null) {
}; slow = slow.next;
slow.next = slow.next.next; fast = fast.next;
return ret.next; }
slow.next = slow.next.next;
return dummyHead.next;
}; };
``` ```
### TypeScript: ### TypeScript:

View File

@ -469,28 +469,58 @@ func dfs(n int, k int, start int) {
``` ```
### Javascript ### Javascript
未剪枝:
```js
var combine = function (n, k) {
// 回溯法
let result = [],
path = [];
let backtracking = (_n, _k, startIndex) => {
// 终止条件
if (path.length === _k) {
result.push(path.slice());
return;
}
// 循环本层集合元素
for (let i = startIndex; i <= _n; i++) {
path.push(i);
// 递归
backtracking(_n, _k, i + 1);
// 回溯操作
path.pop();
}
};
backtracking(n, k, 1);
return result;
};
```
剪枝: 剪枝:
```javascript ```javascript
let result = [] var combine = function (n, k) {
let path = [] // 回溯法
var combine = function(n, k) { let result = [],
result = [] path = [];
combineHelper(n, k, 1) let backtracking = (_n, _k, startIndex) => {
return result // 终止条件
if (path.length === _k) {
result.push(path.slice());
return;
}
// 循环本层集合元素
for (let i = startIndex; i <= _n - (_k - path.length) + 1; i++) {
path.push(i);
// 递归
backtracking(_n, _k, i + 1);
// 回溯操作
path.pop();
}
};
backtracking(n, k, 1);
return result;
}; };
const combineHelper = (n, k, startIndex) => {
if (path.length === k) {
result.push([...path])
return
}
for (let i = startIndex; i <= n - (k - path.length) + 1; ++i) {
path.push(i)
combineHelper(n, k, i + 1)
path.pop()
}
}
``` ```
### TypeScript ### TypeScript

View File

@ -692,27 +692,29 @@ func levelOrderBottom(root *TreeNode) [][]int {
#### Javascript: #### Javascript:
```javascript ```javascript
var levelOrderBottom = function(root) { var levelOrderBottom = function (root) {
let res = [], queue = []; let res = [],
queue.push(root); queue = [];
while(queue.length && root!==null) { queue.push(root);
// 存放当前层级节点数组 while (queue.length && root !== null) {
let curLevel = []; // 存放当前层级节点数组
// 计算当前层级节点数量 let curLevel = [];
let length = queue.length; // 计算当前层级节点数量
while(length--) { let length = queue.length;
let node = queue.shift(); while (length--) {
// 把当前层节点存入curLevel数组 let node = queue.shift();
curLevel.push(node.val); // 把当前层节点存入curLevel数组
// 把下一层级的左右节点存入queue队列 curLevel.push(node.val);
node.left && queue.push(node.left); // 把下一层级的左右节点存入queue队列
node.right && queue.push(node.right); node.left && queue.push(node.left);
} node.right && queue.push(node.right);
// 从数组前头插入值,避免最后反转数组,减少运算时间
res.unshift(curLevel);
} }
return res; // 从数组前头插入值,避免最后反转数组,减少运算时间
res.unshift(curLevel);
}
return res;
}; };
``` ```
#### TypeScript: #### TypeScript:
@ -1140,7 +1142,7 @@ impl Solution {
### 思路 ### 思路
本题就是层序遍历的时候把一层求个总和取一个均值。 本题就是层序遍历的时候把一层求个总和取一个均值。
C++代码: C++代码:
@ -1295,26 +1297,26 @@ func averageOfLevels(root *TreeNode) []float64 {
```javascript ```javascript
var averageOfLevels = function(root) { var averageOfLevels = function(root) {
//层级平均值 let res = [],
let res = [], queue = []; queue = [];
queue.push(root); queue.push(root);
while (queue.length) {
while(queue.length && root!==null) { // 每一层节点个数;
//每一层节点个数 let lengthLevel = queue.length,
let length = queue.length; len = queue.length,
//sum记录每一层的和 // sum记录每一层的和;
let sum = 0; sum = 0;
for(let i=0; i < length; i++) { while (lengthLevel--) {
let node = queue.shift(); const node = queue.shift();
sum += node.val; sum += node.val;
node.left && queue.push(node.left); // 队列存放下一层节点
node.right && queue.push(node.right); node.left && queue.push(node.left);
} node.right && queue.push(node.right);
//每一层的平均值存入数组res
res.push(sum/length);
} }
// 求平均值
return res; res.push(sum / len);
}
return res;
}; };
``` ```
@ -1925,26 +1927,28 @@ func max(x, y int) int {
#### Javascript #### Javascript
```javascript ```javascript
var largestValues = function(root) { var largestValues = function (root) {
//使用层序遍历 let res = [],
let res = [], queue = []; queue = [];
queue.push(root); queue.push(root);
if (root === null) {
while(root !== null && queue.length) {
//设置max初始值就是队列的第一个元素
let max = queue[0].val;
let length = queue.length;
while(length--) {
let node = queue.shift();
max = max > node.val ? max : node.val;
node.left && queue.push(node.left);
node.right && queue.push(node.right);
}
//把每一层的最大值放到res数组
res.push(max);
}
return res; return res;
}
while (queue.length) {
let lengthLevel = queue.length,
// 初始值设为负无穷大
max = -Infinity;
while (lengthLevel--) {
const node = queue.shift();
// 在当前层中找到最大值
max = Math.max(max, node.val);
// 找到下一层的节点
node.left && queue.push(node.left);
node.right && queue.push(node.right);
}
res.push(max);
}
return res;
}; };
``` ```
@ -2805,21 +2809,23 @@ func maxDepth(root *TreeNode) int {
* @param {TreeNode} root * @param {TreeNode} root
* @return {number} * @return {number}
*/ */
var maxDepth = function(root) { var maxDepth = function (root) {
// 最大深度就是二叉树的层数 // 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
if (root === null) return 0; let max = 0,
let queue = [root]; queue = [root];
let height = 0; if (root === null) {
while (queue.length) { return max;
let n = queue.length; }
height++; while (queue.length) {
for (let i=0; i<n; i++) { max++;
let node = queue.shift(); let length = queue.length;
node.left && queue.push(node.left); while (length--) {
node.right && queue.push(node.right); let node = queue.shift();
} node.left && queue.push(node.left);
node.right && queue.push(node.right);
} }
return height; }
return max;
}; };
``` ```

View File

@ -270,22 +270,21 @@ var minSubArrayLen = function(target, nums) {
```typescript ```typescript
function minSubArrayLen(target: number, nums: number[]): number { function minSubArrayLen(target: number, nums: number[]): number {
let left: number = 0, right: number = 0; let left: number = 0,
let res: number = nums.length + 1; res: number = Infinity,
let sum: number = 0; subLen: number = 0,
while (right < nums.length) { sum: number = 0;
sum += nums[right]; for (let right: number = 0; right < nums.length; right++) {
if (sum >= target) { sum += nums[right];
// 不断移动左指针,直到不能再缩小为止 while (sum >= target) {
while (sum - nums[left] >= target) { subLen = right - left + 1;
sum -= nums[left++]; res = Math.min(res, subLen);
} sum -= nums[left];
res = Math.min(res, right - left + 1); left++;
}
right++;
} }
return res === nums.length + 1 ? 0 : res; }
}; return res === Infinity ? 0 : res;
}
``` ```
### Swift: ### Swift:

View File

@ -417,6 +417,7 @@ func dfs(k, n int, start int, sum int) {
``` ```
### JavaScript ### JavaScript
- 未剪枝:
```js ```js
/** /**
@ -424,32 +425,74 @@ func dfs(k, n int, start int, sum int) {
* @param {number} n * @param {number} n
* @return {number[][]} * @return {number[][]}
*/ */
var combinationSum3 = function(k, n) { var combinationSum3 = function (k, n) {
let res = []; // 回溯法
let path = []; let result = [],
let sum = 0; path = [];
const dfs = (path,index) => { const backtracking = (_k, targetSum, sum, startIndex) => {
// 剪枝操作 // 终止条件
if (sum > n){ if (path.length === _k) {
return if (sum === targetSum) {
} result.push(path.slice());
if (path.length == k) { }
if(sum == n){ // 如果总和不相等,就直接返回
res.push([...path]); return;
return
}
}
for (let i = index; i <= 9 - (k-path.length) + 1;i++) {
path.push(i);
sum = sum + i;
index += 1;
dfs(path,index);
sum -= i
path.pop()
}
} }
dfs(path,1);
return res // 循环当前节点因为只使用数字1到9所以最大是9
for (let i = startIndex; i <= 9; i++) {
path.push(i);
sum += i;
// 回调函数
backtracking(_k, targetSum, sum, i + 1);
// 回溯
sum -= i;
path.pop();
}
};
backtracking(k, n, 0, 1);
return result;
};
```
- 剪枝:
```js
/**
* @param {number} k
* @param {number} n
* @return {number[][]}
*/
var combinationSum3 = function (k, n) {
// 回溯法
let result = [],
path = [];
const backtracking = (_k, targetSum, sum, startIndex) => {
if (sum > targetSum) {
return;
}
// 终止条件
if (path.length === _k) {
if (sum === targetSum) {
result.push(path.slice());
}
// 如果总和不相等,就直接返回
return;
}
// 循环当前节点因为只使用数字1到9所以最大是9
for (let i = startIndex; i <= 9 - (_k - path.length) + 1; i++) {
path.push(i);
sum += i;
// 回调函数
backtracking(_k, targetSum, sum, i + 1);
// 回溯
sum -= i;
path.pop();
}
};
backtracking(k, n, 0, 1);
return result;
}; };
``` ```

View File

@ -48,7 +48,7 @@ void traversal(TreeNode* cur, vector<int>& vec)
if (cur == NULL) return; if (cur == NULL) return;
``` ```
3. **确定单层递归的逻辑**:前序遍历是中左右的序,所以在单层递归的逻辑,是要先取中节点的数值,代码如下: 3. **确定单层递归的逻辑**:前序遍历是中左右的序,所以在单层递归的逻辑,是要先取中节点的数值,代码如下:
```cpp ```cpp
vec.push_back(cur->val); // 中 vec.push_back(cur->val); // 中
@ -290,52 +290,91 @@ func postorderTraversal(root *TreeNode) (res []int) {
前序遍历: 前序遍历:
```Javascript ```Javascript
var preorderTraversal = function(root) { var preorderTraversal = function(root) {
let res=[]; // 第一种
const dfs=function(root){ // let res=[];
if(root===null)return ; // const dfs=function(root){
//先序遍历所以从父节点开始 // if(root===null)return ;
res.push(root.val); // //先序遍历所以从父节点开始
//递归左子树 // res.push(root.val);
dfs(root.left); // //递归左子树
//递归右子树 // dfs(root.left);
dfs(root.right); // //递归右子树
} // dfs(root.right);
//只使用一个参数 使用闭包进行存储结果 // }
dfs(root); // //只使用一个参数 使用闭包进行存储结果
return res; // dfs(root);
// return res;
// 第二种
return root
? [
// 前序遍历:中左右
root.val,
// 递归左子树
...preorderTraversal(root.left),
// 递归右子树
...preorderTraversal(root.right),
]
: [];
}; };
``` ```
中序遍历 中序遍历
```javascript ```javascript
var inorderTraversal = function(root) { var inorderTraversal = function(root) {
let res=[]; // 第一种
const dfs=function(root){
if(root===null){ // let res=[];
return ; // const dfs=function(root){
} // if(root===null){
dfs(root.left); // return ;
res.push(root.val); // }
dfs(root.right); // dfs(root.left);
} // res.push(root.val);
dfs(root); // dfs(root.right);
return res; // }
// dfs(root);
// return res;
// 第二种
return root
? [
// 中序遍历:左中右
// 递归左子树
...inorderTraversal(root.left),
root.val,
// 递归右子树
...inorderTraversal(root.right),
]
: [];
}; };
``` ```
后序遍历 后序遍历
```javascript ```javascript
var postorderTraversal = function(root) { var postorderTraversal = function(root) {
let res=[]; // 第一种
const dfs=function(root){ // let res=[];
if(root===null){ // const dfs=function(root){
return ; // if(root===null){
} // return ;
dfs(root.left); // }
dfs(root.right); // dfs(root.left);
res.push(root.val); // dfs(root.right);
} // res.push(root.val);
dfs(root); // }
return res; // dfs(root);
// return res;
// 第二种
// 后续遍历:左右中
return root
? [
// 递归左子树
...postorderTraversal(root.left),
// 递归右子树
...postorderTraversal(root.right),
root.val,
]
: [];
}; };
``` ```

View File

@ -71,7 +71,7 @@
有递归的地方就有回溯,那么回溯在哪里呢? 有递归的地方就有回溯,那么回溯在哪里呢?
递归函数的下面,例如如下代码: 就递归函数的下面,例如如下代码:
```cpp ```cpp
void dfs(参数) { void dfs(参数) {

View File

@ -16,7 +16,7 @@
**数组是存放在连续内存空间上的相同类型数据的集合。** **数组是存放在连续内存空间上的相同类型数据的集合。**
数组可以方便的通过下标索引的方式获取到下标对应的数据。 数组可以方便的通过下标索引的方式获取到下标对应的数据。
举一个字符数组的例子,如图所示: 举一个字符数组的例子,如图所示:
@ -27,7 +27,7 @@
* **数组下标都是从0开始的。** * **数组下标都是从0开始的。**
* **数组内存空间的地址是连续的** * **数组内存空间的地址是连续的**
正是**因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。** 正是**因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。**
例如删除下标为3的元素需要对下标为3的元素后面的所有元素都要做移动操作如图所示 例如删除下标为3的元素需要对下标为3的元素后面的所有元素都要做移动操作如图所示

View File

@ -16,7 +16,7 @@
**数组是存放在连续内存空间上的相同类型数据的集合。** **数组是存放在连续内存空间上的相同类型数据的集合。**
数组可以方便的通过下标索引的方式获取到下标对应的数据。 数组可以方便的通过下标索引的方式获取到下标对应的数据。
举一个字符数组的例子,如图所示: 举一个字符数组的例子,如图所示:
@ -29,7 +29,7 @@
* **数组下标都是从0开始的。** * **数组下标都是从0开始的。**
* **数组内存空间的地址是连续的** * **数组内存空间的地址是连续的**
正是**因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。** 正是**因为数组在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址。**
例如删除下标为3的元素需要对下标为3的元素后面的所有元素都要做移动操作如图所示 例如删除下标为3的元素需要对下标为3的元素后面的所有元素都要做移动操作如图所示