之前的一章花的时间太长了,因此考虑有必要加快自己做题的步伐,毕竟这些题其实都比较基础,自己还要挑战更高更难的题目呢,加油吧自己。
栈的压入弹出序列
题目描述:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
题目分析:这道题其实就是判断某个数组是不是栈的弹出序列,其实栈的输入和输出序列是有一定规律的。就如实例中中所给的例子一样,如果4是第一个弹出的,那么1,2,3一定还在栈中,所以这道题我们可以用真正的栈来走一走就知道结果了。这个题很重要的一点就是数组中的数不能相同,否则这个题的难度会直线上升,会超级复杂递归分析。
class Solution {
public:
bool IsPopOrder(vector<int> pushV,vector<int> popV) {
if (pushV.empty() || popV.empty()) { return true; }
if (pushV.size() != popV.size()) { return false; }
stack<int>temp;
int i = 0; int j = 0;
while (i<pushV.size() || j<popV.size()) { //为空,输入未完成
if (temp.empty() && i < pushV.size()) {
temp.push(pushV[i]);
i++;
continue;
}
if (temp.top() == popV[j]) { //不为空,等于弹出值
temp.pop();
j++;
continue;
}
if (temp.top() != popV[j] && i < pushV.size()) { //不为空,不等于弹出值,输入未完成
temp.push(pushV[i]);
i++;
continue;
}
if (temp.top() != popV[j] && i >= pushV.size()) { //不为空,不等于弹出值,输入已完成
return false;
}
}
return true;
}
};
从上向下打印二叉树
题目描述:从上往下打印出二叉树的每个节点,同层节点从左至右打印。
题目分析:这就是最简单的层次遍历,很简单,利用队列的性质即可。
/*
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};*/
class Solution {
public:
vector<int> PrintFromTopToBottom(TreeNode* root) {
vector<int>output;
if (root == nullptr)return output;
queue<TreeNode*>temp; //关键就是利用队列的性质
temp.push(root);
while (!temp.empty()) {
TreeNode* temptop=temp.front();
if (temptop->left != nullptr)temp.push(temptop->left);
if (temptop->right != nullptr)temp.push(temptop->right);
output.push_back(temptop->val);
temp.pop();
}
return output;
}
};
二叉树的后序遍历序列
题目描述:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
题目分析:这里主要考的是二叉搜索树的后续遍历序列性质。对于二叉搜索数,左子树<根<右子树。后序遍历的顺序是左右根,也就时候的根节点在最后。也就是前面的树分成两部分,一部分比根小,一部分比根大。递归分析,当每一部分满足要求的时候,就是满足的序列。
class Solution {
public:
bool Islastsort(vector<int> sequence,int low,int high) {
if (high - low <= 2)return true; //3个数以内一定对,这样可以减少递归次数,节约时间空间
int cha=0, precha;
int fengedian=-1;
int changeflag = 0;
for (int i = low; i < high; i++) {
precha = cha;
cha = sequence[i] - sequence[high];
if (cha*precha < 0) {
changeflag++;
fengedian = i; //找到正负值交换的位置
}
if (changeflag > 1)return false; //跳跃了两次正负,一定是错的
}
if (fengedian == -1)return true; //如果没有分割点,那就是一定是单边树了,一定对的
return Islastsort(sequence, low, fengedian - 1) && Islastsort(sequence, fengedian, high - 1);
}
bool VerifySquenceOfBST(vector<int> sequence) {
int number = sequence.size();
if(number == 0)return false;
if(number <= 3)return true; //当只有1,2,3个树的时候,一定对
return Islastsort(sequence, 0, number - 1);
}
};
二叉树中和为某一值的路径
题目描述:输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
题目分析:这里的每一条路都是从根节点开始,可以很容易遍历整个数组找到叶节点,但关键是是要把真个节点保存下来,判断节点之和后加入到输出的数组簇中。这个题如果用用递归,会非常麻烦,因此考虑最好使用非递归的遍历写法。本身遍历时的stack就存储了该路径的信息。
//递归写法
class Solution {
public:
void recordPath(vector<vector <int>> &res,vector<int> &temp,TreeNode *root,int exNum)
{
if(exNum<0)
return;
temp.push_back(root->val);
exNum-=root->val;
if(!root->left&&!root->right)
{
if(exNum==0)
res.push_back(temp);
}
if(root->left)
{
recordPath(res,temp,root->left,exNum);
temp.pop_back();
}
if(root->right)
{
recordPath(res,temp,root->right,exNum);
temp.pop_back();
}
}
vector<vector<int> > FindPath(TreeNode* root,int expectNumber)
{
vector<vector <int>> res;
vector<int> temp;
if(!root)
return res;
recordPath(res,temp,root,expectNumber);
return res;
}
};