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

前言

天生我才必有用,千金散去还复来。——李白《将进酒》


一、题:两棵二叉搜索树中的所有元素

给你 root1root2 这两棵二叉搜索树。请你返回一个列表,其中包含 两棵树 中的所有整数并按 升序 排序。.
示例 1:
<力扣刷题>1305. 两棵二叉搜索树中的所有元素_第1张图片

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

示例 2:
<力扣刷题>1305. 两棵二叉搜索树中的所有元素_第2张图片

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

二、方法

二叉搜索树的定义:
二叉查找树(Binary Search Tree)(又:二叉搜索树,二叉排序树) 它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。二叉搜索树作为一种经典的数据结构,它既有链表的快速插入与删除操作的特点,又有数组快速查找的优势;所以应用十分广泛,例如在文件系统和数据库系统一般会采用这种数据结构进行高效率的排序与检索操作。

  • 当前节点的左子树中的数均小于当前节点的数;
  • 当前节点的右子树中的数均大于当前节点的数;
  • 所有左子树和右子树自身也是二叉搜索树。
    <力扣刷题>1305. 两棵二叉搜索树中的所有元素_第3张图片
  1. 可以用中序遍历访问二叉搜索树,即按照访问左子树——根节点——右子树的方式遍历这棵树,而在访问左子树或者右子树的时候也按照同样的方式遍历,直到遍历完整棵树。遍历结束后,就得到了一个有序数组。
  2. 由于整个遍历过程具有递归的性质,我们可以直接用递归函数来模拟这一过程。
  3. 中序遍历这两棵二叉搜索树,可以得到两个有序数组。
  4. 然后可以使用双指针方法来合并这两个有序数组,这一方法将两个数组看作两个队列,每次从队列头部取出比较小的数字放到结果中(头部相同时可任取一个)。
/**
 * 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().
 */

#define MAX_NODE_SIZE 5001

//递归:树
void inorder(struct TreeNode *node, int *res, int *pos) {
    if (node != NULL) {		//如果结点不为空
		//中序遍历:左->根->右
        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类型的指针变量num1,num2
    //并申请 MAX_SIZE*sizeof(int) 个字节(即4 * MAX_SIZE 个字节)的存储空间。
    int *nums1 = (int *)malloc(sizeof(int) * MAX_NODE_SIZE);
    int *nums2 = (int *)malloc(sizeof(int) * MAX_NODE_SIZE);
    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;
}

C语言函数:memcpy()

  • 头文件: #include
  • memcpy() 用来复制内存,其原型为:void * memcpy ( void * dest, const void * src, size_t num );
  • memcpy() 会复制 src 所指的内存内容的前 num 个字节到 dest 所指的内存地址上。
  • memcpy() 并不关心被复制的数据类型,只是逐字节地进行复制,这给函数的使用带来了很大的灵活性,可以面向任何数据类型进行复制。
  • 需要注意的是:
    • dest 指针要分配足够的空间,也即大于等于 num 字节的空间。如果没有分配空间,会出现断错误。
    • destsrc 所指的内存空间不能重叠(如果发生了重叠,使用 memmove() 会更加安全)。
  • 与 strcpy() 不同的是,memcpy() 会完整的复制 num 个字节,不会因为遇到“\0”而结束。
    • 【返回值】返回指向 dest 的指针。注意返回的指针类型是 void,使用时一般要进行强制类型转换。

你可能感兴趣的:(算法刷题,leetcode,数据结构)