leecode更新

This commit is contained in:
markilue 2023-01-29 14:55:39 +08:00
parent 40313d9da9
commit 3524d0c2a9
8 changed files with 326 additions and 4 deletions

View File

@ -18,7 +18,7 @@ import java.util.Set;
* 对于有根树 T 的两个节点 pq最近公共祖先表示为一个节点 x满足 x pq 的祖先且 x 的深度尽可能大一个节点也可以是它自己的祖先 * 对于有根树 T 的两个节点 pq最近公共祖先表示为一个节点 x满足 x pq 的祖先且 x 的深度尽可能大一个节点也可以是它自己的祖先
* @Version: 1.0 * @Version: 1.0
*/ */
public class LowestCommonAncestor { public class T20_LowestCommonAncestor {
@Test @Test
public void test() { public void test() {

View File

@ -13,7 +13,7 @@ import org.junit.Test;
* 对于有根树 T 的两个结点 pq最近公共祖先表示为一个结点 x满足 x pq 的祖先且 x 的深度尽可能大一个节点也可以是它自己的祖先 * 对于有根树 T 的两个结点 pq最近公共祖先表示为一个结点 x满足 x pq 的祖先且 x 的深度尽可能大一个节点也可以是它自己的祖先
* @Version: 1.0 * @Version: 1.0
*/ */
public class LowestCommonAncestorII { public class T21_LowestCommonAncestorII {
@Test @Test
public void test(){ public void test(){

View File

@ -17,7 +17,7 @@ import java.util.List;
* *
* @Version: 1.0 * @Version: 1.0
*/ */
public class InsertIntoBST { public class T22_InsertIntoBST {
@Test @Test
public void test(){ public void test(){

View File

@ -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) { public static void main(String[] args) {

View File

@ -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 的两个节点 pq最近公共祖先表示为一个节点 x
* 满足 x pq 的祖先且 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;
}
}

View File

@ -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 的两个结点 pq最近公共祖先表示为一个结点 x满足 x pq 的祖先且 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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}