二叉树 + 递归 + 分治法 + BFS 总结 leetcode: 前序 中序 后序的的递归及非递归遍历;二叉树的最近公共祖先
二叉树递归相关题目的时间复杂度基本上都是O(n) = 一共有n个点 + 每个点的时间复杂度(1)
而二叉树分治法最坏的时间复杂度为O(n^2)
时间复杂度:T(n) = 2T(n/2) + O(1) = O(n)
Merge Sort, Quick Sort: T(n) = 2T(n/2) + O(n) = O(nlogn)
前序遍历:
解法一:递归,通常是设置一个全局变量来保存结果。
/** * 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<int> preorderTraversal(TreeNode* root) { vector<int> result; traverse(root, result); return result; } void traverse(TreeNode* root, vector<int>& res){ //递归终止条件 if(root == NULL) return; res.push_back(root->val); traverse(root->left, res); traverse(root->right, res); } };
解法二:Divide & Conquer
/** * 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<int> preorderTraversal(TreeNode* root) { vector<int> res; if(root == NULL) return res; //divide vector<int> left = preorderTraversal(root->left); vector<int> right = preorderTraversal(root->right); //conquer res.push_back(root->val); for(auto i : left) res.push_back(i); for(auto i : right) res.push_back(i); return res; } };
解法三:非递归版本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<int> preorderTraversal(TreeNode* root) { vector<int> res; if(root == NULL) return res; stack<TreeNode*> st; st.push(root); while(!st.empty()){ TreeNode* node = st.top(); st.pop(); res.push_back(node->val); if(node->right) st.push(node->right); if(node->left) st.push(node->left); } return res; } };
中序遍历:
一. 递归
/** * 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<int> preorderTraversal(TreeNode* root) { vector<int> res; if(root == NULL) return res; stack<TreeNode*> st; st.push(root); while(!st.empty()){ TreeNode* node = st.top(); st.pop(); res.push_back(node->val); if(node->right) st.push(node->right); if(node->left) st.push(node->left); } return res; } };
二. Divide and Quaqer
/** * 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<int> inorderTraversal(TreeNode* root) { vector<int> res; if(root == NULL) return res; vector<int> left = inorderTraversal(root->left); vector<int> right = inorderTraversal(root->right); for(int i : left) res.push_back(i); res.push_back(root->val); for(int i: right) res.push_back(i); return res; } };
三. 非递归,用栈来实现。
栈或者当前结点不为空时:
1)把当前结点压入栈中,然后继续压入它的左结点,直到左结点为空;
2)将栈顶元素的值保存在res中,并弹出;
3)转到右结点。
/** * 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<int> inorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode* > st; TreeNode* cur = root; while(cur || !st.empty()){ while(cur){ st.push(cur); cur = cur->left; } cur = st.top(); st.pop(); res.push_back(cur->val); cur = cur->right; } return res; } };
后序遍历:
一.
/** * 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<int> postorderTraversal(TreeNode* root) { vector<int> res; traverse(root, res); return res; } void traverse(TreeNode* root, vector<int>& res){ if(root == NULL) return; traverse(root->left, res); traverse(root->right, res); res.push_back(root->val); } };
二.
/** * 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<int> postorderTraversal(TreeNode* root) { vector<int> res; if(root == NULL) return res; vector<int> left = postorderTraversal(root->left); vector<int> right = postorderTraversal(root->right); for(int i: left) res.push_back(i); for(int i: right) res.push_back(i); res.push_back(root->val); return res; } };
三.
/** * 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<int> postorderTraversal(TreeNode* root) { vector<int> res; stack<TreeNode* > st; if(root == NULL) return res; st.push(root); while(!st.empty()){ TreeNode* tmp = st.top(); st.pop(); res.insert(res.begin(), tmp->val); //在前端插入 if(tmp->left) st.push(tmp->left); if(tmp->right) st.push(tmp->right); } return res; } };
一.
/** * 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 { private: int dep_max; //全局变量 public: int maxDepth(TreeNode* root) { dep_max = 0; helper(root, 1); //1为当前根结点 return dep_max; } void helper(TreeNode* root, int depth){ if(root==NULL) return; dep_max = max(dep_max, depth); helper(root->left, depth+1); helper(root->right, depth+1); } };
二.
/** * 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: int maxDepth(TreeNode* root) { if(root==NULL) return 0; //左右子树的深度 int left = maxDepth(root->left); int right = maxDepth(root->right); return max(left, right)+1; } };
平衡二叉树:左右子树高度相差不超过1
/** * 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: bool isBalanced(TreeNode* root) { if(root==NULL) return true; if(abs(getDepth(root->left) - getDepth(root->right)) > 1) return false; return isBalanced(root->left) && isBalanced(root->right); } int getDepth(TreeNode* root){ if(!root) return 0; return max(getDepth(root->left), getDepth(root->right)) + 1; } };
上面的方法使得每个结点都会被上面的点计算深度时访问一次,优化一下:若发现某个结点的子树不平衡,则不计算它的深度,直接返回-1
/** * 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: bool isBalanced(TreeNode* root) { if(depth(root) == -1) return false; return true; } int depth(TreeNode* root){ if(!root) return 0; int left = depth(root->left); if(left==-1) return -1; int right = depth(root->right); if(right == -1) return -1; int dif = abs(left - right); if(dif>1) return -1; else return max(left, right)+1; } };
二叉搜索树的性质是:左子树的值 < 根节点 < 右子树的值
/** * 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: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(p->val > q->val) swap(p,q); // ensure p < q while(root){ if(root->val < p->val) root = root->right; else if(root->val > q->val) root = root->left; else return root; } return NULL; } };
已知A和B的父亲结点:
思路:把A和A的父结点保存在set中,若在B及B的父结点中找到一个和set中相同的结点,就返回这个公共祖先。
/** * Definition of ParentTreeNode: * class ParentTreeNode { * public: * int val; * ParentTreeNode *parent, *left, *right; * } */ class Solution { public: /* * @param root: The root of the tree * @param A: node in the tree * @param B: node in the tree * @return: The lowest common ancestor of A and B */ ParentTreeNode * lowestCommonAncestorII(ParentTreeNode * root, ParentTreeNode * A, ParentTreeNode * B) { // write your code here if(root == NULL) return NULL; unordered_set<ParentTreeNode*> s; //保存A向上的路径 while(A!=NULL){ s.insert(A); A = A->parent; } while(B){ if(s.find(B) == s.end()) //s中找不到相同的结点 B = B->parent; else return B; } } };
未知p,q的父亲结点:
分治法:
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ //若找到了LCA,就返回LCA,即 p和q出现在一左一右,返回它的根结点 //若只找到n1, 就返回n1 //若只找到了n2, 就返回n2 //若都不存在,返回NULL class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(root == NULL) return NULL; if(root == p || root == q) return root; //divide TreeNode* left = lowestCommonAncestor(root->left, p, q); TreeNode* right = lowestCommonAncestor(root->right, p, q); //Conquer if(left != NULL && right != NULL) return root; if(left != NULL) return left; if(right != NULL) return right; return NULL; } };
递归:
/** * 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: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { if(root == NULL || root == p || root == q){ return root; } TreeNode* left = lowestCommonAncestor(root->left, p, q); TreeNode* right = lowestCommonAncestor(root->right, p, q); if(left && right) return root; if(left && right == NULL) return left; if(right && left == NULL) return right; return NULL; } };
从任一结点到任一结点路径的最大值:
参考链接:https://www.geeksforgeeks.org/find-maximum-path-sum-in-a-binary-tree/
/** * Definition of TreeNode: * class TreeNode { * public: * int val; * TreeNode *left, *right; * TreeNode(int val) { * this->val = val; * this->left = this->right = NULL; * } * } */ //一颗二叉树,求从根结点到叶子结点的路径的最大值;求从根结点到任一结点的路径的最大值 class Solution { public: /** * @param root: The root of binary tree. * @return: An integer */ int maxPathSum(TreeNode * root) { // write your code here if (root == NULL) return 0; int left = maxPathSum(root->left); int right = maxPathSum(root->right); //root -> leaf //return max(left, right) + root->val; //root-> anynode return max(0, max(left, right)) + root->val; } };
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ //any to any node: 最长路径的位置:完全在左边;完全在右边;跨过根结点 //O(n) class Solution { public: int findMax(TreeNode* root, int &res){ if(root == NULL) return 0; int l = findMax(root->left, res); int r = findMax(root->right, res); int max_single = max(max(l, r)+root->val, root->val); int max_round = max(max_single, l+r+root->val); res = max(res, max_round); //store the maximum result return max_single; } int maxPathSum(TreeNode* root) { int res = INT_MIN; findMax(root, res); return res; } };
//这次完全是自己写出来的噢
/** * 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: int maxd; int dfs(TreeNode* cur){ if(cur == NULL) return 0; int left = dfs(cur->left); int right = dfs(cur->right); int d = cur->val; if(left > 0) d+= left; if(right > 0) d+= right; maxd = max(maxd, d); int recur_d = cur->val; if(left>0 || right>0){ recur_d += left>right ? left : right; } return recur_d; } int maxPathSum(TreeNode* root) { maxd = -1e9; dfs(root); return maxd; } };
/** * 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<string> binaryTreePaths(TreeNode* root) { vector<string> res; if(root == NULL) return res; //返回空vector res if(root->left==NULL && root->right==NULL) res.push_back(to_string(root->val)); //divide vector<string> left = binaryTreePaths(root->left); vector<string> right = binaryTreePaths(root->right); //conquer for(string s : left) res.push_back(to_string(root->val) + "->" + s); for(string s : right) res.push_back(to_string(root->val) + "->" + s); return res; } };
注意这里s不能传入引用。
/** * 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<string> res; void dfs(TreeNode* cur, string s){ if(cur == NULL) return; s += (to_string(cur->val)); if(cur->left == NULL && cur->right == NULL){ res.push_back(s); } if(cur->left) dfs(cur->left, s + "->"); if(cur->right) dfs(cur->right, s + "->"); } vector<string> binaryTreePaths(TreeNode* root) { res={}; if(root == NULL) return res; string s = ""; dfs(root, s); return res; } };
用队列来实现二叉树的宽度优先搜索:
/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ //BFS + queue class Solution { public: vector<vector<int>> levelOrder(TreeNode* root) { queue<TreeNode* > q; vector<vector<int>> res; if(root == NULL) return res; q.push(root); while(!q.empty()){ int size = q.size(); //取每一层有多少结点,一定要取出来,因为q.size()会变化 vector<int> curlevel; //遍历每一层 for(int i=0; i<size; i++){ TreeNode* tmp = q.front(); curlevel.push_back(tmp->val); q.pop(); if(tmp->left != NULL) q.push(tmp->left); if(tmp->right != NULL) q.push(tmp->right); } res.push_back(curlevel); } return res; } };
448. Inorder Successor in BST
/** * 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: /* * @param root: The root of the BST. * @param p: You need find the successor node of p. * @return: Successor of p. */ TreeNode* cur = NULL; TreeNode * inorderSuccessor(TreeNode * root, TreeNode * p) { // write your code here if(root == NULL || p == NULL) return NULL; if(root->val <= p->val){ if(root->right){ inorderSuccessor(root->right, p); } } else{ if(root->left) cur = inorderSuccessor(root->left, p); if(cur == NULL) return root; else return cur; } } };
1)
参考: https://zhuanlan.zhihu.com/p/46841937
/** * 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: bool isValidBST(TreeNode* root) { if(root == NULL) return true; if(root->left == NULL && root->right == NULL) return true; if(root->left){ TreeNode* leftmax = left_Max(root->left); if(root->val <= leftmax->val) return false; } if(root->right){ TreeNode* rightmin = right_Min(root->right); if(root->val >= rightmin->val) return false; } return isValidBST(root->left) && isValidBST(root->right); } TreeNode* left_Max(TreeNode* cur){ while(cur->right) cur = cur->right; return cur; } TreeNode* right_Min(TreeNode* cur){ while(cur->left) cur = cur->left; return cur; } };
2)中序遍历这颗BST,将结点存到数组res中,再判断res中的结点是否是严格递增的
/** * 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<int> res; void inOrder(TreeNode* cur){ if(cur == NULL) return; inOrder(cur->left); res.push_back(cur->val); inOrder(cur->right); } bool isValidBST(TreeNode* root) { if(root == NULL) return true; inOrder(root); for(int i=0; i<res.size()-1; i++){ if(res[i] >= res[i+1]) return false; } return true; } };