1、Binary Tree Postorder Traversal
Given a binary tree, return the postorder traversal of its nodes' values.
For example:
Given binary tree {1,#,2,3}
,
1 \ 2 / 3
return [3,2,1]
.
Note: Recursive solution is trivial, could you do it iteratively?
分析:后续遍历二叉树,使用递归方法非常简单,分别递归遍历左子树、右子树,然后打印根结点值;
如果使用非递归遍历,感觉比较复杂,一般想法在首先往左走到最左结点,将前面的结点用栈保存,每次根据栈顶元素,判断该元素右子树是否为空,如果不为空则还得往坐走,还需要判断结点是否遍历过。
最后参考http://blog.csdn.net/wzy_1988/article/details/8450952,最后代码实现中,采用设置一个标志结点为上次输入后续遍历序列中的结点:每次判断栈结点的右孩子是否为标志结点,如果为标志结点说明右子树已经遍历结束,直接弹出该结点;如果右孩子不是标志结点,则说明该结点的右子树没有被遍历,则继续循环,进行右孩子压栈处理。
代码如下:
class Solution {
public:
vector<int> postorderTraversal(TreeNode *root) {
vector<int> postVec;
TreeNode* preNode = NULL;
TreeNode* tempNode = root;
while(tempNode != NULL || !nodeStack.empty()){
if( tempNode != NULL){ //走到左子树的头
nodeStack.push(tempNode);
tempNode = tempNode->left;
}else{ //如果为空,则遍历右子树
TreeNode* tempRoot = nodeStack.top();
if(tempRoot->right != NULL && tempRoot->right != preNode){ //右结点不为空,且不是刚遍历的结点
tempNode = tempRoot->right;
}else{
preNode = nodeStack.top(); //保存上次输出的结果
postVec.push_back(preNode->val);
nodeStack.pop();
}
}
}
return postVec;
}
private:
stack<TreeNode*> nodeStack;
};
2、Binary Tree Preorder Traversal
Given a binary tree, return the preorder traversal of its nodes' values.
For example:
Given binary tree {1,#,2,3}
,
1 \ 2 / 3
return [1,2,3]
.
Note: Recursive solution is trivial, could you do it iteratively?
分析:使用非递归前序遍历二叉树,已经弄清楚后续遍历了,前序遍历比较简单,只需要用stack保存遍历的结点,访问过的肯定在遍历序列中,不需要关心结点是否遍历过。思路:从根结点开始往左子树走,遇到的结点压栈且插入输出序列,当左孩子为空时,弹栈,往右孩子走一步,再继续上述循环。
代码如下:
class Solution {
public:
vector<int> preorderTraversal(TreeNode *root) {
stack<TreeNode*> nodeStack;
vector<int> preVec;
while(root != NULL || !nodeStack.empty()){
if(root){
preVec.push_back(root->val);
nodeStack.push(root);
root = root->left;
}else{
root = nodeStack.top();
nodeStack.pop();
root = root->right;
}
}
return preVec;
}
};
3、Edit Distance
Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)
You have the following 3 operations permitted on a word:
a) Insert a character
b) Delete a character
c) Replace a character
分析:求最小编辑距离,这是一个很常见的题目,采用动态规划的方法,借鉴《算法导论》里面求最大公共字串的方法,建立一个矩阵,c[m+1][n+1](其中m,n分别为两个单词的长度),初始化c[0][j]=j,j=0...n,c[i][0]=i,i=0...m;求c[i][j],插入或者删除花费为c[i-1][j]+1和c[i][j-1]+1中的小者,替换花费为如果word1[i]==word2[j],则为c[i-1][j-1],否则为c[i-1][j-1]+1.
代码如下:
class Solution {
public:
int minDistance(string word1, string word2) {
int len1 = word1.length();
int len2 = word2.length();
int** c = new int*[len1+1];
for(int i=0; i<len1+1; ++i){
c[i] = new int[len2+1];
}
for(int i=0; i<len1+1;++i){
c[i][0] = i;
}
for(int j=0; j<len2+1; ++j){
c[0][j] = j;
}
for(int i=1; i<len1+1;++i){
for(int j=1; j<len2+1; ++j){
int insertCost = min(c[i][j-1],c[i-1][j])+1;
int replaceCost = c[i-1][j-1];
if(word1[i-1] != word2[j-1]){
replaceCost += 1;
}
c[i][j] = min(insertCost,replaceCost);
}
}
int result = c[len1][len2];
for(int i=0; i<len1+1; ++i){
delete[] c[i];
}
delete[] c;
return result;
}
};