leecode更新

This commit is contained in:
markilue 2023-01-06 15:17:43 +08:00
parent 88bbded9ca
commit 28e1a9c674
10 changed files with 808 additions and 0 deletions

View File

@ -0,0 +1,27 @@
package com.markilue.leecode.tree.second;
import java.util.List;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-06 10:55
*@Description: TODO N叉树节点
*@Version: 1.0
*/
public class NNode {
public int val;
public List<NNode> children;
public NNode() {}
public NNode(int _val) {
val = _val;
}
public NNode(int _val, List<NNode> _children) {
val = _val;
children = _children;
}
}

View File

@ -0,0 +1,30 @@
package com.markilue.leecode.tree.second;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-06 11:36
*@Description: TODO 完美二叉树
*@Version: 1.0
*/
public class Node {
public int val;
public Node left;
public Node right;
public Node next;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, Node _left, Node _right, Node _next) {
val = _val;
left = _left;
right = _right;
next = _next;
}
}

View File

@ -0,0 +1,77 @@
package com.markilue.leecode.tree.second;
import com.markilue.leecode.tree.TreeNode;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-06 09:55
*@Description:
* TODO leecode199题 二叉树的右视图:
* 给定一个二叉树的 根节点 root想象自己站在它的右侧按照从顶部到底部的顺序返回从右侧所能看到的节点值
*@Version: 1.0
*/
public class T042_RightSideView {
/**
* 思路就是返回他所有最右侧的节点层序遍历确实可以解决返回每一层最后的节点
* 速度击败82.5%内存击败35.82%
* @param root
* @return
*/
public List<Integer> rightSideView(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root==null){
return result;
}
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==size-1){//每层的最右一个,就是最右节点
result.add(node.val);
}
if(node.left!=null)queue.offer(node.left);
if(node.right!=null)queue.offer(node.right);
}
}
return result;
}
/**
* 思路尝试dfs实现层序遍历返回每一层最后的节点
* 速度击败100%内存击败27.1%
* @param root
* @return
*/
List<Integer> result = new ArrayList<>();
public List<Integer> rightSideView1(TreeNode root) {
dfs(root,0);
return result;
}
//核心在于如何判断他是一层最后一个官方思路如果先遍历右子树那么就是那一层第一个
public void dfs(TreeNode node,int depth){
if(node==null){
return;
}
if(result.size()==depth){
result.add(node.val);
}
dfs(node.right,depth+1);
dfs(node.left,depth+1);
}
}

View File

@ -0,0 +1,130 @@
package com.markilue.leecode.tree.second;
import com.markilue.leecode.tree.TreeNode;
import com.markilue.leecode.tree.TreeUtils;
import org.junit.Test;
import java.util.*;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-06 10:23
*@Description:
* TODO leecode637题 二叉树的层平均值:
* 给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值与实际答案相差 10-5 以内的答案可以被接受
*@Version: 1.0
*/
public class T043_averageOfLevels {
@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(averageOfLevels1(root));
}
/**
* 思路:BFS层平均值,求出总和之后除以个数所以需要知道本层所有节点
* 速度击败93.66%内存击败52.84% 2ms
* @param root
* @return
*/
public List<Double> averageOfLevels(TreeNode root) {
List<Double> result = new ArrayList<>();
if(root==null){
return result;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int size = queue.size();
Double sum=0d;
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
sum+=node.val;
if(node.left!=null)queue.offer(node.left);
if(node.right!=null)queue.offer(node.right);
}
result.add(sum/size);
}
return result;
}
/**
* 思路:尝试dfs,获取每层总和和每个节点个数
* 速度击败93.66%内存击败21.8% 2ms
* @param root
* @return
*/
List<Double> result = new ArrayList<>();
List<Integer> depthList = new ArrayList<>();//存储每层个数
public List<Double> averageOfLevels1(TreeNode root) {
dfs(root,0);
for (int i = 0; i < result.size(); i++) {
result.set(i,result.get(i)/depthList.get(i));//求平均值
}
return result;
}
public void dfs(TreeNode node,int depth) {
if(node==null){
return;
}
if(result.size()==depth){
result.add(0d);
}
if(depthList.size()==depth){
depthList.add(0);
}
dfs(node.left,depth+1);
dfs(node.right,depth+1);
result.set(depth,result.get(depth)+node.val);
depthList.set(depth,depthList.get(depth)+1);
}
/**
* 官方最快:本质上和本人的dfs无差异,比本人少设一次0值
* 速度击败100%内存击败26.25% 1ms
* @param root
* @return
*/
public List<Double> averageOfLevels2(TreeNode root) {
List<Integer> counts = new ArrayList<>();
List<Double> sum = new ArrayList<>();
dfs2(root, 0, counts, sum);
List<Double> result = new ArrayList<>();
for (int i = 0; i < counts.size(); i++) {
result.add(sum.get(i) / counts.get(i));
}
return result;
}
private void dfs2(TreeNode root, int level,List<Integer> counts, List<Double> sum) {
if (root == null) {
return;
}
if (level < counts.size()) {
counts.set(level, counts.get(level) + 1);
sum.set(level, sum.get(level) + root.val);
} else {
counts.add(1);
sum.add(1.0 * root.val);
}
dfs2(root.left, level + 1, counts, sum);
dfs2(root.right, level +1, counts, sum);
}
}

