二叉树的第一部分算法如下
https://blog.csdn.net/weixin_44611644/article/details/95897436
下面是第二部分的二叉树题目
(1)知道前序和中序之后,重建二叉树
前序遍历的特点是第一个值为根节点,中序遍历的值是根节点在中间,利用此规律对数组进行分割归并。
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
int n = pre.size();
if(n!=vin.size()||n==0)
return nullptr;
TreeNode* root = new TreeNode(pre[0]);
vector<int> newPre;
vector<int> newVin;
for(int i = 0;i<vin.size();i++)
{
if(vin[i] == pre[0])
{
newPre.assign(pre.begin()+1,pre.begin()+i+1);
newVin.assign(vin.begin(),vin.begin()+i);
root->left = reConstructBinaryTree(newPre,newVin);
newPre.assign(pre.begin()+i+1,pre.end());
newVin.assign(vin.begin()+i+1,vin.end());
root->right = reConstructBinaryTree(newPre,newVin);
break;
}
}
return root;
}
(2)二叉搜索树展开为双向链表
和二叉树展开为链表相似,递归算法。
TreeNode* Convert(TreeNode* pRootOfTree)
{
if(pRootOfTree == nullptr) return nullptr;
TreeNode* pre = nullptr;
convertHelper(pRootOfTree, pre);
TreeNode* res = pRootOfTree;
while(res ->left)
res = res ->left;
return res;
}
void convertHelper(TreeNode* cur, TreeNode*& pre)
{
if(cur == nullptr) return;
convertHelper(cur ->left, pre);
cur ->left = pre;
if(pre) pre ->right = cur;
pre = cur;
convertHelper(cur ->right, pre);
}
(3)左右视图树
以左视图树讲解,代表从最左面能看到的结点,可以这样做,先遍历一次,map存放结点和层数,然后进行逆序更新,就是从右忘左更新,比如第三层有2个结点 左面的结点是x1,右面的结点是x2,map中的键值对应关系是去重复的,先加载了x2 map[3]=x2;这里含义就是第三层能看到x2,逆序的最后把map[3]的值更新成了x1,这样就实现了map中保存的是各个层中 最左面的那个数。
void reUpdate(vector<float> &result) {
map<int, float> mp;
// 逆序更新
for(int i = result.size() - 1; i >0; i -= 2) {
auto pos = mp.find((int)result[i - 1]);
// 如果已经存在则更新,若不存在则添加
if(pos != mp.end()) {
pos->second = result[i]; // 更新
} else {
mp.insert(make_pair((int)result[i - 1], result[i]));
}
}
// 清空原result
vector<float>().swap(result);
// 将mp的结果放入result,并输出结果
for(auto pair : mp) {
result.push_back(pair.second);
}
}
void preLeftView(Node & node, vector<float> &result, const int deep = 0) {
result.push_back(deep);
result.push_back(node.data);
if(node.leftChiled != nullptr) {
preLeftView(*(node.leftChiled), result, deep + 1);
}
if(node.rightChiled != nullptr) {
preLeftView(*(node.rightChiled), result, deep + 1);
}
}
// 左视图生成函数
void leftView(Node & node) {
vector<float> result;
preLeftView(node, result);
// 逆序更新result
reUpdate(result);
for(auto x : result) {
cout << x << " ";
}
}
(4)判断是不是二叉搜索树后序遍历的结果
特点是 左节点比自己小,右结点比自己大。后序遍历的话根节点在最后,对数组进行遍历,先升后降,如果最后到达数组末尾则这个结点符合规律,依次判断全部结点。
这时候如果比较难理解的话不妨自己画一棵树模拟一下。
bool VerifySquenceOfBST(vector<int> sequence) {
int size = sequence.size();
if(0==size)return false;
int i = 0;
while(--size)
{
while(sequence[i++]<sequence[size]);
while(sequence[i++]>sequence[size]);
if(i<size)return false;
i=0;
}
return true;
}
(5)二叉树中和为某一值的路径
和为某一值的路径可能不止一条,用二维数组保存所有结果。
class Solution {
public:
vector<vector<int> > FindPath(TreeNode* root,int expectNumber)
{
if (!root) return res;
cur.push_back(root->val);
if (root->val == expectNumber && !root->left && !root->right)
res.push_back(cur);
FindPath(root->left, expectNumber - root->val);
FindPath(root->right, expectNumber - root->val);
if (!cur.empty())
cur.pop_back();
return res;
}
private:
vector<int> cur;
vector<vector<int>> res;
};