首页 > 代码库 > leetcode day4 -- Binary Tree Postorder(Preorder) Traversal && Edit Distance

leetcode day4 -- Binary Tree Postorder(Preorder) Traversal && Edit Distance



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; 
    }
};