View File

@ -0,0 +1,79 @@
package com.markilue.leecode.tree.second;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-06 10:54
*@Description:
* TODO 力扣429题 N 叉树的层序遍历:
* 给定一个 N 叉树返回其节点值的层序遍历即从左到右逐层遍历
* 树的序列化输入是用层序遍历每组子节点都由 null 值分隔参见示例
*@Version: 1.0
*/
public class T044_LevelOrder {
/**
* 思路N叉树的层序遍历本质上和二叉树无异BFS层序遍历版
* 速度击败84.2%内存击败10.36% 3ms
* @param root
* @return
*/
public List<List<Integer>> levelOrder(NNode root) {
List<List<Integer>> result = new ArrayList<>();
if(root==null){
return result;
}
Queue<NNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int size = queue.size();
List<Integer> cur = new ArrayList<>();
for (int i = 0; i < size; i++) {
NNode NNode = queue.poll();
cur.add(NNode.val);
for (NNode child : NNode.children) {
if(child!=null){
queue.offer(child);
}
}
}
result.add(cur);
}
return result;
}
/**
* 思路N叉树的层序遍历 尝试dfs版
* 速度击败100%内存击败27.66% 0ms
* @param root
* @return
*/
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> levelOrder1(NNode root) {
dfs(root,0);
return result;
}
public void dfs(NNode NNode, int depth) {
if(NNode ==null){
return;
}
if(result.size()==depth){
result.add(new ArrayList<Integer>());
}
for (NNode child : NNode.children) {
dfs(child,depth+1);
}
result.get(depth).add(NNode.val);
}
}

View File

@ -0,0 +1,83 @@
package com.markilue.leecode.tree.second;
import com.markilue.leecode.tree.TreeNode;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-06 11:18
*@Description:
* TODO 力扣515题 在每个树行中找最大值
* 给定一棵二叉树的根节点 root 请找出该二叉树中每一层的最大值
*@Version: 1.0
*/
public class T045_LargestValues {
/**
* 思路:仍然是每行的最大值,层序遍历的题 BFS
* 速度击败84.54%内存击败72.7% 2ms
* @param root
* @return
*/
public List<Integer> largestValues(TreeNode root) {
List<Integer> result = new ArrayList<>();
if(root==null){
return result;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int size = queue.size();
int max=Integer.MIN_VALUE;
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
if(max<node.val)max=node.val;
if(node.left!=null)queue.offer(node.left);
if(node.right!=null)queue.offer(node.right);
}
result.add(max);
}
return result;
}
/**
* 思路:仍然是每行的最大值, DFS
* 速度击败100%内存击败5.4% 0ms
* @param root
* @return
*/
List<Integer> result = new ArrayList<>();
public List<Integer> largestValues1(TreeNode root) {
dfs(root,0);
return result;
}
public void dfs(TreeNode node,int depth){
if(node==null){
return;
}
if(result.size()==depth){
result.add(node.val);
}else {
Integer now = result.get(depth);
if(now<node.val){
result.set(depth,node.val);
}
}
dfs(node.left, depth+1);
dfs(node.right, depth+1);
}
}

