1.minmax 面试题

image.png
代码:(就是代码能力),也是比较邪乎的递归解法

  1. function test(mat) {
  2. let rows = mat.length;
  3. let columns = mat[0].length;
  4. let result = [];
  5. let [row, column] = [0, 0];
  6. function goUpRight() {
  7. result.push(mat[row][column]);
  8. while(inMat([row - 1, column + 1])) { // 能走才走
  9. [row, column] = [row - 1, column + 1];
  10. result.push(mat[row][column]);
  11. }
  12. if (inMat([row, column + 1])) { // go right
  13. [row, column] = [row, column + 1];
  14. goDownLeft();
  15. } else if (inMat([row + 1, column])) { // go down
  16. [row, column] = [row + 1, column];
  17. goDownLeft();
  18. }
  19. }
  20. function goDownLeft() {
  21. result.push(mat[row][column]);
  22. while(inMat([row + 1, column - 1])) {
  23. [row, column] = [row + 1, column - 1];
  24. result.push(mat[row][column]);
  25. }
  26. if (inMat([row + 1, column])) { // go down
  27. [row, column] = [row + 1, column];
  28. goUpRight();
  29. } else if (inMat([row, column + 1])) { // go right
  30. [row, column] = [row, column + 1];
  31. goUpRight();
  32. }
  33. }
  34. function inMat([row, column]) {
  35. if (0 <= row && row < rows && 0 <= column && column < columns) {
  36. return true;
  37. }
  38. return false;
  39. }
  40. goUpRight();
  41. return result;
  42. }
  43. test([[1, 2, 3], [4, 5, 6], [7,8,9]]);

2.863. 二叉树中所有距离为 K 的结点

原始状态:我写的,原理简单,但是很难在面试场上做出来

  1. ar distanceK = function(root, target, k) { // 这道题使用了 层遍历 和 dfs,好复杂,把这段时间的训练都使用了
  2. if (k < 0) {
  3. return [];
  4. }
  5. if (k === 0) {
  6. return [target.val];
  7. }
  8. let targetPath = [];
  9. let targetNode = null;
  10. function dfs(node, path) {
  11. if (!node) {
  12. return;
  13. }
  14. if (node.val === target.val) {
  15. targetPath = path;
  16. targetNode = node;
  17. return;
  18. }
  19. dfs(node.left, [node, ...path]);
  20. dfs(node.right, [node, ...path]);
  21. }
  22. dfs(root, []); // 先找到这个 node
  23. if (!targetNode) { // 没找到
  24. return targetPath;
  25. }
  26. function levelWalk(node, from, k) { // 层遍历
  27. if (k <= 0) {
  28. return [];
  29. }
  30. let maxLevel = k;
  31. let queue = [node];
  32. while (queue.length > 0) {
  33. let size = queue.length;
  34. if (maxLevel === 0) {
  35. queue = queue.filter(node => node).map(node => node.val);
  36. return queue;
  37. }
  38. for (let i = 0; i < size; i++) {
  39. node = queue.shift();
  40. if (!node) {
  41. continue;
  42. }
  43. if (node.left !== from) { // 不走回头路
  44. queue.push(node.left);
  45. }
  46. if (node.right !== from ) { // 不走回头路
  47. queue.push(node.right);
  48. }
  49. }
  50. maxLevel--;
  51. }
  52. return [];
  53. }
  54. let ans = levelWalk(targetNode, targetPath[0], k);
  55. let from = targetNode;
  56. while (targetPath.length > 0) {
  57. let parent = targetPath.shift();
  58. if (k === 1) {
  59. ans.push(parent.val);
  60. break;
  61. } else { // k > 1
  62. let _ans = levelWalk(parent, from, --k); // 递归层遍历
  63. ans.push(..._ans);
  64. from = parent;
  65. }
  66. }
  67. return ans;
  68. };

进化形态:
https://leetcode-cn.com/problems/all-nodes-distance-k-in-binary-tree/solution/er-cha-shu-zhong-suo-you-ju-chi-wei-k-de-qbla/

  1. var distanceK = function(root, target, k) {
  2. const parents = new Map();
  3. const ans = [];
  4. const findParents = (node) => {
  5. if (node.left != null) {
  6. parents.set(node.left.val, node);
  7. findParents(node.left);
  8. }
  9. if (node.right != null) {
  10. parents.set(node.right.val, node);
  11. findParents(node.right);
  12. }
  13. }
  14. // 从 root 出发 DFS,记录每个结点的父结点
  15. findParents(root);
  16. const findAns = (node, from, depth, k) => {
  17. if (node == null) {
  18. return;
  19. }
  20. if (depth === k) {
  21. ans.push(node.val);
  22. return;
  23. }
  24. if (node.left !== from) {
  25. findAns(node.left, node, depth + 1, k);
  26. }
  27. if (node.right !== from) {
  28. findAns(node.right, node, depth + 1, k);
  29. }
  30. if (parents.get(node.val) !== from) {
  31. findAns(parents.get(node.val), node, depth + 1, k);
  32. }
  33. }
  34. // 从 target 出发 DFS,寻找所有深度为 k 的结点
  35. findAns(target, null, 0, k);
  36. return ans;
  37. };

最高级形态:
https://leetcode-cn.com/problems/all-nodes-distance-k-in-binary-tree/solution/yi-shu-jian-tu-qi-fa-si-lu-by-fan-hang-9-4spo/

  1. var distanceK = function(root, target, k) {
  2. const parents = new Map();
  3. const ans = [];
  4. parents.set(root, null);
  5. function dfs(node) {
  6. if (!node) {
  7. return;
  8. }
  9. if (node.left) {
  10. parents.set(node.left, node);
  11. dfs(node.left);
  12. }
  13. if (node.right) {
  14. parents.set(node.right, node);
  15. dfs(node.right);
  16. }
  17. }
  18. dfs(root);
  19. const visitedNodes = new Set(); // 就像大火烧过的路径
  20. function search(node, depth) { // dfs 过程增加 深度参数,这也是第一次使用
  21. if (!node) {
  22. return;
  23. }
  24. if (visitedNodes.has(node)) {
  25. return;
  26. }
  27. if (depth === k) {
  28. ans.push(node.val);
  29. return;
  30. }
  31. visitedNodes.add(node);
  32. search(node.left, depth + 1);
  33. search(node.right, depth + 1);
  34. let parent = parents.get(node);
  35. search(parent, depth + 1);
  36. }
  37. search(target, 0);
  38. return ans;
  39. };

3.1110. 删点成林

https://leetcode-cn.com/problems/delete-nodes-and-return-forest/solution/hou-xu-bian-li-yi-chong-jian-dan-de-si-l-5muy/

  1. var delNodes = function(root, to_delete) {
  2. // 利用 后序遍历的性质,无需专门做 parents 的map
  3. // let parents = new Map();
  4. // parents.set(root, null);
  5. // function dfs(node) {
  6. // if (!node) {
  7. // return;
  8. // }
  9. // if (node.left) {
  10. // parents.set(node.left, node);
  11. // dfs(node.left);
  12. // }
  13. // if (node.right) {
  14. // parents.set(node.right, node);
  15. // dfs(node.right);
  16. // }
  17. // }
  18. // dfs(root);
  19. let ans = [root];
  20. let to_delete_set = new Set(to_delete);
  21. function doDelete(node) { // 返回头节点
  22. if (!node) {
  23. return null; // 这里要返回 null 才行,leetcode 内部使用是 ts 来检验,很恶心
  24. }
  25. // 写到前面
  26. node.left = doDelete(node.left);
  27. node.right = doDelete(node.right);
  28. if (to_delete_set.has(node.val)) {
  29. to_delete_set.delete(node.val);
  30. if (ans.includes(node)) {
  31. let index = ans.indexOf(node);
  32. ans.splice(index, 1);
  33. }
  34. if (node.left) {
  35. ans.push(node.left);
  36. }
  37. if (node.right) {
  38. ans.push(node.right);
  39. }
  40. return null;
  41. }
  42. return node;
  43. }
  44. doDelete(root);
  45. return ans;
  46. };

103. 二叉树的锯齿形层序遍历

一般的层序遍历,其实很简单。 和 102. 二叉树的层序遍历 解法一致。

  1. var zigzagLevelOrder = function(root) {
  2. let ans = [];
  3. if (!root) {
  4. return ans;
  5. }
  6. let queue = [root];
  7. let leftToRight = true;
  8. while (queue.length) {
  9. let size = queue.length;
  10. let level = [];
  11. for (let i = 0; i < size; i++) {
  12. let cur = queue.shift();
  13. level.push(cur);
  14. cur.left && queue.push(cur.left); // 只存在有值时,才填入
  15. cur.right && queue.push(cur.right);
  16. }
  17. let tmp = [];
  18. for (let node of level) {
  19. if (leftToRight) {
  20. tmp.push(node.val);
  21. } else {
  22. tmp.unshift(node.val);
  23. }
  24. }
  25. ans.push(tmp);
  26. leftToRight = !leftToRight; // 翻转方向
  27. }
  28. return ans;
  29. };