C/C++每日一练(20230410) 二叉树专场(4)

简介: C/C++每日一练(20230410) 二叉树专场(4)

1. 二叉搜索树迭代器


实现一个二叉搜索树迭代器类BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器:


   BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应初始化为一个不存在于 BST 中的数字,且该数字小于 BST 中的任何元素。

   boolean hasNext() 如果向指针右侧遍历存在数字,则返回 true ;否则返回 false 。

   int next()将指针向右移动,然后返回指针处的数字。

注意,指针初始化为一个不存在于 BST 中的数字,所以对 next() 的首次调用将返回 BST 中的最小元素。


你可以假设 next() 调用总是有效的,也就是说,当调用 next() 时,BST 的中序遍历中至少存在一个下一个数字。

示例:

743f55b78d358ff4ba5fbb7d8088a0d9.png

输入
["BSTIterator", "next", "next", "hasNext", "next", "hasNext", "next", "hasNext", "next", "hasNext"]
[[[7, 3, 15, null, null, 9, 20]], [], [], [], [], [], [], [], [], []]
输出
[null, 3, 7, true, 9, true, 15, true, 20, false]
解释 
BSTIterator bSTIterator = new BSTIterator([7, 3, 15, null, null, 9, 20]); 
bSTIterator.next(); // 返回 3 
bSTIterator.next(); // 返回 7 
bSTIterator.hasNext(); // 返回 True 
bSTIterator.next(); // 返回 9 
bSTIterator.hasNext(); // 返回 True 
bSTIterator.next(); // 返回 15 
bSTIterator.hasNext(); // 返回 True 
bSTIterator.next(); // 返回 20 
bSTIterator.hasNext(); // 返回 False


提示:

   树中节点的数目在范围 [1, 10^5] 内

   0 <= Node.val <= 10^6

   最多调用 10^5 次 hasNext 和 next 操作


进阶:

   你可以设计一个满足下述条件的解决方案吗?next() 和 hasNext() 操作均摊时间复杂度为 O(1) ,并使用 O(h) 内存。其中 h 是树的高度。


出处:

https://edu.csdn.net/practice/24633337

代码:


#define null INT_MIN
#include <bits/stdc++.h>
using namespace std;
struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class BSTIterator
{
public:
    BSTIterator(TreeNode *root)
    {
        for (; root != nullptr; root = root->left)
        {
            sti_.push(root);
        }
    }
    /** @return the next smallest number */
    int next()
    {
        TreeNode *smallest = sti_.top();
        sti_.pop();
        int val = smallest->val;
        smallest = smallest->right;
        for (; smallest != nullptr; smallest = smallest->left)
        {
            sti_.push(smallest);
        }
        return val;
    }
    /** @return whether we have a next smallest number */
    bool hasNext()
    {
        return !sti_.empty();
    }
private:
    stack<TreeNode *> sti_;
};
/**
 * Your BSTIterator object will be instantiated and called as such:
 * BSTIterator* obj = new BSTIterator(root);
 * int param_1 = obj->next();
 * bool param_2 = obj->hasNext();
 */
TreeNode* buildTree(vector<int>& nums)
{
    if (nums.empty()) return nullptr;
  TreeNode *root = new TreeNode(nums.front());
    queue<TreeNode*> q;
    q.push(root);
    int i = 1;
    while(!q.empty() && i < nums.size())
    {
        TreeNode *cur = q.front();
        q.pop();
        if(i < nums.size() && nums[i] != null)
        {
            cur->left = new TreeNode(nums[i]);
            q.push(cur->left);
        }
        i++;
        if(i < nums.size() && nums[i] != null)
        {
            cur->right = new TreeNode(nums[i]);
            q.push(cur->right);
        }
        i++;
    }
    return root;
}
int main()
{
  vector<int> nums = {7, 3, 15, null, null, 9, 20};
  TreeNode *root = buildTree(nums);
  BSTIterator bSTIterator = BSTIterator(root); 
  cout << bSTIterator.next() << endl; // 返回 3 
  cout << bSTIterator.next() << endl; // 返回 7 
  cout << (bSTIterator.hasNext() ? "True" : "False") << endl; // 返回 True 
  cout << bSTIterator.next() << endl; // 返回 9 
  cout << (bSTIterator.hasNext() ? "True" : "False") << endl; // 返回 True 
  cout << bSTIterator.next() << endl; // 返回 15 
  cout << (bSTIterator.hasNext() ? "True" : "False") << endl; // 返回 True 
  cout << bSTIterator.next() << endl; // 返回 20 
  cout << (bSTIterator.hasNext() ? "True" : "False") << endl; // 返回 True 
    return 0;
}


