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

106 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情

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

一、题目描述:

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

示例 1:

img

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

img

输入:root1 = [1,null,8], root2 = [8,1] 输出:[1,1,8,8]

提示:

每棵树的节点数在 [0, 5000] 范围内 -10^5 <= Node.val <= 10^5

来源:力扣(LeetCode) 链接:leetcode.cn/problems/al… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、思路分析:

  1. 这道题考察了什么思想?你的思路是什么?

    我们先了解一遍什么是二叉搜索树,每个节点的左子树所有节点都比该节点的值要小,每个节点的右子树所有节点都比该节点的值要大。

    我们可以对两棵二叉搜索树进行中序遍历,然后得到俩有序数组,然后合并即可,每次比较数组首部的大小即可。

  2. 做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?

    不是一次通过的,在编写代码的时候,总是遇到一些逻辑问题。

  3. 有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?

image.png

 class Solution {
     /* 中序遍历得到有序数组 */
     void inorder(TreeNode* root, vector<int> &res) {
         if(root == NULL) return;
         inorder(root->left, res);
         res.push_back(root->val);
         inorder(root->right, res);
     }
 ​
 public:
     /* 正向双指针 */
     vector<int> merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
         /* 定义两个指针 主要就是利用两个数组的有序性 那个前面的元素小就把它放入新开辟的数组中 */
         int p1 = 0, p2 = 0;
         /* 新定义一个数组用来储存排序后的元素 */
         vector<int> sort(m+n);
         /* 记录当前要存储到sort中的数据 */
         int cur = 0;
         int Index = 0;
         while(p1 < m || p2 < n) {
             /* p1 == m 说明nums1已经遍历完了后面只需要把nums2数据放入sort即可 */
             if(p1 == m) cur = nums2[p2++];
             else if(p2 == n) cur = nums1[p1++];
             else if(nums1[p1] < nums2[p2]) cur = nums1[p1++];
             else cur = nums2[p2++];
 ​
             sort[Index++] = cur;
         }
         return sort;
     }
     /* 暴力排序 */
     vector<int> merge1(vector<int>& nums1, int m, vector<int>& nums2, int n) {
         vector<int> result(nums1.begin(), nums1.end());
         for (int i = 0; i != n; ++i)
             result.push_back(nums2[i]) ;
         sort(result.begin(), result.end());
         return result;
     }
     /* 逆向双指针 */
     vector<int> merge2(vector<int>& nums1, int m, vector<int>& nums2, int n) {
         /* 定义双指针 */
         int p1 = m - 1, p2 = n - 1;
         /* 定义尾指针 */
         int tail = m + n - 1;
         /* 扩展数组大小 */
         nums1.resize(m + n);
         while(p1 >= 0 || p2 >= 0) {
             if(p1 == -1) nums1[tail--] = nums2[p2--];
             else if (p2 == -1) nums1[tail--] = nums1[p1--];
             else if (nums1[p1] > nums2[p2]) nums1[tail--] = nums1[p1--];
             else nums1[tail--] = nums2[p2--];
         }
         return nums1;      
     }
 ​
     vector<int> getAllElements(TreeNode *root1, TreeNode *root2) {
         vector<int> nums1, nums2;
         inorder(root1, nums1);
         inorder(root2, nums2);
         return merge2(nums1,nums1.size(),nums2,nums2.size());
     }
 };

作者:Nehzil 链接:leetcode.cn/problems/al… 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

三、AC 代码:

 /**
  * Definition for a binary tree node.
  * struct TreeNode {
  *     int val;
  *     struct TreeNode *left;
  *     struct TreeNode *right;
  * };
  */
 ​
 /**
  * Note: The returned array must be malloced, assume caller calls free().
  */
 ​
 void inorder(struct TreeNode *node, int *res, int *pos) {
     if (node) {
         inorder(node->left, res, pos);
         res[(*pos)++] = node->val;
         inorder(node->right, res, pos);
     }
 }
 ​
 int* getAllElements(struct TreeNode* root1, struct TreeNode* root2, int* returnSize) {
     int *nums1 = (int *)malloc(sizeof(int) * (5000+1));
     int *nums2 = (int *)malloc(sizeof(int) * (5000+1));
     int pos1 = 0, pos2 = 0;
     inorder(root1, nums1, &pos1);
     inorder(root2, nums2, &pos2);
 ​
     int *merged = (int *)malloc(sizeof(int) * (pos1 + pos2));
     int p1 = 0, p2 = 0;
     int pos = 0;
     while (true) {
         if (p1 == pos1) {
             memcpy(merged + pos, nums2 + p2, sizeof(int) * (pos2 - p2));
             break;
         }
         if (p2 == pos2) {
             memcpy(merged + pos, nums1 + p1, sizeof(int) * (pos1 - p1));
             break;
         }
         if (nums1[p1] < nums2[p2]) {
             merged[pos++] = nums1[p1++];
         } else {
             merged[pos++] = nums2[p2++];
         }
     }
     *returnSize = pos1 + pos2;
     return merged;
 }

四、总结:

题目链接:1305. 两棵二叉搜索树中的所有元素

本道题目的难点在于如何将二叉搜索树转换为有序数组,然后将两个有序数组合并。将二叉搜索树转换为有序数组可以采用中序遍历等等,而将两个有序数组合并此处可以使用双指针、逆向双指针合并等等方法,关键在于灵活运用,需要掌握各种方法,路漫漫其修远兮!