版权声明:本文为博主原创学习笔记,如需转载请注明来源。 https://blog.csdn.net/SHU15121856/article/details/82585796
D是Degree,后续遍历就是LRD,前序遍历就是DLR。
面试题33:BST的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。
后序遍历是左右中,而根据BST的特性,这个序列中的数字大小情况是小大中,以最后一个结点根节点为基准,可以判断这一层是不是符合要求,同时也划分出了左右子树,再分别对左右子树做递归地判断。
#include<bits/stdc++.h>
using namespace std;
// 参数:
// sequence: 后续遍历序列
// length: 序列的长度
// 返回值:
// 这个后序遍历序列能否属于某BST(二叉搜索树)
bool VerifySquenceOfBST(int sequence[], int length) {
if(sequence == nullptr || length <= 0)//输入合法性校验
return false;
int root = sequence[length - 1];//根节点是最后一个结点
//在二叉搜索树中左子树的结点小于根结点
int i = 0;
for(; i < length - 1; ++ i) {//左右中,所以从左向右扫描
if(sequence[i] > root)//发现第一个大于根节点的值
break;//这时就退出,i点左侧的全部值属于左子树
}
//在二叉搜索树中右子树的结点大于根结点
int j = i;//从刚刚找到的分界位置
for(; j < length - 1; ++ j) {//继续向后检查应当是右子树的部分
if(sequence[j] < root)//如果发现比根结点小的值
return false;//说明该序列不满足要求,绝不是BST的后续遍历序列
}
//判断左子树是不是二叉搜索树
bool left = true;
if(i > 0)//分界点i>0左子树才是真实存在的,即至少有个sequence[0]结点\
//分界点i正好表示其左侧的结点数,即左子树结点数
left = VerifySquenceOfBST(sequence, i);
//判断右子树是不是二叉搜索树
bool right = true;
if(i < length - 1)//分界点i不到达根结点位置,右子树才是真实存在的
//序列起始点要跳过i个左子树结点,序列长度要减掉1个根节点和i个左子树结点
right = VerifySquenceOfBST(sequence + i, length - i - 1);
//左右子树都为BST时,在该子树上才能认为是BST
return (left && right);
}
// 10
// / \
// 6 14
// /\ /\
// 4 8 12 16
int main() {
int data[] = {4, 8, 6, 12, 16, 14, 10};
cout<<boolalpha<<VerifySquenceOfBST(data,sizeof(data)/sizeof(int));
return 0;
}
面试题34:二叉树中和为某一值的路径
输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
DFS遍历这棵二叉树,然后每次走到叶结点就判断一下是否满足条件。可以用前序遍历即中左右来DFS这棵二叉树。
#include<bits/stdc++.h>
#include "../Utilities/BinaryTree.h"
using namespace std;
void FindPath(BinaryTreeNode* pRoot, int expectedSum, std::vector<int>& path, int& currentSum);
// 参数:
// pRoot: 二叉树根
// expectedSum: 想检查的路径和
// 输出:
// 找到的路径
void FindPath(BinaryTreeNode* pRoot, int expectedSum) {
if(pRoot == nullptr)
return;
//用vector模拟栈,因为打印路径时需要得到路径上所有结点,stack不方便
vector<int> path;
int currentSum = 0;//当前路径上的加和
FindPath(pRoot, expectedSum, path, currentSum);
}
//递归函数,在二叉子树上,根据当前已检查到的路径和继续检查,直到叶子
void FindPath
(
BinaryTreeNode* pRoot, //二叉(子)树根
int expectedSum, //想检查的路径和
vector<int>& path, //记录当前路径上结点的栈
int& currentSum //当前路径上的加和
) {
currentSum += pRoot->m_nValue; //当前路径和要加上这个子树的根值
path.push_back(pRoot->m_nValue);//将其加入到栈中(尾入)
//判断是否叶子:左右孩子都为空就是叶结点
bool isLeaf = pRoot->m_pLeft == nullptr && pRoot->m_pRight == nullptr;
//如果路径上结点的和等于输入的值,并且是叶结点
if(currentSum == expectedSum && isLeaf) {
//这时就找到了这条路径
printf("A path is found: ");
//用迭代器从头到尾输出这条路径上的结点值
vector<int>::iterator iter = path.begin();
for(; iter != path.end(); ++ iter)
printf("%d\t", *iter);
printf("\n");
}
//如果不是叶结点,则遍历它的子结点
if(pRoot->m_pLeft != nullptr)
FindPath(pRoot->m_pLeft, expectedSum, path, currentSum);
if(pRoot->m_pRight != nullptr)
FindPath(pRoot->m_pRight, expectedSum, path, currentSum);
//在返回到父结点之前,在路径上删除当前结点
path.pop_back();//将其弹出(尾出)
//并在当前路径和中减去这个结点的值
currentSum -= pRoot->m_nValue;
}
// 10
// / \
// 5 12
// /\
// 4 7
int main() {
BinaryTreeNode* pNode10 = CreateBinaryTreeNode(10);
BinaryTreeNode* pNode5 = CreateBinaryTreeNode(5);
BinaryTreeNode* pNode12 = CreateBinaryTreeNode(12);
BinaryTreeNode* pNode4 = CreateBinaryTreeNode(4);
BinaryTreeNode* pNode7 = CreateBinaryTreeNode(7);
ConnectTreeNodes(pNode10, pNode5, pNode12);
ConnectTreeNodes(pNode5, pNode4, pNode7);
FindPath(pNode10,22);
DestroyTree(pNode10);
return 0;
}