哔哩哔哩9.1笔试题解+注释
1. 小红的链表结点合并
public static class ListNode { int val; ListNode next = null; public ListNode(int val) { this.val = val; } } public static ListNode mergeNode(ListNode head) { if (head == null) { return null; } ListNode dummy = new ListNode(0), cur = dummy; while (head != null && head.next != null) { int a = head.val; head = head.next; int b = head.val; cur.next = new ListNode(a * b); cur = cur.next; head = head.next; } return dummy.next; }
2.小红的最大层权值
前置知识:怎么判断一棵树是否是平衡二叉树
public boolean isBalanced(TreeNode root) { if (root == null) { return true; } return process(root) >= 0; } public int process(TreeNode x) { if (x == null) { return 0; } int left = process(x.left); int right = process(x.right); if (left >= 0 && right >= 0 && Math.abs(left - right) <= 1) { return Math.max(left, right) + 1; } else { return -1; } }
public static class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } public static int maxValue(TreeNode root) { if (root == null) { return 0; } Queue<TreeNode> queue = new LinkedList<>(); queue.add(root); // 深度 int deep = 0; // income[i]代表第i层通过交换能获得的最大收益,默认为0 int maxDeep = maxDeep(root); int[] income = new int[maxDeep]; int[] sums = new int[maxDeep]; // bfs while (!queue.isEmpty()) { int size = queue.size(); // 这一层的权值和 int curSum = 0; for (int i = 0; i < size; i++) { // 遍历这一层的所有结点 TreeNode x = queue.poll(); // 统计这一层的权值和 curSum += x.val; // 当前到达第n层 // case 1: x结点 与 n + 1 层自己的左右结点交换,能给 第 n 层的带来最大收益。 // case 2: x结点 与 n + 1 层自己的左右结点交换,能给 第 n + 1 层的带来最大收益。 // case 1 // 当前结点和左孩子交换获得的收益(左孩子.val - x.val) int leftInCome = 0; if (x.left != null) { leftInCome = x.left.val - x.val; queue.add(x.left); } // 当前结点和右孩子交换获得的收益 int rightInCome = 0; if (x.right != null) { rightInCome = x.right.val - x.val; queue.add(x.right); } // 存入income数组中,代表第deep层通过交换能获得的最大收益 int curMax = Math.max(0, Math.max(leftInCome, rightInCome)); income[deep] = Math.max(income[deep], curMax); // case 2 // x结点换到自己的左孩子交换获取的收益(x.val - 左孩子.val) if (deep + 1 != maxDeep) { leftInCome = -leftInCome; rightInCome = -rightInCome; int curMax2 = Math.max(0, Math.max(leftInCome, rightInCome)); income[deep + 1] = Math.max(income[deep + 1], curMax2); } } // 遍历完一层,深度 + 1。同时记录这一层的权值和 sums[deep++] = curSum; } // 遍历sums数组 int res = 0; for (int i = 0; i < sums.length; i++) { res = Math.max(res, sums[i] + income[i]); } return res; } // 返回二叉树的最大深度 public static int maxDeep(TreeNode x) { if (x == null) { return 0; } return Math.max(maxDeep(x.left), maxDeep(x.right)) + 1; }
3. 平衡二叉树
public static class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } static PriorityQueue<TreeNode> queue = new PriorityQueue<>((t1, t2) -> { // 获取t1、t2的结点个数 int nodes1 = treeNodes(t1); int nodes2 = treeNodes(t2); if (nodes1 == nodes2) { // 如果结点个数相同,按照子树的头结点从小到大排序 return t1.val - t2.val; } else { // 如果结点个数不同,按照结点数量从小到大排序 return nodes1 - nodes2; } }); public static TreeNode[] balanceSubTree(TreeNode root) { if (root == null) { // base case return new TreeNode[]{}; } // 后序遍历 process(root); // 最后加入剩下的头结点 queue.add(root); TreeNode[] ret = new TreeNode[queue.size()]; int index = 0; while (!queue.isEmpty()) { ret[index++] = queue.poll(); } return ret; } private static int process(TreeNode x) { if (x == null) { return 0; } int left = process(x.left); int right = process(x.right); if (left >= 0 && right >= 0 && Math.abs(left - right) <= 1) { // 如果左树是平衡二叉树并且右树是平衡二叉树,并且左树右树高度差不超过1,那么这棵树是平衡二叉树 // 返回最大高度 return Math.max(left, right) + 1; } else { // 不是平衡二叉树,需要拆分。 if (left > right) { // 如果左树高度大于右树高度 // 左树无论如何都要加入的 queue.add(x.left); // 置空x的左树 x.left = null; // 这里就分为两种情况,第一种情况右树高度小于等于1。第二种情况右树高度大于1 // case1:右树高度小于等于1,那么这棵树高度为0或者为1,都可以和当前头结点构成平衡二叉树。不用单独将右树加入返回结果 // case2: 右树高度大于1,也就是大于等于2,因为左树已经置空了,当前头结点加上这个高度大于等于2的子树,构成不了平衡二叉树。所以直接将右树加入 if (right <= 1) { // case 1 右树不需要单独处理,返回当前头结点 + 右树高度 return right + 1; } else { // case 2 右树需要单独处理,返回头结点的高度,也就是1 queue.add(x.right); x.right = null; return 1; } } else { // 左树高度小于右树高度,情况分析和上面一样 queue.add(x.right); // 置空x的右树 x.right = null; if (left <= 1) { // case 1 return left + 1; } else { // case 2 queue.add(x.left); x.left = null; return 1; } } } } // 返回一棵树的结点个数 public static int treeNodes(TreeNode x) { if (x == null) { return 0; } return treeNodes(x.left) + treeNodes(x.right) + 1; }