leecode更新

This commit is contained in:
markilue 2022-09-27 12:32:13 +08:00
parent 16865a08b6
commit f07804340e
2 changed files with 489 additions and 0 deletions

View File

@ -0,0 +1,254 @@
package com.markilue.leecode.tree;
import org.junit.Test;
import javax.transaction.TransactionRequiredException;
import java.util.*;
/**
* @BelongsProject: Leecode
* @BelongsPackage: com.markilue.leecode.tree
* @Author: dingjiawen
* @CreateTime: 2022-09-27 10:58
* @Description: TODO 力扣501题 二叉搜索树中的众数:
* 给你一个含重复值的二叉搜索树BST的根节点 root 找出并返回 BST 中的所有 众数出现频率最高的元素
* 如果树中有不止一个众数可以按 任意顺序 返回
* 假定 BST 满足如下定义
* 结点左子树中所含节点的值 小于等于 当前节点的值
* 结点右子树中所含节点的值 大于等于 当前节点的值
* 左子树和右子树都是二叉搜索树
* @Version: 1.0
*/
public class FindMode {
@Test
public void test() {
TreeNode root = new TreeNode(1);
TreeNode TreeNode2 = new TreeNode(2);
TreeNode TreeNode3 = new TreeNode(2);
// TreeNode TreeNode4 = new TreeNode(4);
// TreeNode TreeNode5 = new TreeNode(5);
// TreeNode TreeNode6 = new TreeNode(15);
// TreeNode TreeNode7 = new TreeNode(7);
root.setRight(TreeNode2);
TreeNode2.setLeft(TreeNode3);
// TreeNode2.setLeft(TreeNode4);
// TreeNode2.setRight(TreeNode5);
// TreeNode3.setRight(TreeNode7);
// TreeNode3.setLeft(TreeNode6);
System.out.println(Arrays.toString(findMode(root)));
}
// PriorityQueue queue = new PriorityQueue<int[]>(new Comparator<int[]>() {
//
// @Override
// public int compare(int[] o1, int[] o2) {
// //int[val,count]
// return o1[1] != o2[1] ? o1[1] - o2[1] : o1[0] - o2[0];
//
// }
// });
//这里使用ArrayList因为不想自己动态扩容
List<int[]> list = new ArrayList<int[]>();
TreeNode pre = null;
int count = 1;
/**
* 思路利用二叉树的特点中序遍历是有序数组来解决 中序遍历+记录前指针
* 有两种思路储存val,count这里使用第二种
* 1map<val,count>
* 2)PriorityQueue<int[val,count]>()
* 递归法
* 速度击败100%,内存击败86.8%
* @param root
* @return
*/
public int[] findMode(TreeNode root) {
find(root);
if(list.isEmpty()){
return new int[]{pre.val};
}
if (count > list.get(0)[1]) {
list.clear();
list.add(new int[]{pre.val, count});
} else if (count == list.get(0)[1]) {
list.add(new int[]{pre.val, count});
}
int[] result = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
result[i] = list.get(i)[0];
}
return result;
}
/**
* 递归法
*
* @param node
*/
public void find(TreeNode node) {
if (node == null) {
return;
}
find(node.left);
if (pre != null) {
if (pre.val == node.val) {
count++;
} else {
if (list.isEmpty()) {
list.add(new int[]{pre.val, count});
} else {
if (count > list.get(0)[1]) {
list.clear();
list.add(new int[]{pre.val, count});
} else if (count == list.get(0)[1]) {
list.add(new int[]{pre.val, count});
}
}
count = 1;
}
}
pre = node;
find(node.right);
}
int base, count1, maxCount;
List<Integer> answer = new ArrayList<Integer>();
/**
* 思路利用二叉树的特点中序遍历是有序数组来解决 中序遍历+记录前指针
* 有两种思路储存val,count这里使用第二种
* 1map<val,count>
* 2)PriorityQueue<int[val,count]>()
* 迭代法:Morris遍历
* 速度击败100%,内存击败86.8%
* @param root
* @return
*/
public int[] findMode1(TreeNode root) {
TreeNode cur = root, pre = null;
while (cur != null) {
if (cur.left == null) {
update(cur.val);
cur = cur.right;
continue;
}
pre = cur.left;
while (pre.right != null && pre.right != cur) {
pre = pre.right;
}
if (pre.right == null) {
pre.right = cur;
cur = cur.left;
} else {
pre.right = null;
update(cur.val);
cur = cur.right;
}
}
int[] mode = new int[answer.size()];
for (int i = 0; i < answer.size(); ++i) {
mode[i] = answer.get(i);
}
return mode;
}
public void update(int x) {
if (x == base) {
++count1;
} else {
count1 = 1;
base = x;
}
//这里效率有点低,因为每次count1+1之后都得放进去之类的操作可以采用递归法上述思路进行更新,好处是出来之后不需要再做判断
if (count1 == maxCount) {
answer.add(base);
}
if (count1 > maxCount) {
maxCount = count1;
answer.clear();
answer.add(base);
}
}
/**
* 思路利用二叉树的特点中序遍历是有序数组来解决 中序遍历+记录前指针
* 有两种思路储存val,count这里使用第二种
* 1map<val,count>
* 2)PriorityQueue<int[val,count]>()
* 自己迭代法:
* 速度击败29.45%,内存击败76.39%
* @param root
* @return
*/
public int[] findMode2(TreeNode root) {
ArrayList<Integer> list = new ArrayList<>();
int count=1;
int maxCount=count;
Stack<TreeNode> stack = new Stack<>();
TreeNode pre=null;
while (!stack.isEmpty()||root!=null){
if(root!=null){
stack.push(root);
root=root.left;
}else {
root=stack.pop();
if (pre != null) {
if (pre.val == root.val) {
count++;
} else {
if (list.isEmpty()) {
list.add(pre.val);
maxCount=count;
} else {
if (count > maxCount) {
list.clear();
list.add(pre.val);
maxCount=count;
} else if (count == maxCount) {
list.add(pre.val);
}
}
count = 1;
}
}
pre = root;
root=root.right;
}
}
if(list.isEmpty()){
return new int[]{pre.val};
}
if (count > maxCount) {
list.clear();
list.add(pre.val);
} else if (count == maxCount) {
list.add(pre.val);
}
int[] result = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
result[i] = list.get(i);
}
return result;
}
}

