1.将 N 叉树编码为二叉树(LeetCode 431. hard)
设计一个算法,可以将 N 叉树编码为二叉树,并能将该二叉树解码为原 N 叉树。
解题思路:对于任意节点a,将其所有子节点放在左子树的右边界上。如下图所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| public static class Node { public int val; public List<Node> children;
public Node() { }
public Node(int _val) { val = _val; }
public Node(int _val, List<Node> _children) { val = _val; children = _children; } };
public static class TreeNode { int val; TreeNode left; TreeNode right;
TreeNode(int x) { val = x; } }
class Codec { public TreeNode encode(Node root) { if (root == null) { return null; } TreeNode head = new TreeNode(root.val); head.left = en(root.children); return head; }
private TreeNode en(List<Node> children) { TreeNode head = null; TreeNode cur = null; for (Node child : children) { TreeNode tNode = new TreeNode(child.val); if (head == null) { head = tNode; } else { cur.right = tNode; } cur = tNode; cur.left = en(child.children); } return head; }
public Node decode(TreeNode root) { if (root == null) { return null; } return new Node(root.val, de(root.left)); }
public List<Node> de(TreeNode root) { List<Node> children = new ArrayList<>(); while (root != null) { Node cur = new Node(root.val, de(root.left)); children.add(cur); root = root.right; } return children; } }
|
2.求二叉树最宽的层有多少个节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| public static int maxWidthUseMap(Node head) { if (head == null) { return 0; } Queue<Node> queue = new LinkedList<>(); queue.add(head); Map<Node, Integer> levelMap = new HashMap<>(); levelMap.put(head, 1); int curLevel = 1; int curLevelNodes = 0; int max = 0; while (!queue.isEmpty()) { Node cur = queue.poll(); int curNodeLevel = levelMap.get(cur); if (cur.left != null) { levelMap.put(cur.left, curNodeLevel + 1); queue.add(cur.left); } if (cur.right != null) { levelMap.put(cur.right, curNodeLevel + 1); queue.add(cur.right); } if (curNodeLevel == curLevel) { curLevelNodes++; } else { max = Math.max(max, curLevelNodes); curLevel++; curLevelNodes = 1; } } max = Math.max(max, curLevelNodes); return max; }
public static int maxWidthNoMap(Node head) { if (head == null) { return 0; } Queue<Node> queue = new LinkedList<>(); queue.add(head); Node curEnd = head; Node nextEnd = null; int max = 0; int curLevelNodes = 0; while (!queue.isEmpty()) { Node cur = queue.poll(); if (cur.left != null) { queue.add(cur.left); nextEnd = cur.left; } if (cur.right != null) { queue.add(cur.right); nextEnd = cur.right; } curLevelNodes++; if (cur == curEnd) { max = Math.max(max, curLevelNodes); curLevelNodes = 0; curEnd = nextEnd; } } return max; }
|
3.找到二叉树的后继节点
二叉树结构定义如下:
1 2 3 4 5 6 7 8 9 10
| public static class Node { public int value; public Node left; public Node right; public Node parent;
public Node(int data) { this.value = data; } }
|
要求给定一个二叉树节点,返回此节点的后继节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| public static Node getSuccessorNode(Node node) { if (node == null) { return node; } if (node.right != null) { return getLeftMost(node.right); } else { Node parent = node.parent; while (parent != null && parent.right == node) { node = parent; parent = node.parent; } return parent; } }
public static Node getLeftMost(Node node) { if (node == null) { return node; } while (node.left != null) { node = node.left; } return node; }
|
4.打印纸条折痕问题
请把一张纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。此时折痕是凹下去的,即折痕突起的方向指向纸条的背面。如果从纸条的下边向上方连续对折2次,压出折痕后展开,此时有三条折痕,从上到下依次是下折痕、下折痕和上折痕。
给定一个输入参数N,代表纸条都从下边向上方连续对折N次,请从上到下打印所有折痕的方向。
解题思路:实际折一下,每次对折后给新折痕上标记是第几次对折以及是凹还是凸。
模拟对折几次可以发现,每次对折都是在上一次的每条折痕前新增一条凹折痕,后新增一条凸折痕,形成一个二叉树,折痕的打印即二叉树中序遍历。
如下图所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public static void printAllFolds(int N) { process(1, N, true); System.out.println(); }
public static void process(int i, int N, boolean down) { if (i > N) { return; } process(i + 1, N, true); System.out.print(down ? "凹 " : "凸 "); process(i + 1, N, false); }
|