输出:

3

7

True

9

True

15

True

20

False




2. 验证二叉搜索树


给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。


有效 二叉搜索树定义如下:


  • 节点的左子树只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

3d85b39145ecc61874276bcb7cfe6765.jpeg


输入:root = [2,1,3]

输出:true


示例 2:

输入:root = [5,1,4,null,null,3,6]

输出:false

解释:根节点的值是 5 ,但是右子节点的值是 4 。


提示:

  • 树中节点数目范围在[1, 10^4]
  • -2^31 <= Node.val <= 2^31 - 1

以下程序实现了这一功能,请你填补空白处内容:

```c++
#include <bits/stdc++.h>
using namespace std;
struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution
{
public:
    bool isValidBST(TreeNode *root)
    {
        stack<TreeNode *> stk;
        int prev = INT_MIN;
        bool first = true;
        while (!stk.empty() || root != nullptr)
        {
            if (root != nullptr)
            {
                stk.push(root);
                root = root->left;
            }
            else
            {
                root = stk.top();
                stk.pop();
                _______________________;
            }
        }
        return true;
    }
};
```


出处:

https://edu.csdn.net/practice/25116236

代码:

#define null INT_MIN
#include <bits/stdc++.h>
using namespace std;
struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution
{
public:
    bool isValidBST(TreeNode *root)
    {
        stack<TreeNode *> stk;
        int prev = INT_MIN;
        bool first = true;
        while (!stk.empty() || root != nullptr)
        {
            if (root != nullptr)
            {
                stk.push(root);
                root = root->left;
            }
            else
            {
                root = stk.top();
                stk.pop();
        if (!first && prev >= root->val)
        {
            return false;
        }
        first = false;
        prev = root->val;
        root = root->right;
            }
        }
        return true;
    }
};
TreeNode* buildTree(vector<int>& nums)
{
    if (nums.empty()) return nullptr;
  TreeNode *root = new TreeNode(nums.front());
    queue<TreeNode*> q;
    q.push(root);
    int i = 1;
    while(!q.empty() && i < nums.size())
    {
        TreeNode *cur = q.front();
        q.pop();
        if(i < nums.size() && nums[i] != null)
        {
            cur->left = new TreeNode(nums[i]);
            q.push(cur->left);
        }
        i++;
        if(i < nums.size() && nums[i] != null)
        {
            cur->right = new TreeNode(nums[i]);
            q.push(cur->right);
        }
        i++;
    }
    return root;
}
int main()
{
  Solution s;
  vector<int> nums = {2,1,3};
  TreeNode* root = buildTree(nums);
  cout << (s.isValidBST(root) ? "true" : "false") << endl;
  nums = {5,1,4,null,null,3,6};
  root = buildTree(nums);
  cout << (s.isValidBST(root) ? "true" : "false") << endl;
  return 0;
} 

输出:

true

false


3. 不同的二叉搜索树 II


给你一个整数 n ,请你生成并返回所有由 n 个节点组成且节点值从 1n 互不相同的不同 二叉搜索树 。可以按 任意顺序 返回答案。

示例 1:

afa8711beb3c6f3c54d039379f525fb7.jpeg



输入:n = 3

输出:[[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,null,2],[3,2,null,1]]


示例 2:

输入:n = 1

输出:[[1]]


提示:

  • 1 <= n <= 8

代码:

