diff --git a/MCA算法突击课/第03期/mca_03/Code01_MergeKSortedLists.java b/MCA算法突击课/第03期/mca_03/Code01_MergeKSortedLists.java index f8facb8..088a1b0 100644 --- a/MCA算法突击课/第03期/mca_03/Code01_MergeKSortedLists.java +++ b/MCA算法突击课/第03期/mca_03/Code01_MergeKSortedLists.java @@ -1,6 +1,5 @@ package 第03期.mca_03; -import java.util.Comparator; import java.util.PriorityQueue; // 给你一个链表数组,每个链表都已经按升序排列。 @@ -8,27 +7,48 @@ import java.util.PriorityQueue; // 测试链接:https://leetcode.cn/problems/merge-k-sorted-lists/ public class Code01_MergeKSortedLists { +// public static void main(String[] args) { +// ListNode h1 = new ListNode(1); +// h1.next = new ListNode(6); +// h1.next.next = new ListNode(9); +// +// ListNode h2 = new ListNode(3); +// h2.next = new ListNode(4); +// h2.next.next = new ListNode(4); +// +// ListNode h3 = new ListNode(5); +// h3.next = new ListNode(6); +// h3.next.next = new ListNode(9); +// +// ListNode[] arr = { h1, h2, h3 }; +// +// ListNode all = mergeKLists(arr); +// +// while (all != null) { +// System.out.print(all.val + " "); +// all = all.next; +// } +// System.out.println(); +// } + // 这个类不提交 public static class ListNode { public int val; public ListNode next; - } - - // 提交以下方法 - public static class ListNodeComparator implements Comparator { - @Override - public int compare(ListNode o1, ListNode o2) { - return o1.val - o2.val; + public ListNode(int v) { + val = v; } - } + // 提交以下方法 public static ListNode mergeKLists(ListNode[] lists) { if (lists == null) { return null; } - PriorityQueue heap = new PriorityQueue<>(new ListNodeComparator()); + // 小根堆! + PriorityQueue heap = new PriorityQueue<>((a, b) -> a.val - b.val); + // 所有链表的头节点,进入小根堆 for (int i = 0; i < lists.length; i++) { if (lists[i] != null) { heap.add(lists[i]); diff --git a/MCA算法突击课/第03期/mca_03/Code02_LevelTraversalBT.java b/MCA算法突击课/第03期/mca_03/Code02_LevelTraversalBT.java index 049bdd9..0754a0e 100644 --- a/MCA算法突击课/第03期/mca_03/Code02_LevelTraversalBT.java +++ b/MCA算法突击课/第03期/mca_03/Code02_LevelTraversalBT.java @@ -28,7 +28,9 @@ public class Code02_LevelTraversalBT { Queue queue = new LinkedList<>(); queue.add(root); while (!queue.isEmpty()) { + // 当前轮做几次动作 int size = queue.size(); + // 当前层的链表 List curLevel = new ArrayList<>(); for (int i = 0; i < size; i++) { TreeNode cur = queue.poll(); diff --git a/MCA算法突击课/第03期/mca_03/Code03_ConstructBinaryTreeFromPreorderAndInorderTraversal.java b/MCA算法突击课/第03期/mca_03/Code03_ConstructBinaryTreeFromPreorderAndInorderTraversal.java index ba81752..57d7bf7 100644 --- a/MCA算法突击课/第03期/mca_03/Code03_ConstructBinaryTreeFromPreorderAndInorderTraversal.java +++ b/MCA算法突击课/第03期/mca_03/Code03_ConstructBinaryTreeFromPreorderAndInorderTraversal.java @@ -15,32 +15,43 @@ public class Code03_ConstructBinaryTreeFromPreorderAndInorderTraversal { TreeNode left; TreeNode right; - TreeNode(int val) { - this.val = val; + TreeNode(int v) { + val = v; } } // 提交如下的方法 + // pre和in真的是某棵二叉树的先序和中序数组 + // 原始二叉树里,无重复值 public static TreeNode buildTree(int[] pre, int[] in) { HashMap valueIndexMap = new HashMap<>(); for (int i = 0; i < in.length; i++) { valueIndexMap.put(in[i], i); } - return g(pre, 0, pre.length - 1, in, 0, in.length - 1, valueIndexMap); + return process(pre, 0, pre.length - 1, in, 0, in.length - 1, valueIndexMap); } - public static TreeNode g(int[] pre, int L1, int R1, int[] in, int L2, int R2, + // pre[pl....pr] + // in [il....ir] + // 子树! + public static TreeNode process(int[] pre, int pl, int pr, int[] in, int il, int ir, HashMap valueIndexMap) { - if (L1 > R1) { - return null; + // pre[pl...pr] + TreeNode head = new TreeNode(pre[pl]); + // [ 7 3 4 5 6 8 ] + // 4 5 6 7 8 9 + // + // [ 3 4 7 6 5 8 ] + // 2 3 4 5 6 7 + int headIndex = valueIndexMap.get(pre[pl]); + int leftSize = headIndex - il; + int rightSize = ir - headIndex; + if (leftSize > 0) { + head.left = process(pre, pl + 1, pl + leftSize, in, il, il + leftSize - 1, valueIndexMap); } - TreeNode head = new TreeNode(pre[L1]); - if (L1 == R1) { - return head; + if (rightSize > 0) { + head.right = process(pre, pr - rightSize + 1, pr, in, ir - rightSize + 1, ir, valueIndexMap); } - int find = valueIndexMap.get(pre[L1]); - head.left = g(pre, L1 + 1, L1 + find - L2, in, L2, find - 1, valueIndexMap); - head.right = g(pre, L1 + find - L2 + 1, R1, in, find + 1, R2, valueIndexMap); return head; } diff --git a/MCA算法突击课/第03期/mca_03/Code04_IsCBT.java b/MCA算法突击课/第03期/mca_03/Code04_IsCBT.java index 89444a0..2ccffec 100644 --- a/MCA算法突击课/第03期/mca_03/Code04_IsCBT.java +++ b/MCA算法突击课/第03期/mca_03/Code04_IsCBT.java @@ -1,6 +1,7 @@ package 第03期.mca_03; import java.util.LinkedList; +import java.util.Queue; // 给定一个二叉树的 root ,确定它是否是一个 完全二叉树 // 在一个 完全二叉树 中,除了最后一个关卡外,所有关卡都是完全被填满的 @@ -25,26 +26,24 @@ public class Code04_IsCBT { if (head == null) { return true; } - LinkedList queue = new LinkedList<>(); - boolean leaf = false; - TreeNode l = null; - TreeNode r = null; + Queue queue = new LinkedList<>(); queue.add(head); + // 一旦遇到不双全的节点,接下来遇到的所有节点都必须是叶! + boolean mustLeafStage = false; while (!queue.isEmpty()) { - head = queue.poll(); - l = head.left; - r = head.right; - if ((leaf && (l != null || r != null)) || (l == null && r != null)) { + TreeNode cur = queue.poll(); + if ((cur.left == null && cur.right != null) + || (mustLeafStage && (cur.left != null || cur.right != null))) { return false; } - if (l != null) { - queue.add(l); + if(cur.left == null || cur.right == null) { + mustLeafStage = true; } - if (r != null) { - queue.add(r); + if (cur.left != null) { + queue.add(cur.left); } - if (l == null || r == null) { - leaf = true; + if (cur.right != null) { + queue.add(cur.right); } } return true; diff --git a/MCA算法突击课/第03期/mca_03/Code05_IsBST.java b/MCA算法突击课/第03期/mca_03/Code05_IsBST.java index 1877a1f..a2f234d 100644 --- a/MCA算法突击课/第03期/mca_03/Code05_IsBST.java +++ b/MCA算法突击课/第03期/mca_03/Code05_IsBST.java @@ -20,13 +20,6 @@ public class Code05_IsBST { } // 提交以下的方法 - public boolean isValidBST(TreeNode root) { - if (root == null) { - return true; - } - return process(root).isBST; - } - public static class Info { public boolean isBST; public int min; @@ -39,28 +32,41 @@ public class Code05_IsBST { } } - public static Info process(TreeNode root) { + public boolean isValidBST(TreeNode root) { if (root == null) { + return true; + } + return process(root).isBST; + } + + public static Info process(TreeNode x) { + if (x == null) { return null; } - Info left = process(root.left); - Info right = process(root.right); - int min = root.val; - int max = root.val; + Info leftInfo = process(x.left); + Info rightInfo = process(x.right); + int min = x.val; + int max = x.val; + if (leftInfo != null) { + min = Math.min(leftInfo.min, min); + max = Math.max(leftInfo.max, max); + } + if (rightInfo != null) { + min = Math.min(rightInfo.min, min); + max = Math.max(rightInfo.max, max); + } boolean isBST = true; - if (left != null) { - min = Math.min(min, left.min); - max = Math.max(max, left.max); - if (!left.isBST || left.max >= root.val) { - isBST = false; - } + if (leftInfo != null && !leftInfo.isBST) { + isBST = false; + } + if (rightInfo != null && !rightInfo.isBST) { + isBST = false; + } + if (leftInfo != null && leftInfo.max >= x.val) { + isBST = false; } - if (right != null) { - min = Math.min(min, right.min); - max = Math.max(max, right.max); - if (!right.isBST || root.val >= right.min) { - isBST = false; - } + if (rightInfo != null && rightInfo.min <= x.val) { + isBST = false; } return new Info(isBST, min, max); } diff --git a/MCA算法突击课/第03期/mca_03/Code07_CompleteTreeNodeNumber.java b/MCA算法突击课/第03期/mca_03/Code07_CompleteTreeNodeNumber.java deleted file mode 100644 index 4d8daf2..0000000 --- a/MCA算法突击课/第03期/mca_03/Code07_CompleteTreeNodeNumber.java +++ /dev/null @@ -1,50 +0,0 @@ -package 第03期.mca_03; - -// 给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数 -// 完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外 -// 其余每层节点数都达到最大值 -// 并且最下面一层的节点都集中在该层最左边的若干位置 -// 若最底层为第 h 层,则该层包含 1~ 2h 个节点。 -// 测试链接 : https://leetcode.cn/problems/count-complete-tree-nodes/ -public class Code07_CompleteTreeNodeNumber { - - // 提交时不要提交这个类 - public class TreeNode { - int val; - TreeNode left; - TreeNode right; - } - - // 提交如下的方法 - public static int countNodes(TreeNode head) { - if (head == null) { - return 0; - } - return bs(head, 1, mostLeftLevel(head, 1)); - } - - // 当前来到node节点,node节点在level层,总层数是h - // 返回node为头的子树(必是完全二叉树),有多少个节点 - public static int bs(TreeNode node, int Level, int h) { - if (Level == h) { - return 1; - } - if (mostLeftLevel(node.right, Level + 1) == h) { - return (1 << (h - Level)) + bs(node.right, Level + 1, h); - } else { - return (1 << (h - Level - 1)) + bs(node.left, Level + 1, h); - } - } - - // 如果node在第level层, - // 求以node为头的子树,最大深度是多少 - // node为头的子树,一定是完全二叉树 - public static int mostLeftLevel(TreeNode node, int level) { - while (node != null) { - level++; - node = node.left; - } - return level - 1; - } - -} diff --git a/MCA算法突击课/第03期/mca_03/Code08_DiameterOfBinaryTree.java b/MCA算法突击课/第03期/mca_03/Code08_DiameterOfBinaryTree.java deleted file mode 100644 index 98e04a8..0000000 --- a/MCA算法突击课/第03期/mca_03/Code08_DiameterOfBinaryTree.java +++ /dev/null @@ -1,48 +0,0 @@ -package 第03期.mca_03; - -// 给定一棵二叉树,你需要计算它的直径长度 -// 一棵二叉树的直径长度是任意两个结点路径长度中的最大值 -// 这条路径可能穿过也可能不穿过根结点 -// 测试链接 : https://leetcode.cn/problems/diameter-of-binary-tree/ -public class Code08_DiameterOfBinaryTree { - - // 提交时不要提交这个类 - public static class TreeNode { - public int val; - public TreeNode left; - public TreeNode right; - - public TreeNode(int value) { - val = value; - } - } - - // 提交以下的方法 - public static int diameterOfBinaryTree(TreeNode root) { - return process(root).maxDistance; - } - - public static class Info { - public int maxDistance; - public int height; - - public Info(int m, int h) { - maxDistance = m; - height = h; - } - } - - public static Info process(TreeNode x) { - if (x == null) { - return new Info(0, 0); - } - Info leftInfo = process(x.left); - Info rightInfo = process(x.right); - int height = Math.max(leftInfo.height, rightInfo.height) + 1; - int p1 = Math.max(leftInfo.maxDistance, rightInfo.maxDistance); - int p2 = leftInfo.height + rightInfo.height; - int maxDistance = Math.max(p1, p2); - return new Info(maxDistance, height); - } - -} diff --git a/MCA算法突击课/第03期/mca_03/Code09_MaxSubBSTSize.java b/MCA算法突击课/第03期/mca_03/Code09_MaxSubBSTSize.java deleted file mode 100644 index ef36c9b..0000000 --- a/MCA算法突击课/第03期/mca_03/Code09_MaxSubBSTSize.java +++ /dev/null @@ -1,87 +0,0 @@ -package 第03期.mca_03; - -// 给定一个二叉树,找到其中最大的二叉搜索树(BST)子树,并返回该子树的大小 -// 其中,最大指的是子树节点数最多的 -// 二叉搜索树(BST)中的所有节点都具备以下属性: -// 左子树的值小于其父(根)节点的值 -// 右子树的值大于其父(根)节点的值 -// 注意:子树必须包含其所有后代 -// 测试链接 : https://leetcode.cn/problems/largest-bst-subtree -public class Code09_MaxSubBSTSize { - - // 提交时不要提交这个类 - public static class TreeNode { - public int val; - public TreeNode left; - public TreeNode right; - - public TreeNode(int value) { - val = value; - } - } - - // 提交如下方法 - public static int largestBSTSubtree(TreeNode head) { - if (head == null) { - return 0; - } - return process(head).maxBSTSubtreeSize; - } - - public static class Info { - public int maxBSTSubtreeSize; - public int allSize; - public int max; - public int min; - - public Info(int m, int a, int ma, int mi) { - maxBSTSubtreeSize = m; - allSize = a; - max = ma; - min = mi; - } - } - - public static Info process(TreeNode x) { - if (x == null) { - return null; - } - Info leftInfo = process(x.left); - Info rightInfo = process(x.right); - int max = x.val; - int min = x.val; - int allSize = 1; - if (leftInfo != null) { - max = Math.max(leftInfo.max, max); - min = Math.min(leftInfo.min, min); - allSize += leftInfo.allSize; - } - if (rightInfo != null) { - max = Math.max(rightInfo.max, max); - min = Math.min(rightInfo.min, min); - allSize += rightInfo.allSize; - } - int p1 = -1; - if (leftInfo != null) { - p1 = leftInfo.maxBSTSubtreeSize; - } - int p2 = -1; - if (rightInfo != null) { - p2 = rightInfo.maxBSTSubtreeSize; - } - int p3 = -1; - boolean leftBST = leftInfo == null ? true : (leftInfo.maxBSTSubtreeSize == leftInfo.allSize); - boolean rightBST = rightInfo == null ? true : (rightInfo.maxBSTSubtreeSize == rightInfo.allSize); - if (leftBST && rightBST) { - boolean leftMaxLessX = leftInfo == null ? true : (leftInfo.max < x.val); - boolean rightMinMoreX = rightInfo == null ? true : (x.val < rightInfo.min); - if (leftMaxLessX && rightMinMoreX) { - int leftSize = leftInfo == null ? 0 : leftInfo.allSize; - int rightSize = rightInfo == null ? 0 : rightInfo.allSize; - p3 = leftSize + rightSize + 1; - } - } - return new Info(Math.max(p1, Math.max(p2, p3)), allSize, max, min); - } - -}