From 28da35a5f8caf1399da747aa8dbf50a1abb7b1a0 Mon Sep 17 00:00:00 2001 From: markilue <745518019@qq.com> Date: Fri, 23 Sep 2022 13:29:51 +0800 Subject: [PATCH] =?UTF-8?q?leecode=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/markilue/leecode/test/test.java | 8 +- .../leecode/tree/BinaryTreePaths.java | 174 ++++++++++++++++++ .../com/markilue/leecode/tree/IsBalance.java | 133 +++++++++++++ 3 files changed, 312 insertions(+), 3 deletions(-) create mode 100644 Leecode/src/main/java/com/markilue/leecode/tree/BinaryTreePaths.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/tree/IsBalance.java diff --git a/Leecode/src/main/java/com/markilue/leecode/test/test.java b/Leecode/src/main/java/com/markilue/leecode/test/test.java index 7ed5b07..b1e34e2 100644 --- a/Leecode/src/main/java/com/markilue/leecode/test/test.java +++ b/Leecode/src/main/java/com/markilue/leecode/test/test.java @@ -35,10 +35,12 @@ public class test { @Test public void test1(){ - String s1=null; - String s2=null; + String s1="1"; + String s2="2"; - System.out.println(s1==s2); + s1=s1+2; + + System.out.println(s1); } } diff --git a/Leecode/src/main/java/com/markilue/leecode/tree/BinaryTreePaths.java b/Leecode/src/main/java/com/markilue/leecode/tree/BinaryTreePaths.java new file mode 100644 index 0000000..303a8de --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/tree/BinaryTreePaths.java @@ -0,0 +1,174 @@ +package com.markilue.leecode.tree; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +/** + * @BelongsProject: Leecode + * @BelongsPackage: com.markilue.leecode.tree + * @Author: dingjiawen + * @CreateTime: 2022-09-23 11:48 + * @Description: TODO 力扣257题 二叉树的所有路径: + * 给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。 + * 叶子节点 是指没有子节点的节点。 + * @Version: 1.0 + */ +public class BinaryTreePaths { + + @Test + public void test() { + TreeNode root = new TreeNode(3); + TreeNode TreeNode2 = new TreeNode(9); + TreeNode TreeNode3 = new TreeNode(20); +// TreeNode TreeNode4 = new TreeNode(4); +// TreeNode TreeNode5 = new TreeNode(5); + TreeNode TreeNode6 = new TreeNode(15); + TreeNode TreeNode7 = new TreeNode(7); + + root.setRight(TreeNode3); + root.setLeft(TreeNode2); +// TreeNode2.setLeft(TreeNode4); +// TreeNode2.setRight(TreeNode5); + TreeNode3.setRight(TreeNode7); + TreeNode3.setLeft(TreeNode6); + + System.out.println(binaryTreePaths1(root)); + + } + + + /** + * 本人递归法: 本质上算是广度优先算法 + * 可以发现官方代码之所以简洁是因为他把当时path记录了下来,就不需要一直通过遍历去加上对应的节点 + * 速度超过49.92%,内存超过34% + * @param root + * @return + */ + public List binaryTreePaths(TreeNode root) { + + List result1 = new ArrayList<>(); + if (root == null) { + return new ArrayList<>(); + } + result1.add(new StringBuilder().append(root.val).append("->")); + path(root, result1); + List result = new ArrayList<>(); + for (int i = 0; i < result1.size(); i++) { + String s = result1.get(i).toString(); + result.add(s.substring(0,s.length()-2)); + } + + return result; + } + + //这里使用StringBuilder,因为他快是因为他适用于同一个string不可变字符串的时候,这里每一个只添加一次 + //这里处理node的左右节点,而不是处理他本身,因为涉及到要不要新new上一个List + public void path(TreeNode node, List result) { + if (node.left == null && node.right == null) { + return; + } else if (node.left != null && node.right != null) { + List temp=new ArrayList<>(); + for (StringBuilder s : result) { + temp.add(new StringBuilder().append(s)); + s .append(node.left.val) .append("->"); + } + path(node.left, result); + for (StringBuilder s : temp) { + s.append(node.right.val) .append("->"); + } + path(node.right, temp); + result.addAll(temp); + } else if (node.left != null) { + for (StringBuilder s : result) { + s .append(node.left.val) .append("->"); + } + path(node.left, result); + } else { + for (StringBuilder s : result) { + s .append(node.right.val) .append("->"); + } + path(node.right, result); + } + + + } + + + /** + * 官方递归法: 本质上是深度优先算法 ->前序遍历 + * 速度超过99.98%,内存超过58.81% + * @param root + * @return + */ + public List binaryTreePaths1(TreeNode root) { + + List result = new ArrayList<>(); + constructPaths(root,"",result); + return result; + + } + + //这里使用StringBuilder,因为他快是因为他适用于同一个string不可变字符串的时候,这里每一个只添加一次 + //这里处理node的左右节点,而不是处理他本身,因为涉及到要不要新new上一个List + public void constructPaths(TreeNode node,String path, List result) { + + if(node!=null){ + StringBuilder pathDS = new StringBuilder(path); + pathDS.append(node.val); + //遍历到了叶子结点,可以把结果加入 + if(node.left==null&&node.right==null){ + result.add(pathDS.toString()); + }else{ + //不是叶子节点,需要继续遍历 + pathDS.append("->"); + constructPaths(node.left,pathDS.toString(),result); + constructPaths(node.right,pathDS.toString(),result); + } + } + } + + + /** + * 官方广度优先算法 + * @param root + * @return + */ + public List binaryTreePaths2(TreeNode root) { + List paths = new ArrayList(); + if (root == null) { + return paths; + } + Queue nodeQueue = new LinkedList(); + Queue pathQueue = new LinkedList(); + + nodeQueue.offer(root); + pathQueue.offer(Integer.toString(root.val)); + + //node和path同步offer和poll保证两边一定是相对应的 + while (!nodeQueue.isEmpty()) { + TreeNode node = nodeQueue.poll(); + String path = pathQueue.poll(); + + if (node.left == null && node.right == null) { + paths.add(path); + } else { + if (node.left != null) { + nodeQueue.offer(node.left); + pathQueue.offer(new StringBuffer(path).append("->").append(node.left.val).toString()); + } + + if (node.right != null) { + nodeQueue.offer(node.right); + pathQueue.offer(new StringBuffer(path).append("->").append(node.right.val).toString()); + } + } + } + return paths; + } + + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/tree/IsBalance.java b/Leecode/src/main/java/com/markilue/leecode/tree/IsBalance.java new file mode 100644 index 0000000..b037f60 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/tree/IsBalance.java @@ -0,0 +1,133 @@ +package com.markilue.leecode.tree; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * @BelongsProject: Leecode + * @BelongsPackage: com.markilue.leecode.tree + * @Author: dingjiawen + * @CreateTime: 2022-09-23 09:59 + * @Description: TODO 力扣110题 平衡二叉树: + * 给定一个二叉树,判断它是否是高度平衡的二叉树。 + * 本题中,一棵高度平衡二叉树定义为: + * 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 + * @Version: 1.0 + */ +public class IsBalance { + + + @Test + public void test() { + TreeNode root = new TreeNode(3); + TreeNode TreeNode2 = new TreeNode(9); + TreeNode TreeNode3 = new TreeNode(20); +// TreeNode TreeNode4 = new TreeNode(4); +// TreeNode TreeNode5 = new TreeNode(5); + TreeNode TreeNode6 = new TreeNode(15); + TreeNode TreeNode7 = new TreeNode(7); + + root.setRight(TreeNode3); + root.setLeft(TreeNode2); +// TreeNode2.setLeft(TreeNode4); +// TreeNode2.setRight(TreeNode5); + TreeNode3.setRight(TreeNode7); + TreeNode3.setLeft(TreeNode6); + + System.out.println(isBalanced(root)); + + } + + @Test + public void test1() { + TreeNode root = new TreeNode(1); + TreeNode TreeNode2 = new TreeNode(2); + TreeNode TreeNode3 = new TreeNode(2); + TreeNode TreeNode4 = new TreeNode(3); + TreeNode TreeNode5 = new TreeNode(3); + TreeNode TreeNode6 = new TreeNode(4); + TreeNode TreeNode7 = new TreeNode(4); + + root.setRight(TreeNode3); + root.setLeft(TreeNode2); + TreeNode2.setLeft(TreeNode4); + TreeNode2.setRight(TreeNode5); + TreeNode4.setRight(TreeNode7); + TreeNode4.setLeft(TreeNode6); + + System.out.println(isBalanced(root)); + + } + + /** + * 自己的思路递归法:本质上就是判断两个子树之间的高度差的绝对值不超过1,因此求出两个高度即可 + * 本质上,我们又想知道其下面左右子树是否平衡,又想知道他的深度,因此这个使用一个List第一个元素存放,这里类似于拿空间换时间 =>只用遍历一次 + * 速度击败5.68%,内存击败5% + * TODO 从代码随想录的递归法可以看出: + * 实际上,其实我们只是有的时候想知道高度(左右两边都是平衡二叉树时), + * 其他时候如果他不是平衡二叉树了,高度就不重要了,所以只需要用一个特殊标记标记他是否还是平衡二叉树就可以将两者逻辑合并即变成了代码随想录的思路 + * + * @param root + * @return + */ + public boolean isBalanced(TreeNode root) { + + return (boolean) balance(root).get(0); + + } + + + public List balance(TreeNode root) { + if (root == null) { + return new ArrayList(Arrays.asList(true, 0)); + } + List left = balance(root.left); + List right = balance(root.right); + + boolean flag1 = (boolean) left.get(0); + boolean flag2 = (boolean) right.get(0); + + int depth1 = (int) left.get(1); + int depth2 = (int) right.get(1); + + if (flag1 && flag2 && Math.abs(depth1 - depth2) <= 1) { + return new ArrayList(Arrays.asList(flag1, Math.max(depth1, depth2) + 1)); + } else { + //但凡有一个false,深度就不重要了 + return new ArrayList(Arrays.asList(false, 0)); + } + + } + + + /** + * 代码随想录递归法:本质上是求高度,而不是深度 + * 速度超过100%,内存超过79.93% + * @param root + * @return + */ + public boolean isBalanced1(TreeNode root) { + + return deep(root) == -1 ? false : true; + + } + + public int deep(TreeNode root) { + if (root == null) { + return 0; + } + int left = deep(root.left); + if (left == -1) return -1; + int right = deep(root.right); + if (right == -1) return -1; + return Math.abs(left - right) > 1 ? -1 : (Math.max(left, right)) + 1; + + } + + + + +}