本题的难点在于如何发现出错的节点,记录下来后交换。常规的做法分三步
(1)通过中序遍历获取一个排序数列
(2)找到排序数列中出问题的地方
(3)再次遍历找到出问题的位置并交换值
但是实际上,如果能在遍历过程中确定出问题的地方,即可以直接交换,算法会优化很多。这里可以采用迭代和递归只进行少于一次的遍历,它们都需要高达O(H) 的空间来保存堆栈,其中 H 指的是树的高度。Morris 算法是遍历两次的方法,但它是一个常数级空间的方法
/**
* 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:
void swap(TreeNode *a, TreeNode *b)
{
int tmp = a->val;
a->val = b->val;
b->val = tmp;
}
void recoverTree(TreeNode *root)
{
// predecessor is a Morris predecessor.
// In the 'loop' cases it could be equal to the node itself predecessor == root.
// pred is a 'true' predecessor,
// the previous node in the inorder traversal.
TreeNode *x = NULL, *y = NULL, *pred = NULL, *predecessor = NULL;
while (root != NULL) {
// If there is a left child
// then compute the predecessor.
// If there is no link predecessor.right = root --> set it.
// If there is a link predecessor.right = root --> break it.
if (root->left != NULL) {
// Predecessor node is one step left
// and then right till you can.
predecessor = root->left;
while (predecessor->right != NULL && predecessor->right != root)
predecessor = predecessor->right;
// set link predecessor.right = root
// and go to explore left subtree
if (predecessor->right == NULL) {
predecessor->right = root;
root = root->left;
}
// break link predecessor.right = root
// link is broken : time to change subtree and go right
else {
// check for the swapped nodes
if (pred != NULL && root->val < pred->val) {
y = root;
if (x == NULL) x = pred;
}
pred = root;
predecessor->right = NULL;
root = root->right;
}
}
// If there is no left child
// then just go right.
else {
// check for the swapped nodes
if (pred != NULL && root->val < pred->val) {
y = root;
if (x == NULL) x = pred;
}
pred = root;
root = root->right;
}
}
swap(x, y);
}
};
很简单,遍历比较即可
/**
* 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 isSameTree(TreeNode* p, TreeNode* q) {
if (p == NULL && q == NULL)
return true;
else if (p == NULL || q == NULL)
return false;
if (p->val != q->val)
return false;
if (p->left == NULL && q->left == NULL
&& p->right == NULL && q->right == NULL
&& p->val == q->val)
return true;
if (isSameTree(p->left, q->left) &&
isSameTree(p->right, q->right))
return true;
else return false;
}
};
本题可以采用递归求解,依次判断左子树的左子树和右子树的右子树以及左子树的右子树和右子树的左子树即可。也可以采用队列或者堆栈,原理相同。
/**
* 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 isSymmetric(TreeNode* root) {
if (root == NULL)
return true;
else
return isSame(root->left, root->right);
}
bool isSame(TreeNode *lhs, TreeNode *rhs)
{
if (lhs == NULL && rhs == NULL)
return true;
else if (lhs == NULL || rhs == NULL)
return false;
if (lhs->val == rhs->val)
return (isSame(lhs->left, rhs->right) &&
isSame(lhs->right, rhs->left));
else return false;
}
};
对于普通遍历多一个变量记录层级即可,然后对应层级记录
/**
* 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 {
vector<vector<int>> ret;
public:
vector<vector<int>> levelOrder(TreeNode* root) {
search(root, 0);
return ret;
}
void search(TreeNode *root, int height)
{
if (root == NULL)
return;
if(ret.size() == height)
ret.resize(height + 1);
ret[height].push_back(root->val);
height++;
search(root->left, height);
search(root->right, height);
}
};
本题和上题其实没啥区别,加一个层级判断从前或者从后插入即可
/**
* 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 {
vector<vector<int>> ret;
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
search(root, 0);
return ret;
}
void search(TreeNode *root, int height)
{
if (root == NULL)
return;
if(ret.size() == height)
ret.resize(height + 1);
if (height % 2 == 0)
ret[height].push_back(root->val);
else ret[height].insert(ret[height].begin(), root->val);
height++;
search(root->left, height);
search(root->right, height);
}
};
很简单的一道题,遍历同时记录大小并存最大值即可
/**
* 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 {
int max = 0;
public:
int maxDepth(TreeNode* root) {
int height = 0;
search(root, height);
return max;
}
void search(TreeNode *root, int height)
{
if (root == NULL)
return;
else
{
height++;
if (height > max)
max = height;
search(root->left, height);
search(root->right, height);
}
}
};
本题的核心思想在于前序的开始为根节点,而中序根节点左侧为左子树,因此可以递归查找:每次由前序判断根,由中序判断左右子树,然后左右子树按照这个规律继续判断,直到没有节点为止
/**
* 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* buildTree(vector<int>& preorder, vector<int>& inorder) {
int pos = 0;
return buildTree(preorder, pos, inorder, 0, inorder.size() - 1);
}
TreeNode* buildTree(vector<int>& preorder, int& pos, vector<int>& inorder, int left, int right)
{
if (pos >= preorder.size())
return 0;
int i = left;
// 搜索到目前的根在中序的位置i
for (; i <= right; ++i)
{
if (inorder[i] == preorder[pos])
break;
}
// 当前的根为前序的pos
TreeNode* node = new TreeNode(preorder[pos]);
// 当左边只剩一个就不用递归了
if (left <= i - 1)
node->left = buildTree(preorder, ++pos, inorder, left, i - 1); // 左子树
// 当右边只剩一个也是不用了
if (i + 1 <= right)
node->right = buildTree(preorder, ++pos, inorder, i + 1, right); // 右子树
return node;
}
};