leecode更新
This commit is contained in:
parent
3524d0c2a9
commit
989eeb2243
|
|
@ -17,7 +17,7 @@ import static com.markilue.leecode.tree.T03_InorderTraversal.inorderTraversal1;
|
|||
* 所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public class TrimBST {
|
||||
public class T24_TrimBST {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
|
@ -16,7 +16,7 @@ import java.util.Stack;
|
|||
* 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public class SortedArrayToBST {
|
||||
public class T25_SortedArrayToBST {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
|
@ -20,7 +20,7 @@ import java.util.Stack;
|
|||
* 左右子树也必须是二叉搜索树。
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public class ConvertBST {
|
||||
public class T26_ConvertBST {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
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;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.tree.second
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2023-01-30 10:59
|
||||
*@Description:
|
||||
* TODO 二刷力扣669题 修剪二叉搜索树:
|
||||
* 给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。
|
||||
* 通过修剪二叉搜索树,使得所有节点的值在[low, high]中。
|
||||
* 修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。
|
||||
* 可以证明,存在 唯一的答案 。
|
||||
* 所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T24_TrimBST {
|
||||
@Test
|
||||
public void test() {
|
||||
TreeNode root = TreeUtils.structureTree(Arrays.asList(3, 1, 4, null, 2), 0);
|
||||
trimBST(root, 3, 4);
|
||||
TreeUtils.printTreeByLevel(root);
|
||||
}
|
||||
|
||||
/**
|
||||
* 思路:找到一个符合范围的就删除,然后再次寻找可以,但是效率太慢了,使用下面这种方式
|
||||
* 速度击败100%,内存击败31.92%
|
||||
* @param root
|
||||
* @param low
|
||||
* @param high
|
||||
* @return
|
||||
*/
|
||||
public TreeNode trimBST(TreeNode root, int low, int high) {
|
||||
if (root == null) {
|
||||
return null;
|
||||
} else if (root.val < low) {
|
||||
return trimBST(root.right, low, high);
|
||||
} else if (root.val > high) {
|
||||
return trimBST(root.left, low, high);
|
||||
}
|
||||
root.left = trimBST(root.left, low, high);
|
||||
root.right = trimBST(root.right, low, high);
|
||||
return root;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 代码随想录提供的一种非递归法思路,将步骤可以总结为:
|
||||
* 1.找到第一个在区间范围内的
|
||||
* 2.处理其左节点范围之外的
|
||||
* 3.处理其右节点范围之外的
|
||||
* 之所以可以这么做,是因为root规定了左子树的右极限;和右子树的左极限
|
||||
* @param root
|
||||
* @param low
|
||||
* @param high
|
||||
* @return
|
||||
*/
|
||||
public TreeNode trimBST1(TreeNode root, int low, int high) {
|
||||
if(root==null)return null;
|
||||
|
||||
|
||||
//处理头结点,让root移动到一个在区间内的数
|
||||
while (root!=null&&(root.val<low||root.val>high)){
|
||||
if(root.val<low)root=root.right;
|
||||
else root= root.left;
|
||||
}
|
||||
|
||||
//找了第一个不是的数
|
||||
//处理其左节点
|
||||
TreeNode cur=root;
|
||||
while (cur!=null){
|
||||
while (cur.left!=null&&cur.left.val<low){
|
||||
cur.left=cur.left.right;
|
||||
}
|
||||
//处理完毕,安心将cur左移,继续判断其左节点会不会超过
|
||||
cur=cur.left;
|
||||
//这里不需要判断右节点,因为root在区间内,那么左子树最大也就是root,所以不会超过其右界
|
||||
}
|
||||
//在处理其右节点
|
||||
cur=root;
|
||||
while (cur!=null){
|
||||
while (cur.right!=null&&cur.right.val>high){
|
||||
cur.right=cur.right.left;
|
||||
}
|
||||
//处理完毕,安心将cur右移,继续判断其左节点会不会超过
|
||||
cur=cur.right;
|
||||
//这里不需要判断左节点,因为root在区间内,那么右子树最小也就是root,所以不会超过其左界
|
||||
}
|
||||
//全部处理完毕,安心返回root
|
||||
return root;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
package com.markilue.leecode.tree.second;
|
||||
|
||||
import com.markilue.leecode.tree.TreeNode;
|
||||
import com.markilue.leecode.tree.TreeUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.tree.second
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2023-01-30 11:36
|
||||
*@Description:
|
||||
* TODO 二刷力扣108题 将有序数组转换为二叉搜索树:
|
||||
* 给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 高度平衡 二叉搜索树。
|
||||
* 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T25_SortedArrayToBST {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
int[] nums = {-10, -3, 0, 5, 9};
|
||||
TreeUtils.printTreeByLevel(sortedArrayToBST(nums));
|
||||
}
|
||||
|
||||
public TreeNode sortedArrayToBST(int[] nums) {
|
||||
return build(nums, 0, nums.length-1);
|
||||
}
|
||||
|
||||
public TreeNode build(int[] nums, int start, int end) {
|
||||
if(start>end)return null;
|
||||
if (start == end) return new TreeNode(nums[start]);
|
||||
int mid = start + ((end - start) >> 1);
|
||||
TreeNode root = new TreeNode(nums[mid]);
|
||||
root.left = build(nums, start, mid - 1);
|
||||
root.right = build(nums, mid + 1, end);
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 这是一种保持左闭右开的方式:由于(right - left) / 2是奇数一定会舍
|
||||
* 所以left + (right - left) / 2<right
|
||||
* @param nums
|
||||
* @param left
|
||||
* @param right
|
||||
* @return
|
||||
*/
|
||||
public TreeNode sorted(int[] nums, int left, int right) {
|
||||
|
||||
|
||||
if (left == right) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int mid = left + (right - left) / 2;
|
||||
TreeNode node = new TreeNode(nums[mid]);
|
||||
|
||||
node.left = sorted(nums, left, mid);
|
||||
node.right = sorted(nums, mid + 1, right);
|
||||
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
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.Arrays;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.tree.second
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2023-01-30 12:02
|
||||
*@Description:
|
||||
* TODO 二刷力扣538题 把二叉搜索树转为累加树:
|
||||
* 给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),
|
||||
* 使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。
|
||||
* 提醒一下,二叉搜索树满足下列约束条件:
|
||||
* 节点的左子树仅包含键 小于 节点键的节点。
|
||||
* 节点的右子树仅包含键 大于 节点键的节点。
|
||||
* 左右子树也必须是二叉搜索树。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T26_ConvertBST {
|
||||
@Test
|
||||
public void test() {
|
||||
TreeNode root = TreeUtils.structureTree(Arrays.asList(4, 1, 6, 0, 2, 5, 7, null, null, null, 3, null, null, null, 8), 0);
|
||||
convertBST2(root);
|
||||
TreeUtils.printTreeByLevel(root);
|
||||
}
|
||||
|
||||
int sum = 0;
|
||||
|
||||
public TreeNode convertBST(TreeNode root) {
|
||||
if (root == null) {
|
||||
return root;
|
||||
}
|
||||
root.right = convertBST(root.right);
|
||||
sum += root.val;
|
||||
root.val = sum;
|
||||
root.left = convertBST(root.left);
|
||||
return root;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 迭代法
|
||||
* @param root
|
||||
* @return
|
||||
*/
|
||||
public TreeNode convertBST1(TreeNode root) {
|
||||
if (root == null) {
|
||||
return root;
|
||||
}
|
||||
Deque<TreeNode> stack = new LinkedList<>();
|
||||
int pre = 0;
|
||||
TreeNode cur = root;
|
||||
while (cur != null || !stack.isEmpty()) {
|
||||
if (cur != null) {
|
||||
stack.push(cur);
|
||||
cur = cur.right;
|
||||
} else {
|
||||
TreeNode node = stack.pop();
|
||||
node.val += pre;
|
||||
pre = node.val;
|
||||
cur = node.left;
|
||||
}
|
||||
}
|
||||
return root;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Morris遍历法
|
||||
* @param root
|
||||
* @return
|
||||
*/
|
||||
public TreeNode convertBST2(TreeNode root) {
|
||||
if (root == null) {
|
||||
return root;
|
||||
}
|
||||
|
||||
TreeNode cur = root;
|
||||
TreeNode pre;
|
||||
int sum=0;
|
||||
while (cur != null) {
|
||||
//寻找其右子树的最左节点
|
||||
pre = cur.right;
|
||||
if (pre != null) {
|
||||
while (pre.left != null && pre.left != cur) {
|
||||
pre = pre.left;
|
||||
}
|
||||
//判断是从什么条件出来的
|
||||
if (pre.left == null) {
|
||||
//第一遍历到
|
||||
pre.left = cur;
|
||||
//放心将其右移
|
||||
cur = cur.right;
|
||||
continue;
|
||||
}
|
||||
else if (pre.left == cur) {
|
||||
//第二次遍历到
|
||||
cur.val+=sum;
|
||||
sum=cur.val;
|
||||
cur=cur.left;
|
||||
pre.left=null;
|
||||
}
|
||||
}else {
|
||||
cur.val+=sum;
|
||||
sum=cur.val;
|
||||
cur=cur.left;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return root;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue