迭代算法与递归算法的区别
迭代算法
迭代算法让计算机对一组指令进行重复执行。迭代是正向思维,从头到尾的思考问题。
例如,计算从1到100的累加值,顺着往下累加,用程序表示为:
int i=1,sum=0;
while(i<=100){
sum = sum +i;
}
递归算法
采用递归算法的问题通常具有这样的特征:为求解规模为N的问题,我们要将它分解成规模较小的问题,然后从这些小问题的解方便的构造出大问题的解,并且这些小问题和大问题具有相同的解决方法。
递归是逆向思维,假设我们已经知道了部分结果,从尾部追溯到头部,从而让问题简化。
递归算法的执行过程分递推和回归两个阶段。
int GetSum(int n)
{
if(n<=0) return 0;
else return n+GetSum(n-1);
}
144 二叉树的前序遍历
用递归和迭代两种方式求解。
递归:采用DFS直接递归实现,按照root, left, right的顺序,依次遍历。
class Solution {
public:
void findPreOrder(TreeNode* root,vector<int> &ans){
ans.push_back(root->val);
if(root->left != NULL)
findPreOrder(root->left,ans);
if(root->right != NULL)
findPreOrder(root->right,ans);
return ;
}
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ans;
if(root == NULL){
return ans;
}
findPreOrder(root,ans);
return ans;
}
};
迭代:自己用栈来完成递归的功能。首先压入根节点,当栈内元素不为空时,取栈顶元素并弹出,随后将该栈顶元素的值存入答案数组中,再分别压入该栈顶元素的右子树和左子树,重复以上步骤直到栈内为空。
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ans;
stack<TreeNode*> st;
if(root == NULL)
return ans;
st.push(root);
while(!st.empty()){
auto u = st.top();
st.pop();
ans.push_back(u -> val);
if(u -> right != NULL){
st.push(u -> right);
}
if(u -> left != NULL){
st.push(u -> left);
}
}
return ans;
}
};
94 二叉树的中序遍历
用递归和迭代两种方式求解。
递归:采用DFS直接递归实现,按照left, root, right的顺序,依次遍历。
class Solution {
public:
void findInorderTraversal(TreeNode* root,vector<int> &ans){
if(root->left != NULL){
findInorderTraversal(root->left,ans);
}
ans.push_back(root->val);
if(root->right != NULL){
findInorderTraversal(root->right,ans);
}
reutrn ;
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ans;
if(root == NULL){
return ans;
}
findInorderTraversal(root,ans);
return ans;
}
};
迭代:自己用栈来完成递归的功能。首先压入根节点,当栈内元素不为空时,取栈顶元素并弹出,随后,再分别压入该栈顶元素的右节点,栈顶节点和左节点。栈内元素格式为pair<TreeNode*, bool>
,当节点第一次被压入栈中时,标记为false
,第二次压入时,标记为true
。当标记为true
时,将该栈顶元素的值存入答案数组中。重复以上步骤直到栈内为空。
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ans;
if(root == NULL){
return ans;
}
stack<pair<TreeNode*, bool>> st;
st.push(make_pair(root, false));
while(!st.empty()){
auto u = st.top();
st.pop();
if(u.second == true){
ans.push_back(u.first -> val);
}
else{
if(u.first -> right != NULL){
st.push(make_pair(u.first -> right, false));
}
st.push(make_pair(u.first, true));
if(u.first -> left != NULL){
st.push(make_pair(u.first -> left, false));
}
}
}
return ans;
}
};
145 二叉树的后序遍历
用递归和迭代两种方式求解。
递归:采用DFS直接递归实现,按照left, right, root的顺序,依次遍历。
class Solution {
public:
void findPostOrderTraversal(TreeNode* root, vector<int>& ans){
if(root -> left != NULL)
findPostOrderTraversal(root -> left, ans);
if(root -> right != NULL)
findPostOrderTraversal(root -> right, ans);
ans.push_back(root -> val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ans;
if(root == NULL)
return ans;
findPostOrderTraversal(root, ans);
return ans;
}
};
迭代:自己用栈来完成递归的功能。首先压入根节点,当栈内元素不为空时,取栈顶元素并弹出,随后,再分别压入该栈顶元素的栈顶节点,右节点,左节点。栈内元素格式为pair<TreeNode*, bool>
,当节点第一次被压入栈中时,标记为false
,第二次压入时,标记为true
。当取出的栈顶元素标记为true
时,证明已经遍历完成该节点的左子树和右子树,将该栈顶元素的值存入答案数组中。重复以上步骤直到栈内为空。
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ans;
if(root == NULL){
return ans;
}
stack<pair<TreeNode*, bool>> st;
st.push(make_pair(root, false));
while(!st.empty()){
auto u = st.top();
st.pop();
if(u.second == true){
ans.push_back(u.first -> val);
}
else{
st.push(make_pair(u.first, true));
if(u.first -> right != NULL){
st.push(make_pair(u.first -> right, false));
}
if(u.first -> left != NULL){
st.push(make_pair(u.first -> left, false));
}
}
}
return ans;
}
};
102 二叉树的层次遍历
给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。
BFS:宽度优先搜索。用队列的形式,依次遍历每个节点,队列中存储的数据格式为pair<TreeNode* node, int depth>
,其中depth控制将节点的值存入数组的第几行。
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root) {
vector<vector<int>> ans;
if(root == NULL)
return ans;
queue<pair<TreeNode*, int>> Q;
Q.push(make_pair(root, 0));
while(!Q.empty()) {
auto q = Q.front();
Q.pop();
if(ans.size() <= q.second)
ans.push_back({});
ans[q.second].push_back(q.first -> val);
if(q.first -> left != NULL)
Q.push(make_pair(q.first -> left, q.second + 1));
if(q.first -> right != NULL)
Q.push(make_pair(q.first -> right, q.second + 1));
}
return ans;
}
};
107 二叉树的层次遍历2
给定一个二叉树,返回其节点值自底向上的层次遍历。 (即逐层地,从左到右访问所有节点)。
BFS:宽度优先搜索。先采用BFS遍历一遍所有的节点,求出该二叉树的最大深度max_depth
,之后再遍历一遍,用队列的形式,依次遍历每个节点,控制行数时,采用max_depth - depth
控制,其余同102题目。
class Solution {
public:
vector<vector<int>> levelOrderBottom(TreeNode* root) {
vector<vector<int>> ans1;
if(root == NULL){
return ans1;
}
queue<pair<TreeNode*, int>> Q;
Q.push(make_pair(root, 0));
int depth = 0;
while(!Q.empty()){
auto u = Q.front();
Q.pop();
depth = max(depth, u.second);
if(u.first -> left != NULL){
Q.push(make_pair(u.first -> left, u.second + 1));
}
if(u.first -> right != NULL){
Q.push(make_pair(u.first -> right, u.second + 1));
}
}
vector<vector<int>> ans(depth + 1);
Q.push(make_pair(root, 0));
while(!Q.empty()){
auto u = Q.front();
Q.pop();
ans[depth - u.second].push_back(u.first -> val);
if(u.first -> left != NULL){
Q.push(make_pair(u.first -> left, u.second + 1));
}
if(u.first -> right != NULL){
Q.push(make_pair(u.first -> right, u.second + 1));
}
}
return ans;
}
};
103 二叉树的锯齿形层次遍历
题目描述: 给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
① 可以同102题目,采用BFS得出顺序层次遍历数组,然后reverse每个奇数行。
② 用两个stack,每个stack各自保存一层节点,利用stack先进后出的特点,调整左右节点的入栈顺序。(借鉴了用队列进行树的层次遍历的思想)
class Solution {
public:
// 两个stack
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> ans;
if(root == NULL)
return ans;
stack<TreeNode*> st1, st2;
st1.push(root);
while(1) {
vector<int> tmp;
while(!st1.empty()) {
auto u = st1.top();
st1.pop();
tmp.push_back(u -> val);
if(u -> left != NULL)
st2.push(u -> left);
if(u -> right != NULL)
st2.push(u -> right);
}
if(tmp.size() != 0) {
ans.push_back(tmp);
tmp.clear();
}
else
break;
while(!st2.empty()) {
auto u = st2.top();
st2.pop();
tmp.push_back(u -> val);
if(u -> right != NULL)
st1.push(u -> right);
if(u -> left != NULL)
st1.push(u -> left);
}
if(tmp.size() != 0) {
ans.push_back(tmp);
tmp.clear();
}
else
break;
}
return ans;
}
};