题目:递增顺序搜索树
代码
这道题是要我们把原来的二叉树转化为一个只有右节点的二叉树,并且要按照递增的顺序排列。由于是要实现递增,我们可以想到二叉树的中序遍历是可以实现递增的,(前提是,这是一棵二叉搜索树。)因此,我们可以先进行中序遍历,然后再进行操作使树按照要求的样子输出。
/**
* Definition for a binary tree node.
* 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:
TreeNode* increasingBST(TreeNode* root) {
vector<int> vals;
inOrder(root,vals);
TreeNode* ans=new TreeNode(0);
TreeNode* cur=ans;
for(auto v:vals){
cur->right=new TreeNode(v);
cur=cur->right;
}
return ans->right;
}
void inOrder(TreeNode* root,vector<int> &vals){
if(root==NULL){return;}
inOrder(root->left,vals);
vals.push_back(root->val);
inOrder(root->right,vals);
}
};
还有一种解法,是在中序遍历的时候,就把树变成要输出的样子,也可以。就是对中序遍历的代码稍作更改。
/**
* Definition for a binary tree node.
* 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:
TreeNode*cur;
TreeNode* increasingBST(TreeNode* root) {
TreeNode*ans=new TreeNode(0);
cur=ans;
inOrder(root);
return ans->right;
}
void inOrder(TreeNode* root){
if(root==NULL){return;}
inOrder(root->left);
root->left=NULL;
cur->right=root;
cur=root;
inOrder(root->right);
}
};
在这里,在中序遍历的时候,就对树进行了操作,使之变成了输出的样子,具体是将当前的节点左子树置为空,并把当前的节点设为前面加入树中的最后一个节点的右子树。还是要自己画几棵树,模拟几遍代码,就可以理解这里的中序遍历的代码了。
题目:求节点值的差(二叉树的坡度)
代码
/**
* Definition for a binary tree node.
* 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:
int tilt=0;
int findTilt(TreeNode* root) {
if(!root){return 0;};
vals(root);return tilt;
}
int vals(TreeNode* root){
if(!root){return 0;}
else{
int left=vals(root->left);
int right=vals(root->right);
tilt+=abs(left-right);
return left+right+root->val;
}
}
};
在这道题里面,我们把tilt这个需要返回的值作为一个全局变量来处理,因为这个也确实是一个关乎全局的值,而像左右子树的所有子节点的val的和的计算,就是需要用递归来处理的事情。这也是一个值得借鉴的地方,对于一个函数如果要返回两个值,可以使用一个全局来处理,剩下的那一个来用递归来处理。
题目:把一个二叉搜索树变平衡
这题的思路就是直接把原来的二叉搜索树先通过中序遍历把它变成一个有序的vector数组,然后再对这个有序数组进行操作,使之变成一个平衡二叉树,具体就是始终选择中间的那个元素作子树的根节点,然后对“分开的左右两边的”小数组,接着用这个方法,也就是接着递归,选择中间的数组作为子树的根节点,如此下去,这里理论上可以证明这种方法构建出来的是平衡二叉树。
代码:
/**
* 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> nodeSequence;
void getInorder(TreeNode* root){
if(!root){return;}
if(root->left){
getInorder(root->left);
}
nodeSequence.push_back(root->val);
if(root->right){
getInorder(root->right);
}
}
TreeNode* build(int l,int r){
int mid=(l+r)/2;
TreeNode*root=new TreeNode(nodeSequence[mid]);
if(l<=mid-1){
root->left=build(l,mid-1);
}
if(r>=mid+1){
root->right=build(mid+1,r);
}
return root;
}
TreeNode* balanceBST(TreeNode* root) {
getInorder(root);
return build(0,nodeSequence.size()-1);
}
};
这里nodeSequence是一个全局变量,用来存储中序遍历得到的有序序列。然后通过bulid()函数得到一个平衡二叉树。关于树的代码,大多都需要用到递归,就像这里这样。
题目:把一个有序数组变成二叉搜索树
代码:
这里的思路很简单, 每次取数组中间的元素作为子树的根节点,然后左边的放到左子树里面,右边的放到右子树里面,递归下去。
/**
* Definition for a binary tree node.
* 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:
TreeNode* sortedArrayToBST(vector<int>& nums) {
int l=0;
int r=nums.size()-1;
return binaryTree(nums,l,r);
}
TreeNode* binaryTree(vector<int>& nums,int l,int r){
int mid=ceil((float)(l+r)/2);
TreeNode* root=new TreeNode(nums[mid]);
if(l+1<=mid){
root->left=binaryTree(nums,l,mid-1);
}
if(r-1>=mid){
root->right=binaryTree(nums,mid+1,r);
}
return root;
}
};
题目:对称二叉树
代码:
可以使用递归的方法,也就是深度优先遍历的思想来解。
/**
* Definition for a binary tree node.
* 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 isSymmetric(TreeNode* root) {
return isRight(root,root);
}
bool isRight(TreeNode* root1,TreeNode* root2){
if(!root1&&!root2){
return true;
}
//如果两个根都是空,说明是对称的。
if(!root1||!root2){
return false;
}
//如果有一个是空的,说明肯定不是对称的,直接返回。
return ((root1->val==root2->val)
&&(isRight(root1->left,root2->right))
&&(isRight(root1->right,root2->left)));
//最后再递归的判断子树是不是对称的,这里的判断条件是左子树和右子树是不是一样的。
//因为要关于中间的那个对称轴对称。
}
};
这里使用isRight()函数来递归判断二叉树是不是一个对称二叉树。
接下来是用迭代的方法,也就是使用队列,来实现广度优先遍历。进而来判断是不是对称的。我么遍历到每一层的时候,都是把左子树的左边和右子树的右边去做对比,左子树的右边和右子树的左边去做对比,这样就可以判断了。
class Solution {
public:
bool isSymmetric(TreeNode* root) {
queue<TreeNode*> q;
q.push(root);
q.push(root);
while(!q.empty()){
TreeNode*a1=q.front();
q.pop();
TreeNode*a2=q.front();
q.pop();
if(a1==NULL&&a2==NULL){
continue;
}
if(a1==NULL||a2==NULL){
return false;
}
if(a1->val!=a2->val){return false;}
q.push(a1->left);
q.push(a2->right);
q.push(a1->right);
q.push(a2->left);
}
return true;
}
};
实际跑下来,两种方法时间上不差多少。哈哈哈。我本以为迭代就比递归快,两者的占用空间也没有多大的区别,这道题使用递归也没有造成空间的占用过大的问题。