当前位置:   article > 正文

算法打卡day20|二叉树篇09|Leetcode 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

算法打卡day20|二叉树篇09|Leetcode 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

   算法题

Leetcode  669. 修剪二叉搜索树

题目链接:669. 修剪二叉搜索树

大佬视频讲解:修剪二叉搜索树视频讲解

个人思路

把这道题想复杂了,还想着如何去重构树

解法
递归法

依旧递归三步走

1.确定递归函数的参数以及返回值

这题递归需要返回值,因为是要遍历整棵树,做修改更方便,可以通过递归函数的返回值来移除节点

2.确定终止条件

修剪的操作并不是在终止条件上进行的,所以就是遇到空节点返回就可以了。

3.确定单层递归的逻辑

如果root(当前节点)的元素小于low的数值,那么应该递归右子树,并返回右子树符合条件的头结点。

如果root(当前节点)的元素大于high的,那么应该递归左子树,并返回左子树符合条件的头结点

如图:修剪区间[1,3] 将,0小于low,将0的右子树,返回给3节点的左子树。

  1. class Solution {
  2. public TreeNode trimBST(TreeNode root, int low, int high) {
  3. if(root==null) return null;//终止条件
  4. if(root.val<low){
  5. //该节点小于修剪范围最小值,但其右节点可能在范围内,因此返回右节点的修剪树
  6. return trimBST(root.right,low,high);
  7. }
  8. if(root.val>high){
  9. return trimBST(root.left,low,high);
  10. }
  11. root.left=trimBST(root.left,low,high);
  12. root.right=trimBST(root.right,low,high);
  13. return root;
  14. }
  15. }

时间复杂度:O(n);(遍历整棵树)

空间复杂度:O(n);(在最坏的情况下,当树是线性链表时(高度接近n),空间复杂度接近O(n))

迭代法

因为二叉搜索树的有序性,不需要使用栈模拟递归的过程。

在剪枝的时候,可以分为三步:

  1. 将root移动到[L, R] 范围内,注意是左闭右闭区间
  2. 剪枝左子树
  3. 剪枝右子树
  1. class Solution {
  2. public TreeNode trimBST(TreeNode root, int low, int high) {
  3. if(root == null)
  4. return null;
  5. while(root != null && (root.val < low || root.val > high)){
  6. if(root.val < low)
  7. root = root.right;
  8. else
  9. root = root.left;
  10. }
  11. TreeNode curr = root;
  12. //剪枝左子树
  13. while(curr != null){
  14. while(curr.left != null && curr.left.val < low){
  15. curr.left = curr.left.right;
  16. }
  17. curr = curr.left;
  18. }
  19. curr = root;//回溯
  20. //剪枝右子树
  21. while(curr != null){
  22. while(curr.right != null && curr.right.val > high){
  23. curr.right = curr.right.left;
  24. }
  25. curr = curr.right;
  26. }
  27. return root;
  28. }
  29. }

时间复杂度:O(n);(遍历整棵树)

空间复杂度:O(n);(最坏的情况下,算法的递归调用栈可能达到树的高度)


Leetcode 108.将有序数组转换为二叉搜索树

题目链接:108.将有序数组转换为二叉搜索树

大佬视频讲解:将有序数组转换为二叉搜索树视频讲解

个人思路

根据前面的题,构成二叉搜索树本质就是寻找分割点,分割点作为当前节点,然后递归左区间和右区间,分割点就是数组中间位置的节点。

解法
递归法

首先先定义区间为左闭右闭区间

递归三步走:

1.确定递归函数返回值及其参数

删除二叉树节点,增加二叉树节点,都是用递归函数的返回值来完成,这样是比较方便的。

构造二叉树,依然用递归函数的返回值来构造中节点的左右孩子

参数的话,首先是传入数组,然后就是左下标left和右下标right,在构造二叉树的时候尽量不要重新定义左右区间数组,而是用下标来操作原数组

2.确定递归终止条件

这里定义的是左闭右闭的区间,所以当区间 left > right的时候,就是空节点

3.确定单层递归的逻辑

首先取数组中间元素的位置,不难写出int mid = (left + right) / 2;这么写其实有一个问题,就是数值越界,例如left和right都是最大int,这么操作就越界了,所以可以这么写:int mid = left + ((right - left) >> 1);

取了中间位置,就开始以中间位置的元素构造节点

接着划分区间,root的左孩子接住下一层左区间的构造节点,右孩子接住下一层右区间构造的节点。

  1. class Solution {
  2. public TreeNode sortedArrayToBST(int[] nums) {
  3. TreeNode root = traversal(nums, 0, nums.length - 1);
  4. return root;
  5. }
  6. // 左闭右闭区间[left, right]
  7. private TreeNode traversal(int[] nums, int left, int right) {
  8. if (left > right) return null;
  9. //取中间值;如果数组长度为偶数,中间位置有两个元素,取靠左边的
  10. int mid = left + ((right - left) >> 1);//不会越界的写法
  11. TreeNode root = new TreeNode(nums[mid]);
  12. root.left = traversal(nums, left, mid - 1);
  13. root.right = traversal(nums, mid + 1, right);
  14. return root;
  15. }
  16. }

