Compare commits
2 Commits
e7559ec1c7
...
a5e958c203
Author | SHA1 | Date | |
---|---|---|---|
a5e958c203 | |||
11b04202d8 |
31
dynamic-programming/subsequence/1035不相交的线.js
Normal file
31
dynamic-programming/subsequence/1035不相交的线.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* @param {number[]} nums1
|
||||||
|
* @param {number[]} nums2
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
const maxUncrossedLines = function (nums1, nums2) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
这个题看似无从下手实际上非常得简单,我们从结果入手,一个不交叉得最大连线是什么样的,经过观察发现就是要我们求
|
||||||
|
最大公共序列,直接把1143的题目拿过来改一下即可
|
||||||
|
*/
|
||||||
|
|
||||||
|
function f1(nums1, nums2) {
|
||||||
|
const m = nums1.length;
|
||||||
|
const n = nums2.length;
|
||||||
|
|
||||||
|
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
|
||||||
|
|
||||||
|
for (let i = m - 1; i >= 0; i--) {
|
||||||
|
for (let j = n - 1; j >= 0; j--) {
|
||||||
|
if (nums1[i] === nums2[j]) {
|
||||||
|
dp[i][j] = dp[i + 1][j + 1] + 1;
|
||||||
|
} else {
|
||||||
|
dp[i][j] = Math.max(dp[i + 1][j], dp[i][j + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[0][0];
|
||||||
|
}
|
30
dynamic-programming/subsequence/1143最长公共子序列.js
Normal file
30
dynamic-programming/subsequence/1143最长公共子序列.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* @param {string} text1
|
||||||
|
* @param {string} text2
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
const longestCommonSubsequence = function (text1, text2) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
定义dp[i][j]为text1从i位置开始统计,text2从j位置开始统计的最长公共子序列长度,如果text1[i]和text2[j]相等,则dp[i][j]=dp[i+1][j+1]
|
||||||
|
若不相等则,dp[i][j] = max(dp[i+1][j], dp[i][j+1])
|
||||||
|
*/
|
||||||
|
function f1(text1, text2) {
|
||||||
|
const m = text1.length;
|
||||||
|
const n = text2.length;
|
||||||
|
|
||||||
|
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
|
||||||
|
|
||||||
|
for (let i = m - 1; i >= 0; i--) {
|
||||||
|
for (let j = n - 1; j >= 0; j--) {
|
||||||
|
if (text1[i] === text2[j]) {
|
||||||
|
dp[i][j] = dp[i + 1][j + 1] + 1;
|
||||||
|
} else {
|
||||||
|
dp[i][j] = Math.max(dp[i + 1][j], dp[i][j + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[0][0];
|
||||||
|
}
|
30
dynamic-programming/subsequence/392判断子序列.js
Normal file
30
dynamic-programming/subsequence/392判断子序列.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* @param {string} s
|
||||||
|
* @param {string} t
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
const isSubsequence = function (s, t) {
|
||||||
|
return f1(s, t);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
这个题目起始从头到尾遍历开s[1]在不在t中,然后再看s[2]在不在,最后看s[len - 1]在不在,如果在则返回true,
|
||||||
|
这个题目也可以是使用动态规划,动态规划的思路就是,如果s[i]在t中存在,如果s[i+1:]这个子序列也在t中存在,
|
||||||
|
那么s[i:]开始的子序列,在t中也存在,定义dp[i]为,字符串s从i开始的所有子序列s[i:]在t[j]之后的子序列中存在
|
||||||
|
s[i] === t[j]
|
||||||
|
*/
|
||||||
|
function f2(s, t) {
|
||||||
|
if (s.length === 0) return true;
|
||||||
|
if (t.length === 0) return false;
|
||||||
|
|
||||||
|
const dp = Array(s.length).fill(false);
|
||||||
|
|
||||||
|
for (let j = t.length - 1, i = s.length - 1; j >= 0 && i >= 0; j--) {
|
||||||
|
if (t[j] === s[i]) {
|
||||||
|
dp[i] = true;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dp[0];
|
||||||
|
}
|
27
dynamic-programming/subsequence/53最大子数组和.js
Normal file
27
dynamic-programming/subsequence/53最大子数组和.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* @param {number[]} nums
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
const maxSubArray = function (nums) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
定义dp[i]为从nums[i]开始的和最大的子数组,那么动态转移方程为dp[i] = dp[i+1] + nums[i] (dp[i+1] > 0)
|
||||||
|
*/
|
||||||
|
|
||||||
|
function f1(nums) {
|
||||||
|
const dp = Array(nums.length + 1).fill(0); // dp[i]表示从i位置开始的和最大子数组
|
||||||
|
let result = -Infinity;
|
||||||
|
|
||||||
|
for (let i = nums.length - 1; i >= 0; i--) {
|
||||||
|
if (dp[i + 1] > 0) {
|
||||||
|
dp[i] = nums[i] + dp[i + 1];
|
||||||
|
} else {
|
||||||
|
dp[i] = nums[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
result = Math.max(result, dp[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
72
dynamic-programming/subsequence/583两个字符串的删除操作.js
Normal file
72
dynamic-programming/subsequence/583两个字符串的删除操作.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/**
|
||||||
|
* @param {string} word1
|
||||||
|
* @param {string} word2
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
const minDistance = function (word1, word2) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
这个题看似无从下手,其实反过来思考非常容易,直接求出最长的公共子序列,然后步数就是这个两个字符串中多出的那几个字符的和
|
||||||
|
*/
|
||||||
|
|
||||||
|
function f1(word1, word2) {
|
||||||
|
const commonLen = longestCommonSubsequence(word1, word2);
|
||||||
|
return word1.length + word2.length - 2 * commonLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
function longestCommonSubsequence(text1, text2) {
|
||||||
|
const m = text1.length;
|
||||||
|
const n = text2.length;
|
||||||
|
|
||||||
|
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
|
||||||
|
|
||||||
|
for (let i = m - 1; i >= 0; i--) {
|
||||||
|
for (let j = n - 1; j >= 0; j--) {
|
||||||
|
if (text1[i] === text2[j]) {
|
||||||
|
dp[i][j] = dp[i + 1][j + 1] + 1;
|
||||||
|
} else {
|
||||||
|
dp[i][j] = Math.max(dp[i + 1][j], dp[i][j + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[0][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
直接利用动态规划,来求解,定义dp[i][j]为s1中前i个字符和s2中前j个字符,变得相同需要删除的字符数量的最少个数,第i个字符是s1[i-1]
|
||||||
|
同理第j个字符是s2[j-1]注意这里的dp[i][j]的定义是前i个字符,从1开始数的,之所以要这样定义,是因为s1可以为空字符,需要使用dp[0][0]
|
||||||
|
来表示空字符
|
||||||
|
*/
|
||||||
|
|
||||||
|
function f2(word1, word2) {
|
||||||
|
const m = word1.length;
|
||||||
|
const n = word2.length;
|
||||||
|
|
||||||
|
// 定义dp表m+1行,n+1列
|
||||||
|
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); // 初始化成0没有特殊意义,反正都要填表
|
||||||
|
|
||||||
|
// 初始第一行,s1为空字符串,那么当s2有多少个字符就取出多少个,即dp[0][j] = j
|
||||||
|
for (let j = 0; j <= n; j++) {
|
||||||
|
dp[0][j] = j;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 列同理
|
||||||
|
for (let i = 0; i <= m; i++) {
|
||||||
|
dp[i][0] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 填充dp表从上到下,从左到右
|
||||||
|
for (let i = 1; i <= m; i++) {
|
||||||
|
for (let j = 1; j <= n; j++) {
|
||||||
|
if (word1[i - 1] === word2[j - 1]) { // 如果第i个字符和第j个字符相等
|
||||||
|
dp[i][j] = dp[i - 1][j - 1];
|
||||||
|
} else {
|
||||||
|
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dp[m][n];
|
||||||
|
}
|
37
dynamic-programming/subsequence/718最长重复子数组.js
Normal file
37
dynamic-programming/subsequence/718最长重复子数组.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* @param {number[]} nums1
|
||||||
|
* @param {number[]} nums2
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
const findLength = function (nums1, nums2) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
定义:dp[i][j]表示nums1从i开始,nums2从j开始的最长子数组的长度,dp[i][j]可以由两种情况得来,第一种,当nums1[i] !== nums2[j],
|
||||||
|
那么从这个位置开始的子数组,就不可能是公共子数组,多以dp[i][j] = 0;第二种,当nums1[i] === nums2[j] 那么dp[i][j] = 1 + dp[i+1][j+1]
|
||||||
|
得来。
|
||||||
|
*/
|
||||||
|
function f1(nums1, nums2) {
|
||||||
|
const m = nums1.length;
|
||||||
|
const n = nums2.length;
|
||||||
|
let result = 0;
|
||||||
|
// 定义dp表,并且初始化
|
||||||
|
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
|
||||||
|
|
||||||
|
// 按照dp[i][j]的定义我们需要从下到上,从右到左填充dp数组
|
||||||
|
for (let i = m - 1; i >= 0; i--) {
|
||||||
|
for (let j = n - 1; j >= 0; j--) {
|
||||||
|
if (nums1[i] === nums2[j]) {
|
||||||
|
dp[i][j] = 1 + dp[i + 1][j + 1];
|
||||||
|
result = Math.max(result, dp[i][j]);
|
||||||
|
} else {
|
||||||
|
dp[i][j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(dp);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
f1([0, 0, 0, 0, 1], [0, 0, 0, 0, 1]);
|
48
dynamic-programming/subsequence/72编辑距离.js
Normal file
48
dynamic-programming/subsequence/72编辑距离.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* @param {string} word1
|
||||||
|
* @param {string} word2
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
const minDistance = function (word1, word2) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
有删除,添加,修改三种操作,word1的删除和word2的添加效果是一样的,所以实际上只有三种操作
|
||||||
|
1. 往word1中删除一个字符
|
||||||
|
2. 往word2中删除一个字符
|
||||||
|
3. 修改word1中的一个字符
|
||||||
|
|
||||||
|
定义dp[i][j]表示word1的前i个字符和word2的前j个字符的最少编辑距离,那么在已知dp[i-1][j-1]和dp[i-1][j],dp[i][j-1]的情况下推出来
|
||||||
|
如果第word1的第i个字符和word2的第j个字符相等,那么最小编辑距离就是dp[i-1][j-1]因为第i个数和第j个字符我不需要操作,而剩下的这些字符
|
||||||
|
最少编辑距离就是dp[i-1][j-1],如果这word1的第i个字符和word2的第j个字符不相等,我们可以删除word1的第i个字符,然后将word1的前i-1个字符
|
||||||
|
和word2的前j个字符变得一样所需得编辑距离加上删除word1得第i个字符这一步一共是dp[i-1][j] + 1个编辑距离,同理:dp[i][j-1]得原理一样,
|
||||||
|
最后还有一种获得最优得情况是,我不删除,只是将word1中得最后一个字符修改成和word2中卒子后一个字符一样,这样就变成word1[i-1]==word2[j-1]
|
||||||
|
相等得情况了。
|
||||||
|
*/
|
||||||
|
function f1(word1, word2) {
|
||||||
|
const m = word1.length;
|
||||||
|
const n = word2.length;
|
||||||
|
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); // 初始化成0无意义,只是初始化而已
|
||||||
|
|
||||||
|
// 初始化,如果word1为空,word2要想变得和word1一样,编辑距离就是它自身长度
|
||||||
|
for (let j = 0; j <= n; j++) {
|
||||||
|
dp[0][j] = j;
|
||||||
|
}
|
||||||
|
// word2为空同理
|
||||||
|
for (let i = 0; i <= m; i++) {
|
||||||
|
dp[i][0] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 填dp表,dp[i][j] 依赖dp[i-1][j-1], dp[i-1][j], dp[i][j-1],所以要从上到下,从左到右遍历
|
||||||
|
for (let i = 1; i <= m; i++) {
|
||||||
|
for (let j = 1; j <= n; j++) {
|
||||||
|
if (word1[i - 1] === word2[j - 1]) {
|
||||||
|
dp[i][j] = dp[i - 1][j - 1];
|
||||||
|
} else {
|
||||||
|
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dp[m][n];
|
||||||
|
}
|
74
top-interview-leetcode150/binary-tree/102二叉树的层序遍历.js
Normal file
74
top-interview-leetcode150/binary-tree/102二叉树的层序遍历.js
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/**
|
||||||
|
* Definition for a binary tree node.
|
||||||
|
* function TreeNode(val, left, right) {
|
||||||
|
* this.val = (val===undefined ? 0 : val)
|
||||||
|
* this.left = (left===undefined ? null : left)
|
||||||
|
* this.right = (right===undefined ? null : right)
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @param {TreeNode} root
|
||||||
|
* @return {number[][]}
|
||||||
|
*/
|
||||||
|
const levelOrder = function (root) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
层序遍历,无需多言
|
||||||
|
*/
|
||||||
|
function f1(root) {
|
||||||
|
if (!root) return []; // 如果树为空,返回空数组
|
||||||
|
|
||||||
|
const result = []; // 用于存储每一层的节点值
|
||||||
|
const queue = [root]; // 初始化队列,开始时只有根节点
|
||||||
|
|
||||||
|
while (queue.length > 0) {
|
||||||
|
const levelSize = queue.length; // 当前层的节点数
|
||||||
|
const levelValues = []; // 存储当前层节点的值
|
||||||
|
|
||||||
|
// 遍历当前层的所有节点
|
||||||
|
for (let i = 0; i < levelSize; i++) {
|
||||||
|
const node = queue.shift(); // 弹出队列中的第一个节点
|
||||||
|
levelValues.push(node.val); // 将节点值加入当前层的结果
|
||||||
|
|
||||||
|
// 如果节点有左子节点,加入队列
|
||||||
|
if (node.left) queue.push(node.left);
|
||||||
|
// 如果节点有右子节点,加入队列
|
||||||
|
if (node.right) queue.push(node.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将当前层的节点值加入最终结果
|
||||||
|
result.push(levelValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
二叉树的层序遍历老生常谈了,通常使用一个队列来处理,但是js中的数组shift的操作复杂度为O(1),这里我们使用一个head指针来优化,表示
|
||||||
|
shift要弹出的元素
|
||||||
|
*/
|
||||||
|
|
||||||
|
function f2(root) {
|
||||||
|
const ans = []; // 返回的遍历结果
|
||||||
|
|
||||||
|
const queue = []; // 层序遍历使用的队列
|
||||||
|
if (root) queue.push(root);
|
||||||
|
let head = 0; // 队列需要弹出的元素的下标
|
||||||
|
while (head < queue.length) {
|
||||||
|
const n = queue.length - head; // 每一层的元素个数
|
||||||
|
|
||||||
|
// 遍历这一层元素,将值存入levelDatas中
|
||||||
|
const levelDatas = [];
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
const node = queue[head++];
|
||||||
|
levelDatas.push(node.val);
|
||||||
|
// 将左右节点加入下一层
|
||||||
|
if (node.left) queue.push(node.left);
|
||||||
|
if (node.right) queue.push(node.right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ans;
|
||||||
|
}
|
51
top-interview-leetcode150/binary-tree/103二叉树的锯齿形层次bianli.js
Normal file
51
top-interview-leetcode150/binary-tree/103二叉树的锯齿形层次bianli.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* Definition for a binary tree node.
|
||||||
|
* function TreeNode(val, left, right) {
|
||||||
|
* this.val = (val===undefined ? 0 : val)
|
||||||
|
* this.left = (left===undefined ? null : left)
|
||||||
|
* this.right = (right===undefined ? null : right)
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @param {TreeNode} root
|
||||||
|
* @return {number[][]}
|
||||||
|
* https://leetcode.cn/problems/binary-tree-zigzag-level-order-traversal/?envType=study-plan-v2&envId=top-interview-150
|
||||||
|
*/
|
||||||
|
const zigzagLevelOrder = function (root) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
这个题目就是102的变种,只需记录一个遍历,order,如果order为true就从左到右,否则从右到左,这里直接复制102的代码
|
||||||
|
*/
|
||||||
|
|
||||||
|
function f1(root) {
|
||||||
|
if (!root) return []; // 如果树为空,返回空数组
|
||||||
|
|
||||||
|
const result = []; // 用于存储每一层的节点值
|
||||||
|
const queue = [root]; // 初始化队列,开始时只有根节点
|
||||||
|
|
||||||
|
let order = true; // 判断这一层数据是从左到右还是从右到左
|
||||||
|
|
||||||
|
while (queue.length > 0) {
|
||||||
|
const levelSize = queue.length; // 当前层的节点数
|
||||||
|
const levelValues = []; // 存储当前层节点的值
|
||||||
|
|
||||||
|
// 遍历当前层的所有节点
|
||||||
|
for (let i = 0; i < levelSize; i++) {
|
||||||
|
const node = queue.shift(); // 弹出队列中的第一个节点
|
||||||
|
levelValues.push(node.val); // 将节点值加入当前层的结果
|
||||||
|
|
||||||
|
// 如果节点有左子节点,加入队列
|
||||||
|
if (node.left) queue.push(node.left);
|
||||||
|
// 如果节点有右子节点,加入队列
|
||||||
|
if (node.right) queue.push(node.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将当前层的节点值加入最终结果
|
||||||
|
result.push(order ? levelValues : levelSize.reverse());
|
||||||
|
order = !order;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
53
top-interview-leetcode150/binary-tree/199二叉树的右视图.js
Normal file
53
top-interview-leetcode150/binary-tree/199二叉树的右视图.js
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* Definition for a binary tree node.
|
||||||
|
* function TreeNode(val, left, right) {
|
||||||
|
* this.val = (val===undefined ? 0 : val)
|
||||||
|
* this.left = (left===undefined ? null : left)
|
||||||
|
* this.right = (right===undefined ? null : right)
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @param {TreeNode} root
|
||||||
|
* @return {number[]}
|
||||||
|
* https://leetcode.cn/problems/binary-tree-right-side-view/?envType=study-plan-v2&envId=top-interview-150
|
||||||
|
*/
|
||||||
|
const rightSideView = function (root) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
按照题目要求,很容易想到利用层序遍历,将每一层的最后一个结果保存进 ans这个数组,最后返回ans就是我们所需要的答案
|
||||||
|
*/
|
||||||
|
|
||||||
|
function f1(root) {
|
||||||
|
const ans = []; // 储存结果的数组
|
||||||
|
const queue = []; // 层序遍历需要使用的队列
|
||||||
|
if (root) queue.push(root);
|
||||||
|
|
||||||
|
while (queue.length > 0) {
|
||||||
|
// 获取每一层的最后一个元素存入 ans
|
||||||
|
const n = queue.length;
|
||||||
|
ans.push(queue[n - 1].val);
|
||||||
|
|
||||||
|
// 将下一层元素压入队列
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
const node = queue.shift();
|
||||||
|
if (node.left) {
|
||||||
|
queue.push(node.left);
|
||||||
|
}
|
||||||
|
if (node.right) {
|
||||||
|
queue.push(node.right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
思路2: 使用dfs优先遍右子树,将每一层遇到的第一个节点储存到一个map中,当遍历完所有元素,按照层数返回map中的值即可
|
||||||
|
过程:右子树DFS,如果当前节点不为空,查看这一层是否已经有元素了,如果没有那么这个值就是这一层的第一个元素,将他
|
||||||
|
加入映射,
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO:
|
48
top-interview-leetcode150/binary-tree/637二叉树的层平均值.js
Normal file
48
top-interview-leetcode150/binary-tree/637二叉树的层平均值.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* Definition for a binary tree node.
|
||||||
|
* function TreeNode(val, left, right) {
|
||||||
|
* this.val = (val===undefined ? 0 : val)
|
||||||
|
* this.left = (left===undefined ? null : left)
|
||||||
|
* this.right = (right===undefined ? null : right)
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @param {TreeNode} root
|
||||||
|
* @return {number[]}
|
||||||
|
* https://leetcode.cn/problems/average-of-levels-in-binary-tree/?envType=study-plan-v2&envId=top-interview-150
|
||||||
|
*/
|
||||||
|
const averageOfLevels = function (root) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
直接层序遍历,之后对每一层的数据求和,再求平均数(保留五位小数)
|
||||||
|
*/
|
||||||
|
function f1(root) {
|
||||||
|
const queue = [root];
|
||||||
|
const ans = [];
|
||||||
|
|
||||||
|
while (queue.length > 0) {
|
||||||
|
const n = queue.length;
|
||||||
|
let sum = 0; // 每一层数据的和
|
||||||
|
|
||||||
|
// 遍历每一层的所有数据,对它们求和
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
const node = queue.shift();
|
||||||
|
sum += node.val;
|
||||||
|
// 将左右子节点存入下一层
|
||||||
|
if (node.left) queue.push(node.left);
|
||||||
|
if (node.right) queue.push(node.right);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 求平均数,保留五位小数,并存入结果集
|
||||||
|
ans.push(Number((sum / n).toFixed(5)));
|
||||||
|
}
|
||||||
|
return ans;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
使用DFS来遍历,利用一个数组levelData保存如下数据,数组元素的下标表示每一层的信息,元素为一个对象{sum: 这层元素的和, count: 这层元素个数}
|
||||||
|
dfs的时候如果当前层数level小于leveData.length,表示这是新层的第一个数据,就levelData.push({sum: curNode.val, count:1})
|
||||||
|
*/
|
||||||
|
// TODO:
|
Loading…
x
Reference in New Issue
Block a user