#include <stdio.h>
#include <stdlib.h>
struct TreeNode
{
  int val;
  struct TreeNode *left;
  struct TreeNode *right;
};
static struct TreeNode *dfs(int low, int high, int *count)
{
  int i, j, k;
  if (low > high)
  {
    *count = 0;
    return NULL;
  }
  else if (low == high)
  {
    struct TreeNode *node = malloc(sizeof(*node));
    node->val = low;
    node->left = NULL;
    node->right = NULL;
    *count = 1;
    return node;
  }
  else
  {
    *count = 0;
    int capacity = 5;
    struct TreeNode *roots = malloc(capacity * sizeof(struct TreeNode));
    for (i = low; i <= high; i++)
    {
      int left_cnt, right_cnt;
      struct TreeNode *left_subs = dfs(low, i - 1, &left_cnt);
      struct TreeNode *right_subs = dfs(i + 1, high, &right_cnt);
      if (left_cnt == 0)
        left_cnt = 1;
      if (right_cnt == 0)
        right_cnt = 1;
      if (*count + (left_cnt * right_cnt) >= capacity)
      {
        capacity *= 2;
        capacity += left_cnt * right_cnt;
        roots = realloc(roots, capacity * sizeof(struct TreeNode));
      }
      for (j = 0; j < left_cnt; j++)
      {
        for (k = 0; k < right_cnt; k++)
        {
          roots[*count].val = i;
          roots[*count].left = left_subs == NULL ? NULL : &left_subs[j];
          roots[*count].right = right_subs == NULL ? NULL : &right_subs[k];
          (*count)++;
        }
      }
    }
    return roots;
  }
}
static struct TreeNode **generateTrees(int n, int *returnSize)
{
  int i, count = 0;
  struct TreeNode *roots = dfs(1, n, &count);
  struct TreeNode **results = malloc(count * sizeof(struct TreeNode *));
  for (i = 0; i < count; i++)
  {
    results[i] = &roots[i];
  }
  *returnSize = count;
  return results;
}
static void dump(struct TreeNode *node)
{
  printf("%d ", node->val);
  if (node->left != NULL)
  {
    dump(node->left);
  }
  else
  {
    printf("# ");
  }
  if (node->right != NULL)
  {
    dump(node->right);
  }
  else
  {
    printf("# ");
  }
}
int main(int argc, char **argv)
{
  if (argc != 2)
  {
    fprintf(stderr, "Usage: ./test n\n");
    exit(-1);
  }
  int i, count = 0;
  struct TreeNode **results = generateTrees(atoi(argv[1]), &count);
  for (i = 0; i < count; i++)
  {
    dump(results[i]);
    printf("\n");
  }
  return 0;
}








目录
相关文章
二叉树进阶面试题(精华总结)【C++版本】
二叉树进阶面试题(精华总结)【C++版本】
128 1
|
存储 编译器 数据库
【C/C++ 数据结构 】线索二叉树全解析:从数学原理到C++实现
【C/C++ 数据结构 】线索二叉树全解析:从数学原理到C++实现
360 0
|
24天前
|
C++
基本二叉树与排序二叉树(C++源码)
本程序实现二叉树基本操作与二叉排序树应用。支持前序建树、四种遍历、求深度、叶子数、第K层节点数及查找功能;并实现二叉排序树的构建、中序输出与查找比较次数统计,分析不同插入顺序对树形态和查找效率的影响。
|
算法 C++ 开发者
【C/C++ 数据结构 】二叉树基本性质:对于任何一颗二叉树T,若其终端结点为n0 ,那么度数为2的结点数为n2。则n0=n2+1...
【C/C++ 数据结构 】二叉树基本性质:对于任何一颗二叉树T,若其终端结点为n0 ,那么度数为2的结点数为n2。则n0=n2+1...
299 0
|
9月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
202 12
|
9月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
174 10
|
9月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
293 3
|
存储 C++
【C++】二叉树进阶之二叉搜索树(下)
【C++】二叉树进阶之二叉搜索树(下)
84 4
|
Java 编译器 C++
【C++】二叉树进阶之二叉搜索树(上)
【C++】二叉树进阶之二叉搜索树(上)
83 3
|
算法 C++
【C++高阶】高效搜索的秘密:深入解析搜索二叉树
【C++高阶】高效搜索的秘密:深入解析搜索二叉树
99 2