leecode更新

This commit is contained in:
markilue 2022-10-07 12:45:29 +08:00
parent f07804340e
commit 2266507c27
3 changed files with 487 additions and 0 deletions

View File

@ -0,0 +1,187 @@
package com.markilue.leecode.tree;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/**
* @BelongsProject: Leecode
* @BelongsPackage: com.markilue.leecode.tree
* @Author: dingjiawen
* @CreateTime: 2022-10-07 12:08
* @Description:
* TODO leecode 701题 二叉搜索树中的插入操作
* 给定二叉搜索树BST的根节点root和要插入树中的值value将值插入二叉搜索树 返回插入后二叉搜索树的根节点 输入数据 保证 新值和原始二叉搜索树中的任意节点值都不同
* 注意可能存在多种有效的插入方式只要树在插入后仍保持为二叉搜索树即可 你可以返回 任意有效的结果
*
* @Version: 1.0
*/
public class InsertIntoBST {
@Test
public void test(){
TreeNode root = new TreeNode(4);
TreeNode TreeNode2 = new TreeNode(2);
TreeNode TreeNode3 = new TreeNode(7);
TreeNode TreeNode4 = new TreeNode(1);
TreeNode TreeNode5 = new TreeNode(3);
// TreeNode TreeNode6 = new TreeNode(0);
// TreeNode TreeNode7 = new TreeNode(8);
// TreeNode TreeNode8 = new TreeNode(7);
// TreeNode TreeNode9 = new TreeNode(4);
root.setRight(TreeNode3);
root.setLeft(TreeNode2);
TreeNode2.setLeft(TreeNode4);
TreeNode2.setRight(TreeNode5);
// TreeNode3.setRight(TreeNode7);
// TreeNode3.setLeft(TreeNode6);
// TreeNode5.setLeft(TreeNode8);
// TreeNode5.setRight(TreeNode9);
System.out.println(inorderTraversal4(insertIntoBST2(root,5)));
}
/**
* 递归法找到叶子结点即可将val加入
* 速度击败100%内存击败5.13%
* @param root
* @param val
* @return
*/
public TreeNode insertIntoBST(TreeNode root, int val) {
if(root==null) return new TreeNode(val);
if(root.val>val){
root.left=insertIntoBST(root.left,val);
}else {
root.right=insertIntoBST(root.right,val);
}
return root;
}
/**
* 代码随想录无返回值递归法仍然是找到叶子结点即可加入,利用一个parent节点记录之前的节点
* @param root
* @param val
*/
TreeNode parent=null;
public void insert(TreeNode root, int val) {
if(root==null){
TreeNode node = new TreeNode(val);
if(parent.val>val){
parent.left=node;
}else {
parent.right=node;
}
return;
}
parent=root;
if(root.val>val){
insertIntoBST(root.left,val);
}else {
insertIntoBST(root.right,val);
}
}
public TreeNode insertIntoBST1(TreeNode root, int val) {
if(root==null) return new TreeNode(val);
insert(root,val);
return root;
}
/**
* 迭代法:
* 速度击败100% 内存击败12.67%
* @param root
* @param val
* @return
*/
public TreeNode insertIntoBST2(TreeNode root, int val) {
if(root==null) return new TreeNode(val);
TreeNode last=null;
TreeNode temp=root;
while (temp!=null){
last=temp;
if(temp.val>val){
temp=temp.left;
}else {
temp=temp.right;
}
}
if(last.val>val){
last.left=new TreeNode(val);
}else {
last.right=new TreeNode(val);
}
return root;
}
/**
* 自己尝试Morris中序遍历
* 速度超过100%内存超过81.82%
* @param root
*/
public static List<Integer> inorderTraversal4(TreeNode root) {
List<Integer> list1 = new ArrayList<Integer>();
TreeNode node1 = root;
TreeNode node2 = null;
while (node1 != null) {
node2 = node1.left;
//判断左边还有没有值
if(node2!=null){
//首先找到遍历node1之前的最后一个节点
while (node2.right != null && node2.right != node1) {
node2 = node2.right;
}
//判断是从哪个条件出来的
if (node2.right == null) {
//如果是从第一个条件出来的,那么就是没有遍历过得节点
//将这个节点的右边定为node1方便以后回来找到node1
node2.right = node1;
//node1已经可以回溯放心将node1左移
node1 = node1.left;
continue;
} else {
//如果是从第二个条件出来的,那么就是遍历过的节点
//那么他的左边一定是遍历完了,这时将node的值加入结果
list1.add(node1.val);
//左边遍历完了往右移
node1 = node1.right;
}
}else {
//左边没值了
list1.add(node1.val);
node1=node1.right;
}
}
return list1;
}
}

