leetcode 树题目整理一(144/94/145/102/107/103含迭代与递归的区别,二叉树前序/中序/后序遍历,层次遍历)

迭代算法与递归算法的区别

迭代算法

迭代算法让计算机对一组指令进行重复执行。迭代是正向思维,从头到尾的思考问题。
例如,计算从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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值