力扣——面试题 04.09. 二叉搜索树序列

面试题 04.09. 二叉搜索树序列

从左向右遍历一个数组,通过不断将其中的元素插入树中可以逐步地生成一棵二叉搜索树。

给定一个由不同节点组成的二叉搜索树 root,输出所有可能生成此树的数组。

示例 1:

输入: root = [2,1,3]
输出: [[2,1,3],[2,3,1]]
解释: 数组 [2,1,3]、[2,3,1] 均可以通过从左向右遍历元素插入树中形成以下二叉搜索树
       2 
      / \ 
     1   3

示例 2:

输入: root = [4,1,null,null,3,2]
输出: [[4,1,3,2]]

提示:

  • 二叉搜索树中的节点数在 [0, 1000] 的范围内
  • 1 <= 节点值 <= 10^6
  • 用例保证符合要求的数组数量不超过 5000

C++代码

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */ 
class Solution {
public:
    vector<vector<int>> BSTSequences(TreeNode* root) {
        if (root == nullptr) {
            return {{}};
        }
        deque<TreeNode*> dq; // 双端队列可以两端插入和删除,便于处理回溯;queue只能在队列头部删除,队列尾部插入
        dq.push_back(root);
        dfs(dq);
        return res;
    }

    void dfs(deque<TreeNode*>& dq) {
        // 终止条件
        if (dq.empty()) { // 说明状态不会再扩展,path已经选择完了最后一个节点
            res.push_back(path);
            return; 
        }
        // 遍历选择条件
        for (unsigned int i = 0; i < dq.size(); ++i) {
            // 作出选择(修改全局变量)
            TreeNode* top = dq.front();
            dq.pop_front();
        
            path.push_back(top->val);

            if (top->left) {
                dq.push_back(top->left);
            }
            if (top->right) {
                dq.push_back(top->right);
            }

            // 递归
            dfs(dq);

            // 回溯 (恢复全局变量)
            if (top->left) {
                dq.pop_back();
            }
            if (top->right) {
                dq.pop_back();
            }

            dq.push_back(top); // 满足队列先进先出条件,不要使用push_front
            path.pop_back();

        }
    }

private:
    vector<int> path;
    vector<vector<int>> res;
};

参考

  • 力扣题解1——每一个节点都必须排在它的子孙结点前面
  • 力扣题解2——c++ 比较容易理解 DFS 回溯
  • 回溯、dfs、递归三者的关系
    • 回溯和DFS本质上是同一种思想,都是搜索算法中的一种,都是利用递归实现的。回溯算法通过试图在所有可能的结果中搜索,然后找到一个符合条件的结果。DFS算法也是利用递归实现的一种搜索算法,与回溯算法不同的是,DFS算法是一种无回溯的搜索算法,即一旦前进到某一步时不再回头。
    • 递归是一种程序设计或编程技术,在编写程序时,递归是一种求解问题的方法,它通过将问题分解为更小的子问题,直到子问题不再需要继续分解为止。回溯和DFS算法都是通过递归解决搜索问题的。
    • 因此,回溯、DFS和递归三者之间存在着密切的联系和相互依赖关系,可以说回溯和DFS算法都是利用递归实现的,而递归则是回溯和DFS算法的基础。
  • 递归和回溯的一般结构:
    在这里插入图片描述
  • 回溯算法模板:
void backtrack(参数) {
    if (终止条件) {
        存储结果;
        return;
    }
    for (选择:选择列表) {
        做出选择;
        backtrack(新参数);
        撤销选择;
    }
}
  • 常考的回溯算法题目:
    1. 八皇后问题
    2. 数独问题
    3. 括号生成
    4. 全排列问题
    5. 组合总和问题
    6. 单词搜索问题
    7. 子集问题
    8. 电话号码的字母组合问题
    9. 分割回文串问题
    10. N 皇后问题
  • deque和queue的区别:
    queue是一种先进先出(FIFO)的数据结构,只能在队列的尾部插入元素,在队列的头部删除元素。deque是双端队列,可以从队列的两端插入或删除元素。queue适用于需要按照先后顺序进行操作的场景,例如任务调度、消息传递等。deque适用于需要在队列的两端进行操作的场景,例如滑动窗口、游戏开发等。
  • deque常用的函数:
    1. push_front():在deque的前面添加元素
    2. push_back():在deque的后面添加元素(跟queue的push()功能一样)
    3. pop_front():删除deque的第一个元素 (跟queue的pop()功能一样)
    4. pop_back():删除deque的最后一个元素
    5. front():返回deque的第一个元素 (跟queue一样)
    6. back():返回deque的最后一个元素 (跟queue一样)
    7. size():返回deque中元素的数量 (跟queue一样)
    8. empty():检查deque是否为空 (跟queue一样)
    9. clear():删除deque中的所有元素
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值