From a97d3a58588378d13a9e164a52c30d31d9908660 Mon Sep 17 00:00:00 2001 From: Leo <582717189@qq.com> Date: Thu, 10 Dec 2020 10:13:45 +0800 Subject: [PATCH] class11 --- .../Code02_SerializeAndReconstructTree.java | 4 +- .../EncodeNaryTreeToBinaryTree.java | 243 +++++++++++++++++ src/leo/class07_11/LevelTraversalBT.java | 147 +++++++++++ src/leo/class07_11/PaperFolding.java | 35 +++ .../SerializeAndReconstructTree.java | 245 ++++++++++++++++++ src/leo/class07_11/SuccessorNode.java | 111 ++++++++ src/leo/class07_11/TreeMaxWidth.java | 130 ++++++++++ 7 files changed, 913 insertions(+), 2 deletions(-) create mode 100644 src/leo/class07_11/EncodeNaryTreeToBinaryTree.java create mode 100644 src/leo/class07_11/LevelTraversalBT.java create mode 100644 src/leo/class07_11/PaperFolding.java create mode 100644 src/leo/class07_11/SerializeAndReconstructTree.java create mode 100644 src/leo/class07_11/SuccessorNode.java create mode 100644 src/leo/class07_11/TreeMaxWidth.java diff --git a/src/class07_11/Code02_SerializeAndReconstructTree.java b/src/class07_11/Code02_SerializeAndReconstructTree.java index af5e5de..4289ce0 100644 --- a/src/class07_11/Code02_SerializeAndReconstructTree.java +++ b/src/class07_11/Code02_SerializeAndReconstructTree.java @@ -19,7 +19,7 @@ public class Code02_SerializeAndReconstructTree { * \ * 2 * 补足空位置的中序遍历结果都是{ null, 1, null, 2, null} - * + * * */ public static class Node { public int value; @@ -259,6 +259,6 @@ public class Code02_SerializeAndReconstructTree { } } System.out.println("test finish!"); - + } } diff --git a/src/leo/class07_11/EncodeNaryTreeToBinaryTree.java b/src/leo/class07_11/EncodeNaryTreeToBinaryTree.java new file mode 100644 index 0000000..0b68ac3 --- /dev/null +++ b/src/leo/class07_11/EncodeNaryTreeToBinaryTree.java @@ -0,0 +1,243 @@ +package leo.class07_11; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Leo + * @ClassName EncodeNaryTreeToBinaryTree + * @DATE 2020/12/9 5:30 下午 + * @Description + * 本题测试链接:https://leetcode.com/problems/encode-n-ary-tree-to-binary-tree + * 将多个子节点树序列化和反序列化为二叉树 + */ +public class EncodeNaryTreeToBinaryTree { + + public static class Node { + public int val; + public List children; + + public Node() { + } + + public Node(int _val) { + val = _val; + } + + public Node(int _val, List _children) { + val = _val; + children = _children; + } + } + public static class TreeNode { + int val; + TreeNode left; + TreeNode right; + + TreeNode(int x) { + val = x; + } + } + + static class Codec { + // Encodes an n-ary tree to a binary tree. + public static TreeNode encode(Node root) { + if (root == null) { + return null; + } + TreeNode head = new TreeNode(root.val); + head.left = en(root.children); + return head; + } + + private static TreeNode en(List 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; + } + + + + // Decodes your binary tree to an n-ary tree. + public static Node decode(TreeNode root) { + if (root == null) { + return null; + } + return new Node(root.val, de(root.left)); + } + + public static List de(TreeNode root) { + List children = new ArrayList<>(); + while (root != null) { + Node cur = new Node(root.val, de(root.left)); + children.add(cur); + root = root.right; + } + return children; + } + + } + + static class Codec1 { + + public static TreeNode encode(Node root){ + if (root == null) { + return null; + } + TreeNode head = new TreeNode(root.val); + head.left = encode(root.children); + return head; + } + + private static TreeNode encode(List 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 = encode(child.children); + } + return head; + } + + public static Node decode(TreeNode root){ + if (root == null) { + return null; + } + Node head = new Node(root.val); + head.children = de(root.left); + return head; + } + + private static List de (TreeNode root) { + List children = new ArrayList<>(); + while (root != null) { + Node node = new Node(root.val, de(root.left)); + children.add(node); + root = root.right; + } + return children; + + } + + } + + static class Codec2{ + public static TreeNode encode(Node root){ + if (root == null) { + return null; + } + TreeNode head = new TreeNode(root.val); + head.left = encode(root.children); + return head; + } + + private static TreeNode encode(List children) { + TreeNode head = null; + TreeNode cur = null; + for (Node child : children) { + TreeNode node = new TreeNode(child.val); + if (head == null) { + head = node; + }else { + cur.right = node; + } + cur = node; + cur.left = encode(child.children); + } + return head; + } + + public static Node decode(TreeNode root){ + if (root == null) { + return null; + } + Node head = new Node(root.val); + head.children = de(root.left); + return head; + } + public static List de(TreeNode root){ + if (root == null) { + return null; + } + List children = new ArrayList<>(); + + while (root != null) { + Node node = new Node(root.val, de(root.left)); + children.add(node); + root = root.right; + } + return children; + + } + } + + static class EncodeNaryTreeToBinaryTree_Main { + + public static void main(String[] args){ + int maxLevel = 10; + int range = 50; + int test = 100000; + System.out.println("start"); + for (int i = 0; i < test; i++) { + TreeNode node = generateRandomNode(maxLevel, range); + Node decodeOrigin = Codec1.decode(node); + TreeNode encodeOrigin = Codec1.encode(decodeOrigin); + Node decode = Codec1.decode(encodeOrigin); + TreeNode treeNode = Codec1.encode(decode); + if (!isEqualsNode(treeNode, encodeOrigin)) { + System.out.println("fuck!"); + } + + } + System.out.println("end"); + } + + + public static TreeNode generateRandomNode(int maxLevel, int range) { + return generate(1, maxLevel, range); + } + + public static TreeNode generate(int curLevel, int maxLevel, int range) { + if (curLevel > maxLevel || Math.random() < 0.5) { + return null; + } + TreeNode head = new TreeNode((int) (range * Math.random() )); + head.left = generate(curLevel + 1, maxLevel, range); + head.right = generate(curLevel + 1, maxLevel, range); + return head; + } + + public static boolean isEqualsNode(TreeNode head1, TreeNode head2) { + if (head1 != null && head2 == null) { + return false; + } + if (head1 == null && head2 != null) { + return false; + } + if (head1 == null && head2 == null) { + return true; + } + if (head1.val != head2.val) { + return false; + } + return isEqualsNode(head1.left, head2.left) && isEqualsNode(head1.right, head2.right); + } + } +} + diff --git a/src/leo/class07_11/LevelTraversalBT.java b/src/leo/class07_11/LevelTraversalBT.java new file mode 100644 index 0000000..0f7f0a5 --- /dev/null +++ b/src/leo/class07_11/LevelTraversalBT.java @@ -0,0 +1,147 @@ +package leo.class07_11; + + +import leo.class07_10.TreeNode; + +import java.util.LinkedList; +import java.util.Queue; + +/** + * &author Leo + * &ClassName LevelTraversalBT + * &DATE 2020/12/9 2:11 下午 + * &Description 二叉树宽度(按层)遍历 queue + */ +public class LevelTraversalBT { + static class Node{ + int value; + Node left; + Node right; + + public Node(int value) { + this.value = value; + } + + } + + + public static void level(Node head) { + if (head == null) { + return; + } + Node cur = head; + Queue queue = new LinkedList<>(); + queue.offer(cur); + while (!queue.isEmpty()) { + cur = queue.poll(); + System.out.print(cur.value + " "); + if (cur.left != null) { + queue.offer(cur.left); + } + if (cur.right != null) { + queue.offer(cur.right); + } + } + System.out.println(); + + } + + public static void level1(Node head) { + if (head == null) { + return; + } + Queue queue = new LinkedList<>(); + Node cur = head; + queue.offer(cur); + while (!queue.isEmpty()) { + cur = queue.poll(); + System.out.print(cur.value + " "); + if (cur.left != null) { + queue.offer(cur.left); + } + if (cur.right != null) { + queue.offer(cur.right); + } + } + System.out.println(); + } + + + public static void level2(Node head) { + if (head == null) { + return; + } + Queue queue = new LinkedList<>(); + Node cur = head; + queue.offer(cur); + while (!queue.isEmpty()) { + cur = queue.poll(); + System.out.print(cur.value + " "); + if (cur.left != null) { + queue.offer(cur.left); + } + if (cur.right != null) { + queue.offer(cur.right); + } + } + System.out.println(); + } + + public static void level3(Node head) { + if (head == null) { + return; + } + Queue queue = new LinkedList<>(); + Node cur = head; + queue.offer(cur); + while (!queue.isEmpty()) { + cur = queue.poll(); + System.out.print(cur.value + " "); + if (cur.left != null) { + queue.offer(cur.left); + } + if (cur.right != null) { + queue.offer(cur.right); + } + } + System.out.println(); + } + + public static void main(String[] args){ + Node node = randomTreeNode(10); + level3(node); + } + + + public static Node randomTreeNode(int size) { + if (size == 0) { + return null; + } + int v = 1; + Node head = new Node(v++); + if (size == 1) { + return head; + } + Node cur = head; + Queue queue = new LinkedList<>(); + queue.offer(cur); + while (size != 0) { + Node left = null; + Node right = null; + while (!queue.isEmpty()) { + cur = queue.poll(); + left = new Node(v++); + right = new Node(v++); + cur.left = left; + cur.right = right; + } + queue.offer(left); + queue.offer(right); + size--; + } + + return head; + } +} + + diff --git a/src/leo/class07_11/PaperFolding.java b/src/leo/class07_11/PaperFolding.java new file mode 100644 index 0000000..2af66d6 --- /dev/null +++ b/src/leo/class07_11/PaperFolding.java @@ -0,0 +1,35 @@ +package leo.class07_11; + +/** + * @author Leo + * @ClassName PaperFolding + * @DATE 2020/12/10 9:43 上午 + * @Description 打印一张纸条对着n次后的折痕 + */ +public class PaperFolding { + + + public static void printAllFolds(int n) { + if (n < 0) { + return; + } + processPrint(1, n, true); + System.out.println(); + + } + + public static void processPrint(int i, int n, boolean boo) { + if (i > n) { + return; + } + processPrint(i + 1, n, true); + System.out.print(boo ? "凹 " : "凸 "); + processPrint(i + 1, n, false); + } + + public static void main(String[] args){ + //凹 凹 凸 凹 凹 凸 凸 凹 凹 凹 凸 凸 凹 凸 凸 + //凹 凹 凸 凹 凹 凸 凸 凹 凹 凹 凸 凸 凹 凸 凸 + printAllFolds(4); + } +} diff --git a/src/leo/class07_11/SerializeAndReconstructTree.java b/src/leo/class07_11/SerializeAndReconstructTree.java new file mode 100644 index 0000000..a81cffa --- /dev/null +++ b/src/leo/class07_11/SerializeAndReconstructTree.java @@ -0,0 +1,245 @@ +package leo.class07_11; + +import java.util.LinkedList; +import java.util.Queue; +import java.util.Stack; + +/** + * @author Leo + * @ClassName SerializeAndReconstructTree + * @DATE 2020/12/9 4:33 下午 + * @Description 序列化二叉树 + * 先序和后序序列化和反序列化都可以,中序不行,中序有歧义. + */ +public class SerializeAndReconstructTree { + static class Node{ + int value; + Node left; + Node right; + + public Node(int value) { + this.value = value; + } + + } + + /** + * 先序方式序列化为队列 + */ + public static Queue preSerial(Node node) { + Queue queue = new LinkedList<>(); + preSerial(node, queue); + return queue; + } + + public static void preSerial(Node node, Queue queue) { + if (node == null) { + queue.offer(null); + }else{ + queue.offer(String.valueOf(node.value)); + preSerial(node.left, queue); + preSerial(node.right, queue); + } + } + + /** + * 先序方式反序列化 + */ + public static Node preDeSerial(Queue queue) { + if (queue.isEmpty() || queue == null) { + return null; + } + return preDeSerialProcess(queue); + } + + public static Node preDeSerialProcess(Queue queue) { + String v = queue.poll(); + if (v == null) { + return null; + } + Node head = new Node(Integer.valueOf(v)); + head.left = preDeSerialProcess(queue); + head.right = preDeSerialProcess(queue); + return head; + } + + /** + * 后续方式序列化队列 + */ + public static Queue posSerial(Node node) { + Queue queue = new LinkedList<>(); + posSerial(node, queue); + return queue; + } + + public static void posSerial(Node node, Queue queue) { + if (node == null) { + queue.offer(null); + }else{ + posSerial(node.left, queue); + posSerial(node.right, queue); + queue.offer(String.valueOf(node.value)); + } + } + + /** + * 后续方式反序列化 + */ + public static Node posDeSerial(Queue queue) { + if (queue.isEmpty() || queue == null) { + return null; + } + Stack stack = new Stack<>(); + while (!queue.isEmpty()) { + stack.push(queue.poll()); + } + + return posDeSerialProcess(stack); + } + + public static Node posDeSerialProcess(Stack stack) { + String v = stack.pop(); + if (v == null ) { + return null; + } + Node head = new Node(Integer.valueOf(v)); + head.right = posDeSerialProcess(stack); + head.left = posDeSerialProcess(stack); + return head; + } + + /** + * 按层序列化 + */ + public static Queue levelSerial(Node node) { + Queue ans = new LinkedList<>(); + if (node == null) { + ans.offer(null); + }else{ + ans.offer(String.valueOf(node.value)); + Queue queue = new LinkedList<>(); + queue.offer(node); + while (!queue.isEmpty()) { + node = queue.poll(); + if (node.left != null) { + ans.offer(String.valueOf(node.left.value)); + queue.offer(node.left); + }else{ + ans.offer(null); + } + if (node.right != null) { + ans.offer(String.valueOf(node.right.value)); + queue.offer(node.right); + }else{ + ans.offer(null); + } + } + } + return ans; + } + /** + * 按层反序列化 + */ + public static Node levelDeSerial(Queue list) { + if (list.isEmpty() || list == null || list.size() == 0) { + return null; + } + Node head = generateNode(list.poll()); + Queue queue = new LinkedList<>(); + if (head != null) { + queue.offer(head); + } + Node cur = null; + while (!queue.isEmpty()) { + cur = queue.poll(); + cur.left = generateNode(list.poll()); + cur.right = generateNode(list.poll()); + if (cur.left != null) { + queue.offer(cur.left); + } + if (cur.right != null) { + queue.offer(cur.right); + } + } + return head; + } + + public static Node generateNode(String v) { + if (v == null) { + return null; + } + Node node = new Node(Integer.valueOf(v)); + return node; + } + + /** + * 功能描述 : 测试 + * @author Leo + * @date 2020/12/9 8:11 下午 + * @param args + * @return void + */ + public static void main(String[] args){ + int maxLevel = 10; + int range = 100; + int testTime = 10000; + System.out.println("start"); + for (int i = 0; i < testTime; i++) { + Node head = generateRandomNode(maxLevel, range); + Queue preSerial = preSerial(head); + Queue posSerial = posSerial(head); + Node posDeSerial = posDeSerial(posSerial); + Queue levelSerial = levelSerial(head); + Node levelDeSerial = levelDeSerial(levelSerial); + + Node preDeSerial = preDeSerial(preSerial); + if (!isEqualsNode(preDeSerial, head)) { + System.out.println("preDeSerial ==> fuck"); + break; + } + if (!isEqualsNode(posDeSerial, head)) { + System.out.println("posDeSerial ==> fuck"); + break; + } + if (!isEqualsNode(levelDeSerial, head)) { + System.out.println("levelDeSerial ==> fuck"); + break; + } + } + System.out.println("end"); + + + } + + public static Node generateRandomNode(int maxLevel, int range) { + return generate(1, maxLevel, range); + } + + public static Node generate(int curLevel, int maxLevel, int range) { + if (curLevel > maxLevel || Math.random() < 0.5) { + return null; + } + Node head = new Node((int) (range * Math.random() )); + head.left = generate(curLevel + 1, maxLevel, range); + head.right = generate(curLevel + 1, maxLevel, range); + return head; + } + + public static boolean isEqualsNode(Node head1, Node head2) { + if (head1 != null && head2 == null) { + return false; + } + if (head1 == null && head2 != null) { + return false; + } + if (head1 == null && head2 == null) { + return true; + } + if (head1.value != head2.value) { + return false; + } + return isEqualsNode(head1.left, head2.left) && isEqualsNode(head1.right, head2.right); + } +} + + diff --git a/src/leo/class07_11/SuccessorNode.java b/src/leo/class07_11/SuccessorNode.java new file mode 100644 index 0000000..2a5fa71 --- /dev/null +++ b/src/leo/class07_11/SuccessorNode.java @@ -0,0 +1,111 @@ +package leo.class07_11; + +/** + * @author Leo + * @ClassName SuccessorNode + * @DATE 2020/12/9 10:00 下午 + * @Description 找到某个几点的后继节点 + * 后继节点:在中序遍历中的下个节点就是后继节点. + */ +public class SuccessorNode { + + + public static class Node { + public int value; + public Node left; + public Node right; + public Node parent; + + public Node(int data) { + this.value = data; + } + } + + public static Node getSuccessorNode(Node node) { + if (node == null) { + return null; + } + if (node.right != null) { + //在右子树下找最左侧的节点 + Node right = node.right; + while (right.left != null) { + right = right.left; + } + return right; + }else{ + //没有右子树,找顶级父节点 + Node parent = node.parent; + while (parent != null && parent.right == node) { + node = parent; + parent = node.parent; + } + return parent; + } + } + + public static Node getSuccessorNode1(Node node){ + if (node == null) { + return null; + } + if (node.right != null) { + Node cur = node.right; + while (cur.left != null) { + cur = cur.left; + } + return cur; + }else{ + Node parent = node.parent; + while (parent != null && parent.right == node) { + node = parent; + parent = node.parent; + } + return parent; + } + } + + public static void main(String[] args) { + Node head = new Node(6); + head.parent = null; + head.left = new Node(3); + head.left.parent = head; + head.left.left = new Node(1); + head.left.left.parent = head.left; + head.left.left.right = new Node(2); + head.left.left.right.parent = head.left.left; + head.left.right = new Node(4); + head.left.right.parent = head.left; + head.left.right.right = new Node(5); + head.left.right.right.parent = head.left.right; + head.right = new Node(9); + head.right.parent = head; + head.right.left = new Node(8); + head.right.left.parent = head.right; + head.right.left.left = new Node(7); + head.right.left.left.parent = head.right.left; + head.right.right = new Node(10); + head.right.right.parent = head.right; + + Node test = head.left.left; + System.out.println(test.value + " next: " + getSuccessorNode1(test).value); + test = head.left.left.right; + System.out.println(test.value + " next: " + getSuccessorNode1(test).value); + test = head.left; + System.out.println(test.value + " next: " + getSuccessorNode1(test).value); + test = head.left.right; + System.out.println(test.value + " next: " + getSuccessorNode1(test).value); + test = head.left.right.right; + System.out.println(test.value + " next: " + getSuccessorNode1(test).value); + test = head; + System.out.println(test.value + " next: " + getSuccessorNode1(test).value); + test = head.right.left.left; + System.out.println(test.value + " next: " + getSuccessorNode1(test).value); + test = head.right.left; + System.out.println(test.value + " next: " + getSuccessorNode1(test).value); + test = head.right; + System.out.println(test.value + " next: " + getSuccessorNode1(test).value); + test = head.right.right; // 10's next is null + System.out.println(test.value + " next: " + getSuccessorNode1(test)); + } + + +} diff --git a/src/leo/class07_11/TreeMaxWidth.java b/src/leo/class07_11/TreeMaxWidth.java new file mode 100644 index 0000000..10d5213 --- /dev/null +++ b/src/leo/class07_11/TreeMaxWidth.java @@ -0,0 +1,130 @@ +package leo.class07_11; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Queue; + +/** + * @author Leo + * @ClassName TreeMaxWidth + * @DATE 2020/12/9 7:28 下午 + * @Description 二叉树的最大宽度 + */ +public class TreeMaxWidth { + + public static class Node { + public int value; + public Node left; + public Node right; + + public Node(int data) { + this.value = data; + } + } + + public static int maxWidthUseMap(Node head) { + if (head == null) { + return 0; + } + Queue queue = new LinkedList<>(); + Map map = new HashMap<>(); + map.put(head, 1); + queue.offer(head); + int curLevel = 1; + int curLevelCount = 0; + int max = 0; + Node cur; + while (!queue.isEmpty()) { + cur = queue.poll(); + Integer curNodeLevel = map.get(cur); + if (cur.left != null) { + map.put(cur.left, curNodeLevel + 1); + queue.offer(cur.left); + } + if (cur.right != null) { + map.put(cur.right, curNodeLevel + 1); + queue.offer(cur.right); + } + if (curLevel == curNodeLevel) { + curLevelCount++; + }else{ + max = Math.max(curLevelCount, max); + curLevel++; + curLevelCount = 1; + } + } + max = Math.max(max, curLevelCount); + return max; + } + + public static int maxWidthNoMap(Node head) { + if (head == null) { + return 0; + } + + Queue queue = new LinkedList<>(); + int max = 0; + int curMax = 0; + Node curEnd = head; + Node nextEnd = null; + queue.offer(head); + while (!queue.isEmpty()) { + Node cur = queue.poll(); + if (cur.left != null) { + queue.offer(cur.left); + nextEnd = cur.left; + } + if (cur.right != null) { + queue.offer(cur.right); + nextEnd = cur.right; + } + curMax++; + if (cur == curEnd) { + curEnd = nextEnd; + max = Math.max(max, curMax); + curMax = 0; + } + } + return max; + } + + + public static void main(String[] args){ + + int maxSize = 10; + int range = 100; + int test = 1000; + System.out.println("start!"); + + for (int i = 0; i < test; i++) { + Node head = generateRandomNode(maxSize, range); + int i1 = maxWidthUseMap(head); + int i2 = maxWidthNoMap(head); + if (i1 != i2) { + System.out.println("i1: " + i1 + " i2: " + i2); + break; + } + } + System.out.println("end!"); + + } + + public static Node generateRandomNode(int maxSize, int range) { + if (maxSize == 0) { + return null; + } + return generateNode(1, maxSize, range); + + } + + private static Node generateNode(int i, int maxSize, int range) { + if (i > maxSize || Math.random() < 0.5) { + return null; + } + Node head = new Node((int) (range * Math.random())); + head.left = generateNode(i + 1, maxSize, range); + head.right = generateNode(i + 1, maxSize, range); + return head; + } +}