View File

@ -0,0 +1,208 @@
package com.markilue.leecode.tree;
import org.junit.Test;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @BelongsProject: Leecode
* @BelongsPackage: com.markilue.leecode.tree
* @Author: dingjiawen
* @CreateTime: 2022-10-07 09:30
* @Description: TODO 力扣236题 二叉树的最近公共祖先
* 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先
* 百度百科中最近公共祖先的定义为
* 对于有根树 T 的两个节点 pq最近公共祖先表示为一个节点 x满足 x pq 的祖先且 x 的深度尽可能大一个节点也可以是它自己的祖先
* @Version: 1.0
*/
public class LowestCommonAncestor {
@Test
public void test() {
TreeNode root = new TreeNode(3);
TreeNode TreeNode2 = new TreeNode(5);
TreeNode TreeNode3 = new TreeNode(1);
TreeNode TreeNode4 = new TreeNode(6);
TreeNode TreeNode5 = new TreeNode(2);
TreeNode TreeNode6 = new TreeNode(0);
TreeNode TreeNode7 = new TreeNode(8);
TreeNode TreeNode8 = new TreeNode(7);
TreeNode TreeNode9 = new TreeNode(4);
root.setRight(TreeNode3);
root.setLeft(TreeNode2);
TreeNode2.setLeft(TreeNode4);
TreeNode2.setRight(TreeNode5);
TreeNode3.setRight(TreeNode7);
TreeNode3.setLeft(TreeNode6);
TreeNode5.setLeft(TreeNode8);
TreeNode5.setRight(TreeNode9);
System.out.println(lowestCommonAncestor1(root, TreeNode2, TreeNode3).val);
}
@Test
public void test1() {
TreeNode root = new TreeNode(3);
TreeNode TreeNode2 = new TreeNode(5);
TreeNode TreeNode3 = new TreeNode(1);
TreeNode TreeNode4 = new TreeNode(6);
TreeNode TreeNode5 = new TreeNode(2);
TreeNode TreeNode6 = new TreeNode(0);
TreeNode TreeNode7 = new TreeNode(8);
TreeNode TreeNode8 = new TreeNode(7);
TreeNode TreeNode9 = new TreeNode(4);
root.setRight(TreeNode3);
root.setLeft(TreeNode2);
TreeNode2.setLeft(TreeNode4);
TreeNode2.setRight(TreeNode5);
TreeNode3.setRight(TreeNode7);
TreeNode3.setLeft(TreeNode6);
TreeNode5.setLeft(TreeNode8);
TreeNode5.setRight(TreeNode9);
System.out.println(lowestCommonAncestor1(root, TreeNode2, TreeNode9).val);
}
/**
* 本人思路递归法用一个boolean值记录是否找到了p,q如果找到了就可以返回当前叶子节点
* 速度超过5.09%内存超过38.12%
* 慢之处在于即使找到了还需要继续遍历因为本人这种方式是自顶向下遍历的方式找到的不一定是最近公共祖先只能通过不断遍历的方式确定
*
* @param root
* @param p
* @param q
* @return
*/
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
find(root, p, q);
return result;
}
TreeNode result = null;
boolean flag = false;
public boolean find(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return false;
}
//记录两个树值是否找到
boolean flagp = false;
boolean flagq = false;
if (p != null) {
if (root.val == p.val) {
flagp = true;
} else {
//这里只找p
flagp = find(root.left, p, null) || find(root.right, p, null);
}
}
if (q != null) {
if (root.val == q.val) {
flagq = true;
} else {
flagq = find(root.left, null, q) || find(root.right, null, q);
}
}
if (flagp && flagq) {
result = root;
find(root.left, p, q);
find(root.right, p, q);
// flag = true;
}
return flagp || flagq;
}
/**
* 代码随想录思路递归法最近节点->如果能自底向上查找就好了因此可以使用回溯回溯的过程就是自底向上二叉树的后续遍历就符合回溯过程先处理的一定是叶子结点
* 速度超过100%内存超过28.79%
* <p>
* 递归三部曲
* 1确定递归函数返回值和参数TreeNode 找到了就返回这个节点
* 2确定终止条件找到p或q或者空节点就返回
* 3确定单层递归逻辑通过递归函数确定该节点是不是公共节点
*
*
* @param root
* @param p
* @param q
* @return
*/
public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) {
//这里之所以可以直接等于就返回是因为后边还有判断right边有没有如果right边没有那么一定是在left边的子树上这里默认两个子树一定存在
if (root == p || root == q || root == null) return root;
TreeNode left = lowestCommonAncestor1(root.left, p, q);
TreeNode right = lowestCommonAncestor1(root.right, p, q);
//如果left和right都有值那么证明当前节点就是最近
//反之如果任意没有值就返回另一边
if(left!=null&&right!=null){
return root;
}else if(left==null){
return right;
}else {
return left;
}
}
Map<Integer, TreeNode> parent = new HashMap<Integer, TreeNode>();
Set<Integer> visited = new HashSet<Integer>();
public void dfs(TreeNode root) {
if (root.left != null) {
parent.put(root.left.val, root);
dfs(root.left);
}
if (root.right != null) {
parent.put(root.right.val, root);
dfs(root.right);
}
}
/**
* 官方另一种解法利用map记录父节点q不断回溯来寻找最近节点
* @param root
* @param p
* @param q
* @return
*/
public TreeNode lowestCommonAncestor2(TreeNode root, TreeNode p, TreeNode q) {
dfs(root);
while (p != null) {
visited.add(p.val);
p = parent.get(p.val);
}
while (q != null) {
if (visited.contains(q.val)) {
return q;
}
q = parent.get(q.val);
}
return null;
}
}

