leecode更新

This commit is contained in:
markilue 2023-01-10 13:37:46 +08:00
parent 8e4aae2076
commit 64abd13286
8 changed files with 480 additions and 3 deletions

View File

@ -0,0 +1,133 @@
package com.markilue.leecode.tree;
import org.junit.Test;
import java.util.*;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-10 10:12
*@Description:
* TODO 力扣404 左子树之和:
* 给定二叉树的根节点 root 返回所有左叶子之和
*@Version: 1.0
*/
public class T10_SumOfLeftLeaves {
@Test
public void test() {
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(3, 9, 20, null, null, 15, 7));
TreeNode root = TreeUtils.structureTree(list, 0);
System.out.println(sumOfLeftLeaves(root));
}
@Test
public void test1() {
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
TreeNode root = TreeUtils.structureTree(list, 0);
System.out.println(sumOfLeftLeaves(root));
}
/**
* 思路:左叶子节点(叶子节点左右没有节点且是左节点) 迭代法中序遍历不处理中节点即可
* 速度击败10.5%内存击败80.37%
* @param root
* @return
*/
public int sumOfLeftLeaves(TreeNode root) {
int sum = 0;
if (root == null) {
return sum;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
TreeNode jin = root;//不让他加入的节点
while (cur != null || !stack.isEmpty()) {
if (cur != null) {
if (cur != jin && cur.left == null && cur.right == null) {
sum += cur.val;
}
stack.push(cur);
cur = cur.left;
} else {
cur = stack.pop();
cur = cur.right;
jin = cur;//刚刚进入右节点则不能让他加
}
}
return sum;
}
/**
* 思路:左叶子节点(叶子节点左右没有节点且是左节点) 递归法中序遍历不处理中节点即可
* 速度击败100%内存击败84.12%
* @param root
* @return
*/
public int sumOfLeftLeaves1(TreeNode root) {
if (root == null) {
return 0;
}
return travelLeftLeaves1(root, null);
}
/**
* 遍历看看node是不是pre的左节点来判断
* @param node
* @param pre
* @return
*/
public int travelLeftLeaves1(TreeNode node, TreeNode pre) {
if (node == null) {//节点为null不用继续遍历
return 0;
}
if (pre != null && pre.left == node && node.left == null && node.right == null) {
return node.val;//左叶子节点,加上这个值
}
return travelLeftLeaves1(node.left, node) + travelLeftLeaves1(node.right, node);
}
/**
* 官方BFS:之前都是dfs这里试试BFS法核心在于不是处理当前节点而是在父节点判断左节点是不是叶子结点
* 速度击败100%内存击败47.69%
* @param root
* @return
*/
public int sumOfLeftLeaves3(TreeNode root) {
if (root == null) {
return 0;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
int ans = 0;
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
if (node.left != null) {
if (isLeafNode(node.left)) {
ans += node.left.val;
} else {
queue.offer(node.left);
}
}
if (node.right != null) {
if (!isLeafNode(node.right)) {
queue.offer(node.right);
}
}
}
return ans;
}
public boolean isLeafNode(TreeNode node) {
return node.left == null && node.right == null;
}
}

View File

@ -0,0 +1,75 @@
package com.markilue.leecode.tree;
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: 2023-01-10 10:53
*@Description:
* TODO 力扣513题 找左下角的值:
* 给定一个二叉树的 根节点 root请找出该二叉树的 最底层 最左边 节点的值
* 假设二叉树中至少有一个节点
*@Version: 1.0
*/
public class T11_FindBottomLeftValue {
/**
* 思路:不仅要最底层还要最左事实上层序遍历就是一个很好地选择
* 速度击败13.85%内存击败45.94% 2ms
* @param root
* @return
*/
public int findBottomLeftValue(TreeNode root) {
int value = 0;
if (root == null) {
return value;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
if (i == 0) {
//每层的最左边
value = node.val;
}
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
}
return value;
}
/**
* 思路:不仅要最底层还要最左事实上层序遍历就是一个很好地选择,尝试递归DFS
* 速度击败100%内存击败65.25% 0ms
* @param root
* @return
*/
public int findBottomLeftValue1(TreeNode root) {
find(root,0);
return result.get(result.size()-1);
}
//记录每层最右
List<Integer> result=new ArrayList<>();
public void find(TreeNode node, int deep) {
if (node == null) {
return;
}
if(result.size()==deep){
result.add(node.val);
}
find(node.left,deep+1);
find(node.right,deep+1);
}
}

