971. 翻转二叉树以匹配先序遍历

Posted Debroon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了971. 翻转二叉树以匹配先序遍历相关的知识,希望对你有一定的参考价值。

971. 翻转二叉树以匹配先序遍历

 


题目

传送门:https://leetcode.cn/problems/flip-binary-tree-to-match-preorder-traversal/

 


算法设计:深度优先搜索

解题思路,对于一个结点:

  • 它翻转前可以匹配 voyage 序列,不用翻转
  • 若不匹配,就需要翻转左右子树,即遍历顺序从 [根、左、右] 变成 [根、右、左],若这样匹配 voyage 序列,则记录该结点的值。
  • 否则,代表这棵树无法匹配 voyage 序列,返回 [-1]
  • 题目要求最少翻转次数,因此不翻转的情况优先级更高,若不匹配再进行翻转。

匹不匹配需要用一个状态值来表示,DFS 方法的返回值可设置为 bool ,表示当前结点及翻转子树前后能否匹配 voyage 序列。

用拆解子问题公式分析:

  • 二叉树原问题 = 根节点 + 左右子树问题

  • 翻转二叉树是否匹配先序遍历 = 根节点匹配 && (根节点的左右子树匹配 || 翻转后,根节点的左右子树匹配)

class Solution 
    vector<int> res;       // 全局变量存结果
    int i = 0;             // 匹配voyage第 i 个元素
public:
    vector<int> flipMatchVoyage(TreeNode* root, vector<int>& v) 
        return dfs(root, v) ? res : vector<int>-1;          // 匹配voyage,返回翻转结点值,否则无解
    

    bool dfs(TreeNode* node, vector<int>& v) 
        if (!node) return true;                               // 空树 或 当前节点及左右子树匹配,不用翻转
        if (node->val != v[i]) return false;                  // 当前结点不匹配voyage
        
        ++ i;                                                 // 当前节点匹配,再判断左右子树是否匹配
        if (node->left && node->left->val != v[i])           // 左叶子存在 且 左叶子值与voyage不匹配,就翻转
            res.push_back(node->val);                         // 记录这次翻转的值
            return dfs(node->right, v) && dfs(node->left, v); // 翻转遍历(先右后左)
         else                                                // 左叶子不存在 或 左叶子值匹配,就不用翻转
        	return dfs(node->left, v) && dfs(node->right, v); // 遍历左右子树
    
;

以上是关于971. 翻转二叉树以匹配先序遍历的主要内容,如果未能解决你的问题,请参考以下文章

采用邻接表存储的图的深度优先遍历算法类似于二叉树的先序遍历,为啥是先序呢?

Python版算法专题--二叉树的深度优先遍历

讲透学烂二叉树:二叉树的遍历图解算法步骤及JS代码

二叉树的深度优先遍历逆推

求高手给个遍历算法

二叉树遍历