View File

@ -0,0 +1,235 @@
package com.markilue.leecode.tree;
import org.junit.Test;
import java.util.Stack;
/**
* @BelongsProject: Leecode
* @BelongsPackage: com.markilue.leecode.tree
* @Author: dingjiawen
* @CreateTime: 2022-09-27 09:21
* @Description: TODO Leecode530题 二叉搜索树的最小绝对差
* 给你一个二叉搜索树的根节点 root 返回 树中任意两不同节点值之间的最小差值
* 差值是一个正数其数值等于两值之差的绝对值
* @Version: 1.0
*/
public class GetMinimumDifference {
@Test
public void test() {
TreeNode root = new TreeNode(4);
TreeNode TreeNode2 = new TreeNode(2);
TreeNode TreeNode3 = new TreeNode(6);
TreeNode TreeNode4 = new TreeNode(1);
TreeNode TreeNode5 = new TreeNode(3);
// TreeNode TreeNode6 = new TreeNode(15);
// TreeNode TreeNode7 = new TreeNode(7);
root.setRight(TreeNode3);
root.setLeft(TreeNode2);
TreeNode2.setLeft(TreeNode4);
TreeNode2.setRight(TreeNode5);
// TreeNode3.setRight(TreeNode7);
// TreeNode3.setLeft(TreeNode6);
System.out.println(getMinimumDifference(root));
}
@Test
public void test1() {
TreeNode root = new TreeNode(1);
// TreeNode TreeNode2 = new TreeNode(2);
TreeNode TreeNode3 = new TreeNode(3);
// TreeNode TreeNode4 = new TreeNode(1);
// TreeNode TreeNode5 = new TreeNode(3);
TreeNode TreeNode6 = new TreeNode(2);
// TreeNode TreeNode7 = new TreeNode(7);
root.setRight(TreeNode3);
// root.setLeft(TreeNode2);
// TreeNode2.setLeft(TreeNode4);
// TreeNode2.setRight(TreeNode5);
// TreeNode3.setRight(TreeNode7);
TreeNode3.setLeft(TreeNode6);
System.out.println(getMinimumDifference1(root));
}
int result = Integer.MAX_VALUE;
/**
* 思路某个节点的最小差值一定出现在该节点的左节点的最右节点或者右节点的最左节点两个之一
* 递归法:
* 速度击败100%内存击败45.7%
*
* @param root
* @return
*/
public int getMinimumDifference(TreeNode root) {
if (root == null || (root.left == null && root.right == null)) {
return result;
}
if (result == 1) {
return result;
}
//寻找左节点的最右节点
TreeNode node = root.left;
int left = Integer.MAX_VALUE;
if (node != null) {
while (node.right != null) {
node = node.right;
}
left = root.val - node.val;
}
//寻找左节点的最右节点
TreeNode node1 = root.right;
int right = Integer.MAX_VALUE;
if (node1 != null) {
while (node1 != null && node1.left != null) {
node1 = node1.left;
}
right = node1.val - root.val;
}
int flag = left < right ? left : right;
result = result < flag ? result : flag;
getMinimumDifference(root.left);
getMinimumDifference(root.right);
return result;
}
/**
* 思路某个节点的最小差值一定出现在该节点的左节点的最右节点或者右节点的最左节点两个之一
* 迭代法:
* 速度击败18.64%内存击败98.39%
*
* @param root
* @return
*/
public int getMinimumDifference1(TreeNode root) {
if (root == null || (root.left == null && root.right == null)) {
return 0;
}
int result = Integer.MAX_VALUE;
Stack<TreeNode> treeNodes = new Stack<>();
while (!treeNodes.isEmpty() || root != null) {
if (result == 1) {
break;
}
if (root != null) {
treeNodes.push(root);
root = root.left;
} else {
root = treeNodes.pop();
//添加找最小差节点逻辑:
//寻找左节点的最右节点
TreeNode node = root.left;
int left = Integer.MAX_VALUE;
if (node != null) {
while (node.right != null) {
node = node.right;
}
left = root.val - node.val;
}
//寻找左节点的最右节点
TreeNode node1 = root.right;
int right = Integer.MAX_VALUE;
if (node1 != null) {
while (node1 != null && node1.left != null) {
node1 = node1.left;
}
right = node1.val - root.val;
}
int flag = left < right ? left : right;
result = result < flag ? result : flag;
//右移
root = root.right;
}
}
return result;
}
/**
* 思路二叉搜索树的中序遍历就是一个有序数组只需要记录前一个节点用当前节点减去现在节点即可
* 递归法:
* 速度击败18.64%内存击败98.39%
*
* @param root
* @return
*/
TreeNode pre = null;
int ans = Integer.MAX_VALUE;
public int getMinimumDifference2(TreeNode root) {
get(root);
return ans;
}
public void get(TreeNode root) {
if (root == null) {
return;
}
//
get(root.left);
//
if (pre != null) {
ans = Math.min(root.val - pre.val, ans);
}
//记录当前
pre=root;
//
get(root.right);
}
/**
* 代码随想录迭代法:
* 速度超过18.64%,内存超过49.37%
* @param root
* @return
*/
public int getMinimumDifference3(TreeNode root) {
if (root == null || (root.left == null && root.right == null)) {
return 0;
}
int result = Integer.MAX_VALUE;
TreeNode pre=null;
Stack<TreeNode> treeNodes = new Stack<>();
while (!treeNodes.isEmpty() || root != null) {
if (result == 1) {
break;
}
if (root != null) {
treeNodes.push(root);
root = root.left;
} else {
root = treeNodes.pop();
//添加找最小差节点逻辑:
if(pre!=null){
result=Math.min(result,root.val-pre.val);
}
//记录前指针
pre=root;
//右移
root = root.right;
}
}
return result;
}
}