leecode更新
This commit is contained in:
parent
40313d9da9
commit
3524d0c2a9
|
|
@ -18,7 +18,7 @@ import java.util.Set;
|
|||
* “对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public class LowestCommonAncestor {
|
||||
public class T20_LowestCommonAncestor {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
|
@ -13,7 +13,7 @@ import org.junit.Test;
|
|||
* “对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public class LowestCommonAncestorII {
|
||||
public class T21_LowestCommonAncestorII {
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
|
|
@ -17,7 +17,7 @@ import java.util.List;
|
|||
*
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public class InsertIntoBST {
|
||||
public class T22_InsertIntoBST {
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
|
|
@ -9,7 +9,7 @@ import static com.markilue.leecode.tree.T03_InorderTraversal.inorderTraversal1;
|
|||
/**
|
||||
* 删除二叉排序树的某个节点
|
||||
*/
|
||||
public class DeleteNode {
|
||||
public class T23_DeleteNode {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
package com.markilue.leecode.tree.second;
|
||||
|
||||
import com.markilue.leecode.tree.TreeNode;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.tree.second
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2023-01-29 10:08
|
||||
*@Description:
|
||||
* TODO 二刷力扣236题 二叉树的最近公共祖先:
|
||||
* 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
|
||||
* 百度百科中最近公共祖先的定义为:
|
||||
* “对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,
|
||||
* 满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
|
||||
*
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T20_LowestCommonAncestor {
|
||||
|
||||
|
||||
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
|
||||
if (root == null) {
|
||||
return root;
|
||||
}
|
||||
//这里之所以可以直接返回,而不怕其子树中有另一个节点,
|
||||
// 是因为后面如果都不满足会直接返回root,如果root里面有子树,那么root也是最近祖先
|
||||
if(root.val==p.val||root.val==q.val){
|
||||
return root;
|
||||
}
|
||||
TreeNode node = lowestCommonAncestor(root.left, p, q);
|
||||
TreeNode node1 = lowestCommonAncestor(root.right, p, q);
|
||||
if (node == null) {
|
||||
return node1;
|
||||
} else if (node1 == null) {
|
||||
return node;
|
||||
} else if (node.val == p.val && node1.val == q.val || node.val == q.val && node1.val == p.val) {
|
||||
//这个判断条件可以优化为left和right都不等于null,就可以返回root
|
||||
return root;
|
||||
}
|
||||
|
||||
return root;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 官方最快
|
||||
* 5ms
|
||||
* @param root
|
||||
* @param p
|
||||
* @param q
|
||||
* @return
|
||||
*/
|
||||
public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) {
|
||||
if (root == null || root == p || root == q) return root;
|
||||
TreeNode left = lowestCommonAncestor1(root.left, p, q);
|
||||
TreeNode right = lowestCommonAncestor1(root.right, p, q);
|
||||
if (left != null && right != null) {return root;}
|
||||
return left != null ? left : right;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
package com.markilue.leecode.tree.second;
|
||||
|
||||
import com.markilue.leecode.tree.TreeNode;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.tree.second
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2023-01-29 10:52
|
||||
*@Description:
|
||||
* TODO 二刷力扣235题 二叉搜索树的最近公共祖先:
|
||||
* 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
|
||||
* 百度百科中最近公共祖先的定义为:
|
||||
* “对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
|
||||
* 例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5]
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T21_LowestCommonAncestorII {
|
||||
|
||||
/**
|
||||
* 思路:理论上来说,适用于普通二叉树的方式,也适用于二叉搜索树
|
||||
* 速度击败35.59%,内存击败19.97%
|
||||
* @param root
|
||||
* @param p
|
||||
* @param q
|
||||
* @return
|
||||
*/
|
||||
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
|
||||
if(root==null|| root.val==p.val||root.val==q.val)return root;
|
||||
TreeNode left = lowestCommonAncestor(root.left, p, q);
|
||||
TreeNode right = lowestCommonAncestor(root.right, p, q);
|
||||
if(left!=null&&right!=null)return root;
|
||||
return left==null?right:left;
|
||||
}
|
||||
|
||||
/**
|
||||
* 思路:从上往下找,找到第一个在p和q中间的值,就一定是他们的公共祖先
|
||||
* 速度击败99.96%,内存击败93.11% 5ms
|
||||
* @param root
|
||||
* @param p
|
||||
* @param q
|
||||
* @return
|
||||
*/
|
||||
public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) {
|
||||
if(root==null)return root;
|
||||
if(p.val>q.val){
|
||||
TreeNode temp=p;
|
||||
p=q;
|
||||
q=temp;
|
||||
}
|
||||
if(root.val<=q.val&&root.val>=p.val){
|
||||
return root;
|
||||
}else if(root.val<p.val){
|
||||
return lowestCommonAncestor1(root.right,p,q);
|
||||
}else {
|
||||
return lowestCommonAncestor1(root.left, p, q);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 官方最快:使用迭代法完成左右的查找工作
|
||||
* 速度击败99.96%,内存击败21.90% 5ms
|
||||
* @param root
|
||||
* @param p
|
||||
* @param q
|
||||
* @return
|
||||
*/
|
||||
public TreeNode lowestCommonAncestor2(TreeNode root, TreeNode p, TreeNode q) {
|
||||
int pv = p.val;
|
||||
int qv = q.val;
|
||||
int rv = root.val;
|
||||
while ( rv < Math.min(pv, qv) || rv > Math.max(pv,qv)) {
|
||||
if (rv < Math.min(pv, qv)) {
|
||||
root = root.right;
|
||||
rv = root.val;
|
||||
}
|
||||
else {
|
||||
root = root.left;
|
||||
rv = root.val;
|
||||
}
|
||||
}
|
||||
return root;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 针对最快的改进,一直计算最大最小太麻烦了,直接存起来
|
||||
* 速度击败99.96%,内存击败59.90% 5ms
|
||||
* @param root
|
||||
* @param p
|
||||
* @param q
|
||||
* @return
|
||||
*/
|
||||
public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode p, TreeNode q) {
|
||||
int min = Math.min(p.val, q.val);
|
||||
int max = Math.max(p.val, q.val);
|
||||
int rv = root.val;
|
||||
while ( rv < min || rv >max ) {
|
||||
if (rv < min) {
|
||||
root = root.right;
|
||||
rv = root.val;
|
||||
}
|
||||
else {
|
||||
root = root.left;
|
||||
rv = root.val;
|
||||
}
|
||||
}
|
||||
return root;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package com.markilue.leecode.tree.second;
|
||||
|
||||
import com.markilue.leecode.tree.TreeNode;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.tree.second
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2023-01-29 11:19
|
||||
*@Description:
|
||||
* TODO 二刷力扣701 二叉搜索树中的插入操作:
|
||||
* 给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。
|
||||
* 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。
|
||||
* 注意,可能存在多种有效的插入方式,只要树在插入后仍保持为二叉搜索树即可。 你可以返回 任意有效的结果 。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T22_InsertIntoBST {
|
||||
|
||||
/**
|
||||
* 思路:找到合适的位置插在叶子结点
|
||||
* 速度击败100%,内存击败11.89%
|
||||
* @param root
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public TreeNode insertIntoBST(TreeNode root, int val) {
|
||||
if (root == null) {
|
||||
return new TreeNode(val);
|
||||
}
|
||||
TreeNode temp = root;
|
||||
insert(root, val);
|
||||
return root;
|
||||
|
||||
}
|
||||
|
||||
public void insert(TreeNode root, int val) {
|
||||
if (root.val < val) {
|
||||
if (root.right == null) root.right = new TreeNode(val);
|
||||
else insertIntoBST(root.right, val);
|
||||
} else {
|
||||
if (root.left == null) root.left = new TreeNode(val);
|
||||
else insertIntoBST(root.left, val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 代码随想录优秀写法
|
||||
* @param root
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
public TreeNode insertIntoBST1(TreeNode root, int val) {
|
||||
if (root == null) // 如果当前节点为空,也就意味着val找到了合适的位置,此时创建节点直接返回。
|
||||
return new TreeNode(val);
|
||||
|
||||
if (root.val < val){
|
||||
root.right = insertIntoBST(root.right, val); // 递归创建右子树
|
||||
}else if (root.val > val){
|
||||
root.left = insertIntoBST(root.left, val); // 递归创建左子树
|
||||
}
|
||||
return root;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package com.markilue.leecode.tree.second;
|
||||
|
||||
import com.markilue.leecode.tree.TreeNode;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.tree.second
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2023-01-29 11:53
|
||||
*@Description:
|
||||
* TODO 二刷力扣450题 删除二叉搜索树中的节点:
|
||||
* 给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。
|
||||
* 一般来说,删除节点可分为两个步骤:
|
||||
* 首先找到需要删除的节点;
|
||||
* 如果找到了,删除它。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T23_DeleteNode {
|
||||
|
||||
/**
|
||||
* 核心思路:找到需要删除的节点,然后寻找其左子树的最右节点或右子树的最左节点,将其赋值给当前节点;
|
||||
* 然后变为删除这个最左右节点(该节点最多只有一个子树)
|
||||
* 速度击败100%,内存击败41.24%
|
||||
* @param root
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
public TreeNode deleteNode(TreeNode root, int key) {
|
||||
if (root == null) {
|
||||
return root;
|
||||
}
|
||||
TreeNode temp = root;
|
||||
|
||||
|
||||
TreeNode pre = null;//父节点
|
||||
//寻找需要删除的节点
|
||||
while (temp != null && temp.val != key) {
|
||||
pre = temp;
|
||||
if (temp.val > key) {
|
||||
temp = temp.left;
|
||||
} else {
|
||||
temp = temp.right;
|
||||
}
|
||||
}
|
||||
if(temp==null){
|
||||
//没找到
|
||||
return root;
|
||||
}
|
||||
|
||||
//寻找要删除节点其右子树的最左节点
|
||||
TreeNode need=null;
|
||||
if (temp.right != null) {
|
||||
pre = temp;
|
||||
need = temp.right;
|
||||
while (need.left != null) {
|
||||
pre = need;
|
||||
need = need.left;
|
||||
}
|
||||
temp.val = need.val;
|
||||
}else {
|
||||
need=temp;
|
||||
}
|
||||
|
||||
//后续删除need节点;need最多仅有一个节点
|
||||
TreeNode child = need.left == null ? need.right : need.left;
|
||||
if (pre == null) {
|
||||
//删除的是root节点
|
||||
return child;
|
||||
}
|
||||
|
||||
|
||||
if(pre.left==need){
|
||||
pre.left=child;
|
||||
}else {
|
||||
pre.right=child;
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue