二叉樹的第一部分算法如下
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;
};