View File

@ -0,0 +1,92 @@
package com.markilue.leecode.tree;
import org.junit.Test;
/**
* @BelongsProject: Leecode
* @BelongsPackage: com.markilue.leecode.tree
* @Author: dingjiawen
* @CreateTime: 2022-10-07 11:29
* @Description: TODO leecode 235题 二叉搜索树的最近公共祖先
* 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先
* 百度百科中最近公共祖先的定义为
* 对于有根树 T 的两个结点 pq最近公共祖先表示为一个结点 x满足 x pq 的祖先且 x 的深度尽可能大一个节点也可以是它自己的祖先
* @Version: 1.0
*/
public class LowestCommonAncestorII {
@Test
public void test(){
TreeNode root = new TreeNode(6);
TreeNode TreeNode2 = new TreeNode(2);
TreeNode TreeNode3 = new TreeNode(8);
TreeNode TreeNode4 = new TreeNode(0);
TreeNode TreeNode5 = new TreeNode(4);
TreeNode TreeNode6 = new TreeNode(7);
TreeNode TreeNode7 = new TreeNode(9);
TreeNode TreeNode8 = new TreeNode(3);
TreeNode TreeNode9 = new TreeNode(5);
root.setRight(TreeNode3);
root.setLeft(TreeNode2);
TreeNode2.setLeft(TreeNode4);
TreeNode2.setRight(TreeNode5);
TreeNode3.setRight(TreeNode7);
TreeNode3.setLeft(TreeNode6);
TreeNode5.setLeft(TreeNode8);
TreeNode5.setRight(TreeNode9);
System.out.println(lowestCommonAncestor(root, TreeNode2, TreeNode3).val);
System.out.println(lowestCommonAncestor(root, TreeNode2, TreeNode5).val);
}
/**
* 二叉搜索树的特性root节点比左边大右边小
* 速度击败36.19%内存击败82.68%
* @param root
* @param p
* @param q
* @return
*/
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null ) return root;
if(root.val>p.val&&root.val>q.val){
return lowestCommonAncestor(root.left, p, q);
}
if(root.val<p.val&&root.val<q.val){
return lowestCommonAncestor(root.right, p, q);
}
return root;
}
/**
* 迭代法依然是利用当前节点比左边大比右边节点小这个特性
* @param root
* @param p
* @param q
* @return
*/
public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) {
TreeNode ancestor = root;
while (true) {
if (p.val < ancestor.val && q.val < ancestor.val) {
ancestor = ancestor.left;
} else if (p.val > ancestor.val && q.val > ancestor.val) {
ancestor = ancestor.right;
} else {
break;
}
}
return ancestor;
}
}