持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
力扣1305. 两棵二叉搜索树中的所有元素
一、题目描述:
给你 root1 和 root2 这两棵二叉搜索树。请你返回一个列表,其中包含 两棵树 中的所有整数并按 升序 排序。
示例 1:
输入:root1 = [2,1,4], root2 = [1,0,3] 输出:[0,1,1,2,3,4] 示例 2:
输入:root1 = [1,null,8], root2 = [8,1] 输出:[1,1,8,8]
提示:
每棵树的节点数在 [0, 5000] 范围内 -10^5 <= Node.val <= 10^5
来源:力扣(LeetCode) 链接:leetcode.cn/problems/al… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、思路分析:
-
这道题考察了什么思想?你的思路是什么?
我们先了解一遍什么是二叉搜索树,每个节点的左子树所有节点都比该节点的值要小,每个节点的右子树所有节点都比该节点的值要大。
我们可以对两棵二叉搜索树进行中序遍历,然后得到俩有序数组,然后合并即可,每次比较数组首部的大小即可。
-
做题的时候是不是一次通过的,遇到了什么问题,需要注意什么细节?
不是一次通过的,在编写代码的时候,总是遇到一些逻辑问题。
-
有几种解法,哪种解法时间复杂度最低,哪种解法空间复杂度最低,最优解法是什么?其他人的题解是什么,谁的效率更好一些?用不同语言实现的话,哪个语言速度最快?
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. 两棵二叉搜索树中的所有元素
本道题目的难点在于如何将二叉搜索树转换为有序数组,然后将两个有序数组合并。将二叉搜索树转换为有序数组可以采用中序遍历等等,而将两个有序数组合并此处可以使用双指针、逆向双指针合并等等方法,关键在于灵活运用,需要掌握各种方法,路漫漫其修远兮!