View File

@ -18,7 +18,7 @@ import java.util.Stack;
* 叶子节点 是指没有子节点的节点 * 叶子节点 是指没有子节点的节点
* @Version: 1.0 * @Version: 1.0
*/ */
public class HasPathSum { public class T12_HasPathSum {
@Test @Test
public void test() { public void test() {

View File

@ -14,7 +14,7 @@ import java.util.*;
* 给你二叉树的根节点 root 和一个整数目标和 targetSum 找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径 * 给你二叉树的根节点 root 和一个整数目标和 targetSum 找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径
* @Version: 1.0 * @Version: 1.0
*/ */
public class PathSum { public class T13_PathSum {
@Test @Test

View File

@ -13,7 +13,7 @@ import java.util.*;
* 给定两个整数数组 inorder postorder 其中 inorder 是二叉树的中序遍历 postorder 是同一棵树的后序遍历请你构造并返回这颗二叉树 * 给定两个整数数组 inorder postorder 其中 inorder 是二叉树的中序遍历 postorder 是同一棵树的后序遍历请你构造并返回这颗二叉树
* @Version: 1.0 * @Version: 1.0
*/ */
public class BuildTree { public class T14_BuildTree {
@Test @Test

View File

@ -0,0 +1,83 @@
package com.markilue.leecode.tree.second;
import com.markilue.leecode.tree.TreeNode;
import org.junit.Test;
import java.util.Stack;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-10 11:33
*@Description:
* TODO 力扣112题 二刷路径总和:
* 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum
* 判断该树中是否存在 根节点到叶子节点 的路径这条路径上所有节点值相加等于目标和 targetSum
* 如果存在返回 true 否则返回 false
* 叶子节点 是指没有子节点的节点
*@Version: 1.0
*/
public class T12_HasPathSum {
@Test
public void test(){
Integer sum=1000;
int i = sum.intValue();
System.out.println(i);
}
/**
* 思路:核心就在于在叶子结点时就判断targetSum;DFS
* @param root
* @param targetSum
* @return
*/
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) {//避免开始就是空的情况
return false;
}
if (root.left == null && root.right == null) {//在叶子结点就处理逻辑
return root.val == targetSum;
}
int nextTarget = targetSum - root.val;
return hasPathSum(root.left, nextTarget) || hasPathSum(root.right, nextTarget);
}
/**
* 思路:非递归法DFS
* 速度击败6.83%内存击败58.93%
* @param root
* @param targetSum
* @return
*/
public boolean hasPathSum1(TreeNode root, int targetSum) {
if (root == null) {//避免开始就是空的情况
return false;
}
Stack<TreeNode> stack = new Stack<>();
Stack<Integer> stackSum = new Stack<>();
stack.push(root);
stackSum.push(0);
while (!stack.isEmpty()){
TreeNode node = stack.pop();
Integer sum = stackSum.pop();
sum+=node.val;
if(node.left==null&&node.right==null){
if(sum.intValue()==targetSum){
return true;
}
}
if(node.left!=null){
stack.push(node.left);
stackSum.push(sum);
}
if(node.right!=null){
stack.push(node.right);
stackSum.push(sum);
}
}
return false;
}
}

View File

@ -0,0 +1,103 @@
package com.markilue.leecode.tree.second;
import com.markilue.leecode.tree.TreeNode;
import java.util.ArrayList;
import java.util.List;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-10 11:52
*@Description:
* TODO 二刷力扣113题 路径总和II:
* 给你二叉树的根节点 root 和一个整数目标和 targetSum 找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径
* 叶子节点 是指没有子节点的节点
*@Version: 1.0
*/
public class T13_PathSum {
List<Integer> cur=new ArrayList<>();
List<List<Integer>> result=new ArrayList<>();
/**
* 递归法:
* 速度击败99.98%内存击败88.17%
* @param root
* @param targetSum
* @return
*/
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
travel(root,targetSum);
return result;
}
public void travel(TreeNode node, int targetSum){
if(node==null){
return;
}
cur.add(node.val);
if(node.left==null&&node.right==null){
//到达叶子节点
if(node.val==targetSum){
result.add(new ArrayList<>(cur));
}
}
travel(node.left,targetSum- node.val);
travel(node.right,targetSum- node.val);
cur.remove(cur.size()-1);
}
/**
* 官方最快思路一样可能快在使用数组进行增减
*/
private List<List<Integer>> ans = new ArrayList<>();
private void dfs(TreeNode root, int targetSum, int current, int[] node, int index) {
if( root == null ) {
return;
}
node[index] = root.val;
current += root.val;
if( root.left == null && root.right == null ) {
if( current == targetSum ) {
List<Integer> result = new ArrayList<>();
for( int i = 0; i <= index; i++ ) {
result.add(node[i]);
}
ans.add(result);
}
return;
}
dfs(root.left, targetSum, current, node, index + 1);
dfs(root.right, targetSum, current, node, index + 1);
}
private int getDepth(TreeNode root) {
if( root == null ) {
return 0;
}
if( root.left == null && root.right == null ) {
return 1;
}
return Math.max(getDepth(root.left), getDepth(root.right)) + 1;
}
public List<List<Integer>> pathSum1(TreeNode root, int targetSum) {
int depth = getDepth(root);
if( root == null ) {
return ans;
}
int[] node = new int[depth];
dfs(root, targetSum, 0, node, 0);
return ans;
}
}

View File

@ -0,0 +1,83 @@
package com.markilue.leecode.tree.second;
import com.markilue.leecode.tree.TreeNode;
import org.junit.Test;
import java.util.Arrays;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-10 12:18
*@Description:
* TODO 二刷力扣106题 从中序与后序遍历序列构造二叉树:
* 给定两个整数数组 inorder postorder 其中 inorder 是二叉树的中序遍历
* postorder 是同一棵树的后序遍历请你构造并返回这颗 二叉树
*@Version: 1.0
*/
public class T14_BuildTree {
@Test
public void test(){
int[] inorder = {9, 3, 15, 20, 7}, postorder = {9, 15, 7, 20, 3};
System.out.println(buildTree1(inorder,postorder));
}
/**
* 思路后续遍历的最后一个就是根节点以此划分左右树
* 自己被卡在就算划分了左右但是不知道inorder和postOrder应该怎么划分
* 事实上两个个order一定一样长可以根据中序定边界从而划分两边
* 下属写法是最容易理解的写法还有一些较为难理解但是传递索引而不是复制的写法来处理的写法会比这个快
* 速度击败13.81%内存击败15.72% 6ms
* @param inorder
* @param postorder
* @return
*/
public TreeNode buildTree(int[] inorder, int[] postorder) {
int length = postorder.length;
if(length==0){
return null;
}
TreeNode root = new TreeNode(postorder[length - 1]);
int boundary=0;
for (; boundary < inorder.length; boundary++) {
if(inorder[boundary]==postorder[length-1]){
break;
}
}
int[] leftInorder = Arrays.copyOfRange(inorder, 0, boundary);
int[] rightInorder = Arrays.copyOfRange(inorder, boundary+1, length);
int[] leftPostorder = Arrays.copyOfRange(postorder, 0, boundary);
int[] rightPostorder = Arrays.copyOfRange(postorder, boundary, length - 1);
root.left=buildTree(leftInorder,leftPostorder);
root.right=buildTree(rightInorder,rightPostorder);
return root;
}
/**
* 官方最快
* 速度击败100%内存击败72.96%
*/
int post,in;
public TreeNode buildTree1(int[] inorder, int[] postorder) {
post=inorder.length-1;
in=inorder.length-1;
return buildTreeHelper(inorder,postorder,Integer.MAX_VALUE);
}
public TreeNode buildTreeHelper(int[] inorder, int[] postorder, int stop) {
if(post==-1)return null;
if(inorder[in]==stop){//stop是right边界如果触及了右边界就那边就没有值了
in--;
return null;//找到了右边的边界
}
int root_val=postorder[post--];
TreeNode root = new TreeNode(root_val);
root.right=buildTreeHelper(inorder,postorder,root_val);
root.left=buildTreeHelper(inorder,postorder,stop);
return root;
}
}