View File

@ -0,0 +1,85 @@
package com.markilue.leecode.tree.second;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-06 11:31
*@Description:
* TODO 力扣116题 填充每个节点的下一个右侧节点指针
* 给定一个 完美二叉树 其所有叶子节点都在同一层每个父节点都有两个子节点二叉树定义如下
* struct Node {
* int val;
* Node *left;
* Node *right;
* Node *next;
* }
* 填充它的每个 next 指针让这个指针指向其下一个右侧节点如果找不到下一个右侧节点则将 next 指针设置为 NULL
*
* 初始状态下所有 next 指针都被设置为 NULL
*@Version: 1.0
*/
public class T046_Connect {
/**
* 思路:本质上还是每层之间彼此连接BFS
* 速度击败70.41%内存击败69.1% 2ms
* @param root
* @return
*/
public Node connect(Node root) {
if(root==null){
return root;
}
Deque<Node> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int size = queue.size();
Node pre=null;
for (int i = 0; i < size; i++) {
Node node = queue.poll();
if(pre!=null)pre.next=node;
if(node.left!=null)queue.offer(node.left);
if(node.right!=null)queue.offer(node.right);
pre=node;
}
}
return root;
}
/**
* 思路:本质上还是每层之间彼此连接DFS使用一个list记录每一层的上一个节点
* 速度击败100%内存击败57.66% 0ms
* @param root
* @return
*/
List<Node> preList=new ArrayList<>();
public Node connect1(Node root) {
dfs(root,0);
return root;
}
public void dfs(Node node,int depth) {
if(node==null){
return;
}
if(preList.size()==depth){
preList.add(node);
}else {
Node pre = preList.get(depth);
pre.next=node;
preList.set(depth,node);
}
dfs(node.left,depth+1);
dfs(node.right,depth+1);
}
}

View File

@ -0,0 +1,132 @@
package com.markilue.leecode.tree.second;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-06 11:31
*@Description:
* TODO 力扣116题 填充每个节点的下一个右侧节点指针
* 给定一个二叉树 二叉树定义如下
* struct Node {
* int val;
* Node *left;
* Node *right;
* Node *next;
* }
* 填充它的每个 next 指针让这个指针指向其下一个右侧节点如果找不到下一个右侧节点则将 next 指针设置为 NULL
* 初始状态下所有 next 指针都被设置为 NULL
* 与T46似乎完全一致,所以代码完全没有改动
*@Version: 1.0
*/
public class T047_Connect {
/**
* 思路:本质上还是每层之间彼此连接BFS
* 速度击败66.57%内存击败58.33% 1ms
* @param root
* @return
*/
public Node connect(Node root) {
if(root==null){
return root;
}
Deque<Node> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int size = queue.size();
Node pre=null;
for (int i = 0; i < size; i++) {
Node node = queue.poll();
if(pre!=null)pre.next=node;
if(node.left!=null)queue.offer(node.left);
if(node.right!=null)queue.offer(node.right);
pre=node;
}
}
return root;
}
/**
* 思路:本质上还是每层之间彼此连接DFS使用一个list记录每一层的上一个节点
* 速度击败100%内存击败67.82% 0ms
* @param root
* @return
*/
List<Node> preList=new ArrayList<>();
public Node connect1(Node root) {
dfs(root,0);
return root;
}
public void dfs(Node node,int depth) {
if(node==null){
return;
}
if(preList.size()==depth){
preList.add(node);
}else {
Node pre = preList.get(depth);
pre.next=node;
preList.set(depth,node);
}
dfs(node.left,depth+1);
dfs(node.right,depth+1);
}
/**
* 评论区针对第一种queue思路的优化:
* TODO
* 上面运行效率并不是很高这是因为我们把节点不同的入队然后再不停的出队
* 其实可以不需要队列每一行都可以看成一个链表比如第一行就是只有一个节点的链表
* 第二行是只有两个节点的链表假如根节点的左右两个子节点都不为空
* 速度击败100%内存击败65.71%
* @param root
* @return
*/
public Node connect2(Node root) {
if (root == null)
return root;
//cur我们可以把它看做是每一层的链表的头结点
Node cur = root;
while (cur != null) {
//遍历当前层的时候为了方便操作在下一
//层前面添加一个哑结点注意这里是访问
//当前层的节点然后把下一层的节点串起来
Node dummy = new Node(0);
//pre表示访下一层节点的前一个节点
Node pre = dummy;
//然后开始遍历当前层的链表
while (cur != null) {
if (cur.left != null) {
//如果当前节点的左子节点不为空就让pre节点
//的next指向他也就是把它串起来
pre.next = cur.left;
//然后再更新pre
pre = pre.next;
}
//同理参照左子树
if (cur.right != null) {
pre.next = cur.right;
pre = pre.next;
}
//继续访问这一行的下一个节点
cur = cur.next;
}
//把下一层串联成一个链表之后让他赋值给cur
//后续继续循环直到cur为空为止
cur = dummy.next;
}
return root;
}
}