时间复杂度:O(n);(最差遍历一遍树)

空间复杂度:O(n);(递归树的高度h)

迭代法

通过三个队列来模拟,一个队列放遍历的节点,一个队列放左区间下标,一个队列放右区间下标。

  1. class Solution {
  2. public TreeNode sortedArrayToBST(int[] nums) {
  3. if (nums.length == 0) return null;
  4. //根节点初始化
  5. TreeNode root = new TreeNode(-1);
  6. Queue<TreeNode> nodeQueue = new LinkedList<>();
  7. Queue<Integer> leftQueue = new LinkedList<>();
  8. Queue<Integer> rightQueue = new LinkedList<>();
  9. // 根节点入队列
  10. nodeQueue.offer(root);
  11. // 0为左区间下标初始位置
  12. leftQueue.offer(0);
  13. // nums.size() - 1为右区间下标初始位置
  14. rightQueue.offer(nums.length - 1);
  15. while (!nodeQueue.isEmpty()) {
  16. TreeNode currNode = nodeQueue.poll();
  17. int left = leftQueue.poll();
  18. int right = rightQueue.poll();
  19. int mid = left + ((right - left) >> 1);
  20. // 将mid对应的元素给中间节点
  21. currNode.val = nums[mid];
  22. // 处理左区间
  23. if (left <= mid - 1) {
  24. currNode.left = new TreeNode(-1);
  25. nodeQueue.offer(currNode.left);
  26. leftQueue.offer(left);
  27. rightQueue.offer(mid - 1);
  28. }
  29. // 处理右区间
  30. if (right >= mid + 1) {
  31. currNode.right = new TreeNode(-1);
  32. nodeQueue.offer(currNode.right);
  33. leftQueue.offer(mid + 1);
  34. rightQueue.offer(right);
  35. }
  36. }
  37. return root;
  38. }
  39. }

时间复杂度:O(n);(遍历整棵树)

空间复杂度:O(n);(最坏的情况下,队列中可能需要存储整个输入数组的大小数量的节点)


Leetcode 538.把二叉搜索树转换为累加树

题目链接:538.把二叉搜索树转换为累加树

大佬视频讲解:把二叉搜索树转换为累加树视频讲解

个人思路

从题目所给例子树中,可以看出累加的顺序是右中左,所以反中序遍历这个二叉树,然后顺序累加就可以了。

解法
递归法

需要一个pre指针记录当前遍历节点cur的前一个节点,这样才方便做累加

递归三步走:

1.递归函数参数以及返回值

不需要递归函数的返回值做什么操作,要遍历整棵树。

同时需要定义一个全局变量pre,用来保存cur节点的前一个节点的数值,定义为int型就可以了。

2.确定终止条件

遇空就终止。

3.确定单层递归的逻辑

注意右中左来遍历二叉树, 中节点的处理逻辑就是让cur的数值加上前一个节点的数值

  1. class Solution {
  2. int sum;
  3. public TreeNode convertBST(TreeNode root) {
  4. sum = 0;
  5. convertBST1(root);
  6. return root;
  7. }
  8. // 按右中左顺序遍历
  9. public void convertBST1(TreeNode root) {
  10. if (root == null) {
  11. return;
  12. }
  13. convertBST1(root.right);
  14. sum += root.val;//累加
  15. root.val = sum;
  16. convertBST1(root.left);
  17. }
  18. }

时间复杂度:O(n);(遍历二叉树)

空间复杂度:O(n);(递归树的高度,如果是一个高度不平衡的树(例如链状结构)高度与n接近)

迭代法

中序模板题,用栈模仿递归,遍历二叉树

  1. class Solution {
  2. public TreeNode convertBST(TreeNode root) {
  3. int pre = 0;//遍历节点的前一个节点
  4. Stack<TreeNode> stack = new Stack<>();
  5. if(root == null) return null;
  6. stack.add(root);
  7. while(!stack.isEmpty()){
  8. TreeNode curr = stack.peek();
  9. //curr != null的状况,只负责存node到stack中
  10. if(curr != null){
  11. stack.pop();
  12. if(curr.left != null) //左
  13. stack.add(curr.left);
  14. stack.add(curr); //中
  15. stack.add(null);
  16. if(curr.right != null) //右
  17. stack.add(curr.right);
  18. }
  19. else{
  20. //curr == null的状况,只负责做单层逻辑
  21. stack.pop();
  22. TreeNode temp = stack.pop();
  23. temp.val += pre;
  24. pre = temp.val;
  25. }
  26. }
  27. return root;
  28. }
  29. }

时间复杂度:O(n);(遍历二叉树)

空间复杂度:O(n);(递归树的高度,如果是一个高度不平衡的树(例如链状结构)高度与n接近)


以上是个人的思考反思与总结,若只想根据系列题刷,参考卡哥的网址代码随想录算法官网

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/1021237
推荐阅读
相关标签
  

闽ICP备14008679号