From f07804340e136e2d0f306fdf23aa67b2c2f7ae27 Mon Sep 17 00:00:00 2001 From: markilue <745518019@qq.com> Date: Tue, 27 Sep 2022 12:32:13 +0800 Subject: [PATCH] =?UTF-8?q?leecode=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/markilue/leecode/tree/FindMode.java | 254 ++++++++++++++++++ .../leecode/tree/GetMinimumDifference.java | 235 ++++++++++++++++ 2 files changed, 489 insertions(+) create mode 100644 Leecode/src/main/java/com/markilue/leecode/tree/FindMode.java create mode 100644 Leecode/src/main/java/com/markilue/leecode/tree/GetMinimumDifference.java diff --git a/Leecode/src/main/java/com/markilue/leecode/tree/FindMode.java b/Leecode/src/main/java/com/markilue/leecode/tree/FindMode.java new file mode 100644 index 0000000..714598b --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/tree/FindMode.java @@ -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(new Comparator() { +// +// @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 list = new ArrayList(); + TreeNode pre = null; + int count = 1; + + /** + * 思路:利用二叉树的特点中序遍历是有序数组来解决 :中序遍历+记录前指针: + * 有两种思路储存val,count:这里使用第二种 + * 1)map + * 2)PriorityQueue() + * 递归法 + * 速度击败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 answer = new ArrayList(); + /** + * 思路:利用二叉树的特点中序遍历是有序数组来解决 :中序遍历+记录前指针: + * 有两种思路储存val,count:这里使用第二种 + * 1)map + * 2)PriorityQueue() + * 迭代法: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:这里使用第二种 + * 1)map + * 2)PriorityQueue() + * 自己迭代法: + * 速度击败29.45%,内存击败76.39% + * @param root + * @return + */ + public int[] findMode2(TreeNode root) { + + ArrayList list = new ArrayList<>(); + + int count=1; + int maxCount=count; + Stack 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; + } + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/tree/GetMinimumDifference.java b/Leecode/src/main/java/com/markilue/leecode/tree/GetMinimumDifference.java new file mode 100644 index 0000000..eec3896 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/tree/GetMinimumDifference.java @@ -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 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 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; + } + +}