【leetcode】1305. 两棵二叉搜索树中的所有元素

1305. 两棵二叉搜索树中的所有元素

题目:给你 root1root2 这两棵二叉搜索树。请你返回一个列表,其中包含 两棵树 中的所有整数并按 升序 排序。

示例1:

在这里插入图片描述

输入:root1 = [2,1,4], root2 = [1,0,3]
输出:[0,1,1,2,3,4]
示例2:
输入:root1 = [0,-10,10], root2 = [5,1,7,0,2]
输出:[-10,0,0,1,2,5,7,10]
示例3:
输入:root1 = [], root2 = [5,1,7,0,2]
输出:[0,1,2,5,7]
示例4:
输入:root1 = [0,-10,10], root2 = []
输出:[-10,0,10]
示例5:

在这里插入图片描述

输入:root1 = [0,-10,10], root2 = []
输出:[-10,0,10]
提示:
每棵树最多有 5000 个节点。
每个节点的值在 [-10^5, 10^5] 之间。
解题思路1(已实现):

由于两棵都是二叉搜索树,那么我们可以先把两颗二叉搜索树的结点先按照先序遍历的方法,将遍历的结果逐个放到辅助数组中,得到两个先序排列的数组,然后将两个数组进行一次简单的归并排序便可得到结果。

解题步骤:
  1. 通过StackRoot来存放父节点,通过链表num来存放已排序的子节点;
  2. 循环判断的节点root是否为空,或者判断StackRoot是否为空;
    • root不为空,则说明未找到欲进行遍历的子节点,跳转到3
    • 若是StackRoot不为空,则说明还有结点未被访问,跳转到4
    • 若都不符合则跳转到5
  3. 若是root不为空,则将当前的root节点压进StackRoot,并继续查找root左子树,这步的目的是为了找到先序遍历的节点;
  4. 若是StackRoot不为空,则StackRoot.pop(),并且弹出的节点便是要查找的叶子节点,于是我们将该节点放入num中,并继续查找其右子树
  5. 循环判断两个num是否为空,若都不为空则跳转到7,否则跳转到6
  6. 判断两个num的第一个元素的大小,将较小的放入结果集result中,并移除较小的元素,若是num1先为空,则将num2剩余的元素依次放入结果集result中,反之将num1的放入结果集;
  7. 运行结束,返回结果。
分析思路1的时间复杂度和空间复杂度:
  • 遍历了两棵二叉搜索树,时间复杂度为O(n+m),并且最后还要进行遍历两次num中的数组,则时间复杂度为O(2n+2m);,即O(n+m)
  • 由于用num分别存放了root的所有节点,所以空间复杂度为O(n+m);
代码:
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> getAllElements(TreeNode root1, TreeNode root2) {
        //链表,存放已搜索到的节点
        LinkedList<Integer> num1 = new LinkedList<>();  
		LinkedList<Integer> num2 = new LinkedList<>();
        //栈,存放未被访问的结点
		ArrayDeque<TreeNode> StackRoot1 = new ArrayDeque<>(); 
		ArrayDeque<TreeNode> StackRoot2 = new ArrayDeque<>();
        //先序遍历二叉搜索树
		while (root1 != null || !StackRoot1.isEmpty()) {
			if (root1 != null) {
				StackRoot1.push(root1);
				root1 = root1.left;
			} else {
				root1 = StackRoot1.pop();
				num1.add(root1.val);
				root1 = root1.right;
			}
		}
		while (root2 != null || !StackRoot2.isEmpty()) {
			if (root2 != null) {
				StackRoot2.push(root2);
				root2 = root2.left;
			} else {
				root2 = StackRoot2.pop();
				num2.add(root2.val);
				root2 = root2.right;
			}
		}
        //存放结果集
		List<Integer> result = new ArrayList();
                //将两个有序链表进行一趟归并排序
		while (num1.size() != 0 || num2.size() != 0) {
            //只要两个链表都不为空,则进行比较
			if (num1.size() != 0 && num2.size() != 0) {
				if (num1.getFirst() <= num2.getFirst()){
					result.add(num1.removeFirst());
				}
				else{
					result.add(num2.removeFirst());
				}
			}
            //只要有任意一个链表为空,则将另一个链表依次插入结果集
			if (num1.size() != 0 && num2.size() == 0) {
				result.add(num1.removeFirst());
			} 
			if((num1.size() == 0 && num2.size() != 0)){
				result.add(num2.removeFirst());
			}

		}
		return result;
    }
}
提交记录
48 / 48 个通过测试用例
执行用时:26 ms
解题思路2(待实现):

在先序遍历的的时候,每次找到一个子节点便进行比较,将小的结果放入返回的数组,并继续先序遍历小的结果,由于是先序遍历,那么每次比较的元素都将是两棵树中最小子节点,直至两棵树遍历结束便可得到结果。

分析思路2的时间复杂度和空间复杂度:
  • 由于只把两棵二叉搜索树遍历一遍,时间复杂度为O(n+m);
  • 该过程只有一个存放结果集的数组result,所以空间复杂度为O(n+m);
总结:

第一次写关于树的题,虽然是简单的数据结构的题目,但是之前从未在Java中进行过树的操作,导致有很多地方不熟悉,而且在使用集合的时候也不熟练,之后要多多加练习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值