1.minmax 面试题

代码:(就是代码能力),也是比较邪乎的递归解法
function test(mat) {let rows = mat.length;let columns = mat[0].length;let result = [];let [row, column] = [0, 0];function goUpRight() {result.push(mat[row][column]);while(inMat([row - 1, column + 1])) { // 能走才走[row, column] = [row - 1, column + 1];result.push(mat[row][column]);}if (inMat([row, column + 1])) { // go right[row, column] = [row, column + 1];goDownLeft();} else if (inMat([row + 1, column])) { // go down[row, column] = [row + 1, column];goDownLeft();}}function goDownLeft() {result.push(mat[row][column]);while(inMat([row + 1, column - 1])) {[row, column] = [row + 1, column - 1];result.push(mat[row][column]);}if (inMat([row + 1, column])) { // go down[row, column] = [row + 1, column];goUpRight();} else if (inMat([row, column + 1])) { // go right[row, column] = [row, column + 1];goUpRight();}}function inMat([row, column]) {if (0 <= row && row < rows && 0 <= column && column < columns) {return true;}return false;}goUpRight();return result;}test([[1, 2, 3], [4, 5, 6], [7,8,9]]);
2.863. 二叉树中所有距离为 K 的结点
原始状态:我写的,原理简单,但是很难在面试场上做出来
ar distanceK = function(root, target, k) { // 这道题使用了 层遍历 和 dfs,好复杂,把这段时间的训练都使用了if (k < 0) {return [];}if (k === 0) {return [target.val];}let targetPath = [];let targetNode = null;function dfs(node, path) {if (!node) {return;}if (node.val === target.val) {targetPath = path;targetNode = node;return;}dfs(node.left, [node, ...path]);dfs(node.right, [node, ...path]);}dfs(root, []); // 先找到这个 nodeif (!targetNode) { // 没找到return targetPath;}function levelWalk(node, from, k) { // 层遍历if (k <= 0) {return [];}let maxLevel = k;let queue = [node];while (queue.length > 0) {let size = queue.length;if (maxLevel === 0) {queue = queue.filter(node => node).map(node => node.val);return queue;}for (let i = 0; i < size; i++) {node = queue.shift();if (!node) {continue;}if (node.left !== from) { // 不走回头路queue.push(node.left);}if (node.right !== from ) { // 不走回头路queue.push(node.right);}}maxLevel--;}return [];}let ans = levelWalk(targetNode, targetPath[0], k);let from = targetNode;while (targetPath.length > 0) {let parent = targetPath.shift();if (k === 1) {ans.push(parent.val);break;} else { // k > 1let _ans = levelWalk(parent, from, --k); // 递归层遍历ans.push(..._ans);from = parent;}}return ans;};
var distanceK = function(root, target, k) {const parents = new Map();const ans = [];const findParents = (node) => {if (node.left != null) {parents.set(node.left.val, node);findParents(node.left);}if (node.right != null) {parents.set(node.right.val, node);findParents(node.right);}}// 从 root 出发 DFS,记录每个结点的父结点findParents(root);const findAns = (node, from, depth, k) => {if (node == null) {return;}if (depth === k) {ans.push(node.val);return;}if (node.left !== from) {findAns(node.left, node, depth + 1, k);}if (node.right !== from) {findAns(node.right, node, depth + 1, k);}if (parents.get(node.val) !== from) {findAns(parents.get(node.val), node, depth + 1, k);}}// 从 target 出发 DFS,寻找所有深度为 k 的结点findAns(target, null, 0, k);return ans;};
var distanceK = function(root, target, k) {const parents = new Map();const ans = [];parents.set(root, null);function dfs(node) {if (!node) {return;}if (node.left) {parents.set(node.left, node);dfs(node.left);}if (node.right) {parents.set(node.right, node);dfs(node.right);}}dfs(root);const visitedNodes = new Set(); // 就像大火烧过的路径function search(node, depth) { // dfs 过程增加 深度参数,这也是第一次使用if (!node) {return;}if (visitedNodes.has(node)) {return;}if (depth === k) {ans.push(node.val);return;}visitedNodes.add(node);search(node.left, depth + 1);search(node.right, depth + 1);let parent = parents.get(node);search(parent, depth + 1);}search(target, 0);return ans;};
3.1110. 删点成林
var delNodes = function(root, to_delete) {// 利用 后序遍历的性质,无需专门做 parents 的map// let parents = new Map();// parents.set(root, null);// function dfs(node) {// if (!node) {// return;// }// if (node.left) {// parents.set(node.left, node);// dfs(node.left);// }// if (node.right) {// parents.set(node.right, node);// dfs(node.right);// }// }// dfs(root);let ans = [root];let to_delete_set = new Set(to_delete);function doDelete(node) { // 返回头节点if (!node) {return null; // 这里要返回 null 才行,leetcode 内部使用是 ts 来检验,很恶心}// 写到前面node.left = doDelete(node.left);node.right = doDelete(node.right);if (to_delete_set.has(node.val)) {to_delete_set.delete(node.val);if (ans.includes(node)) {let index = ans.indexOf(node);ans.splice(index, 1);}if (node.left) {ans.push(node.left);}if (node.right) {ans.push(node.right);}return null;}return node;}doDelete(root);return ans;};
103. 二叉树的锯齿形层序遍历
一般的层序遍历,其实很简单。 和 102. 二叉树的层序遍历 解法一致。
var zigzagLevelOrder = function(root) {let ans = [];if (!root) {return ans;}let queue = [root];let leftToRight = true;while (queue.length) {let size = queue.length;let level = [];for (let i = 0; i < size; i++) {let cur = queue.shift();level.push(cur);cur.left && queue.push(cur.left); // 只存在有值时,才填入cur.right && queue.push(cur.right);}let tmp = [];for (let node of level) {if (leftToRight) {tmp.push(node.val);} else {tmp.unshift(node.val);}}ans.push(tmp);leftToRight = !leftToRight; // 翻转方向}return ans;};