View File

@ -0,0 +1,72 @@
package com.markilue.leecode.tree.second;
import com.markilue.leecode.tree.TreeNode;
import java.util.LinkedList;
import java.util.Queue;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-06 12:22
*@Description:
* TODO 力扣104题 二叉树的最大深度:
* 给定一个二叉树找出其最大深度
* 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数
* 说明: 叶子节点是指没有子节点的节点
*@Version: 1.0
*/
public class T048_MaxDepth {
/**
* 思路:深度本质上就是要遍历到最底层
* 速度击败19.79%内存击败56.29%
* @param root
* @return
*/
public int maxDepth(TreeNode root) {
int depth=0;
if(root==null){
return depth;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int size = queue.size();
depth++;
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
if(node.left!=null)queue.offer(node.left);
if(node.right!=null)queue.offer(node.right);
}
}
return depth;
}
/**
* 思路:深度本质上就是要遍历到最底层DFS法
* 速度击败100%内存击败10.99%
* @param root
* @return
*/
int maxDepth=0;
public int maxDepth1(TreeNode root) {
dfs(root,1);
return maxDepth;
}
public void dfs(TreeNode node,int depth){
if(node==null){
return;
}
if(maxDepth<depth){
maxDepth=depth;
}
dfs(node.left,depth+1);
dfs(node.right,depth+1);
}
;
}

View File

@ -0,0 +1,93 @@
package com.markilue.leecode.tree.second;
import com.markilue.leecode.tree.TreeNode;
import com.markilue.leecode.tree.TreeUtils;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.tree.second
*@Author: dingjiawen
*@CreateTime: 2023-01-06 14:22
*@Description:
* TODO 力扣111题 二叉树的最小深度:
* 给定一个二叉树找出其最小深度
* 最小深度是从根节点到最近叶子节点的最短路径上的节点数量
* 说明叶子节点是指没有子节点的节点
*@Version: 1.0
*/
public class T049_MinDepth {
@Test
public void test() {
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,4,5));
TreeNode root = TreeUtils.structureTree(list, 0);
System.out.println(minDepth1(root));
}
/**
* 思路
* 1)如果有左右结点分别计算左右节点深度取最小
* 2)如果只有左或右节点返回另一边深度
* 3)如果两边有没有了那么就是叶子结点返回1
* 速度击败34.68%内存击败5.87% 9ms
* 慢在哪里?找到第一个叶子节点了还是不能返回得判断另一端
* @param root
* @return
*/
public int minDepth(TreeNode root) {
if(root==null){
return 0;
}
if(root.left==null&&root.right==null){
return 1;
}else if(root.left==null){
return minDepth(root.right)+1;
}else if(root.right==null){
return minDepth(root.left)+1;
}
return Math.min(minDepth(root.left),minDepth(root.right))+1;
}
/**
* 思路尝试使用层序遍历优化,核心在于找到第一个叶子节点就返回
* 速度击败100%内存击败73.53% 0ms
* @param root
* @return
*/
public int minDepth1(TreeNode root) {
int depth=0;
if(root==null){
return depth;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int size = queue.size();
depth++;
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
if(node.left==null&&node.right==null){
return depth;
}
if(node.left!=null){
queue.offer(node.left);
}
if(node.right!=null){
queue.offer(node.right);
}
}
}
return depth;
}
}