算法基础__第4课(二叉树前中后序非递归遍历、层次遍历、二叉树的序列化与反序列化、二叉树的后继节点、二叉搜索树的后继节点、折纸问题)

1. 二叉树的锯齿形层次遍历
给出一棵二叉树,返回其节点值的锯齿形层次遍历(先从左往右,下一层再从右往左,层与层之间交替进行) 

样例
样例 1:

输入:{1,2,3}
输出:[[1],[3,2]]
解释:
    1
   / \
  2   3
它将被序列化为 {1,2,3}
样例 2:

输入:{3,9,20,#,#,15,7}
输出:[[3],[20,9],[15,7]]
解释:
    3
   / \
  9  20
    /  \
   15   7
它将被序列化为 {3,9,20,#,#,15,7}
/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param root: A Tree
     * @return: A list of lists of integer include the zigzag level order traversal of 
its nodes' values.
     */
     deque<TreeNode*> d;//
    vector<vector<int>> zigzagLevelOrder(TreeNode * root) {
        // write your code here
     vector<vector<int>> res;
     if(root == NULL)
        return res;
     d.push_back(root);
     int index = 0;
     while(!d.empty())
    {
        int t = d.size();
        vector<int> vt;
        if(index%2 == 0)
        {
            for (int i = 0; i < t; i++)
            {
                /* code */
                TreeNode * oushu = d.front();
                vt.push_back(oushu->val);
                d.pop_front();
                if(oushu->left)
                d.push_back(oushu->left);
                if(oushu->right)
                d.push_back(oushu->right);
            }
        }
        else
        {
              for (int i = 0; i < t; i++)
            {
                /* code */
                TreeNode * jishu = d.back();
                vt.push_back(jishu->val);
                d.pop_back();
                if(jishu->right)
                d.push_front(jishu->right);
                 if(jishu->left)
                d.push_front(jishu->left);
            }
        }
        index++;
          res.push_back(vt);  
    }
     return res;
    }
};
前序遍历
/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    vector<int> res;
    /**
     * @param root: A Tree
     * @return: Preorder in ArrayList which contains node values.
     */
    vector<int> preorderTraversal(TreeNode * root) {
        // write your code here
       //Preorder(root);
      PreorderNoCur(root);
       return res;
    }
    //非递归遍历
    void PreorderNoCur(TreeNode *root)
    {
       if(!root)
        return ;
        std::stack<TreeNode*> s ;
        s.push(root);
        while(!s.empty())
        {
            TreeNode *t = s.top();
            s.pop();
            res.push_back(t->val);
            if(t->right)
            s.push(t->right);
            if(t->left)
            s.push(t->left);
        }
        
    }
    
    
} ;
/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
vector<int> res;
    /**
     * @param root: A Tree
     * @return: Inorder in ArrayList which contains node values.
     */
    vector<int> inorderTraversal(TreeNode * root) {
        // write your code here
        InorderNocur(root);
        return res;
    }
        void Inorder(TreeNode *root)
      {
          if(root)
          {
              Inorder(root->left);
              res.push_back(root->val);
              Inorder(root->right);
          }
          
      }
     //非递归遍历
     void InorderNocur(TreeNode *root)
     {
         std::stack<TreeNode*> stk ;
         
         if(root)
         {
             TreeNode *head = root;
            while(!stk.empty() ||head)
            {
                while(head)//一直往左边走
                {
                    stk.push(head);
                    head = head->left;
                }
                if(!stk.empty())
                {
                    head = stk.top();
                    res.push_back(head->val);
                    stk.pop();
                    head = head->right;
                }
            }
         }
     }
};
/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    vector<int> res;
    /**
     * @param root: A Tree
     * @return: Postorder in ArrayList which contains node values.
     */
    vector<int> postorderTraversal(TreeNode * root) {
        // write your code here
        //二叉树的遍历 非递归遍历
        if(!root)
         return res;
        std::stack<TreeNode *> stk;
        TreeNode *head =  root, *pLast = NULL;
        while(head)
        {
            stk.push(head);
            head = head->left;
        }//一直朝着左边走
        while(!stk.empty())
        {
            TreeNode *r = stk.top();
            stk.pop();
            if(r->right == NULL || r->right == pLast)//标记是否被访问过
            {
                //因为两次经过同一个节点,需要标记是否被访问
                res.push_back(r->val);
                pLast = r;
            }//记录最近访问的节点
            else
            {
                stk.push(r);
                r = r->right;
                while(r)
                {
                    stk.push(r);
                    r = r->left;
                }
            }
            
        }
       return res; 
    }
};
设计一个算法,并编写代码来序列化和反序列化二叉树。将树写入一个文件被称为“序列化”,读取文件后重建同
样的二叉树被称为“反序列化”。

如何反序列化或序列化二叉树是没有限制的,你只需要确保可以将二叉树序列化为一个字符串,并且可以将字符
串反序列化为原来的树结构。

样例
样例 1:

输入:{3,9,20,#,#,15,7}
输出:{3,9,20,#,#,15,7}
解释:
二叉树 {3,9,20,#,#,15,7},表示如下的树结构:
	  3
	 / \
	9  20
	  /  \
	 15   7
它将被序列化为 {3,9,20,#,#,15,7}
样例 2:

输入:{1,2,3}
输出:{1,2,3}
解释:
二叉树 {1,2,3},表示如下的树结构:
   1
  / \
 2   3
它将被序列化为 {1,2,3}
我们的数据是进行 BFS 遍历得到的。当你测试结果 Wrong Answer 时,你可以作为输入调试你的代码。

你可以采用其他的方法进行序列化和反序列化。

注意事项
对二进制树进行反序列化或序列化的方式没有限制,LintCode 将您的 serialize 输出作为 deserialize 的
输入,它不会检查序列化的结果。

 

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */
class Solution {
public:
    /**
     * This method will be invoked first, you should design your own algorithm 
     * to serialize a binary tree which denote by a root node to a string which
     * can be easily deserialized by your own "deserialize" method later.
     */
     //按照满二叉树的特征遍历二叉树
    string serialize(TreeNode * root) {
        // write your code here
        preOrderA(root);
        return toString();
    }
    std::vector<string>res;
    //std::stack<TreeNode*> stk;
    void  preOrderA(TreeNode* root)
    {
     if(root == NULL) 
     {
        res.push_back("#");  
        return;
     }
     else
     {
         res.push_back(to_string(root->val));
         preOrderA(root->left);
         preOrderA(root->right);
     }
    }
     TreeNode * preOrderB(vector<string> arr, int &i)
    {
     if(arr[i] == "#") 
     {
          i++;//这个非常重要
        return NULL;
     }
     else
     {
         TreeNode * root =  new TreeNode(stoi(arr[i]));
         i++;//注意这里每次遍历都会导致数组下标的变化
         root->left = preOrderB(arr,  i);
         root->right =  preOrderB(arr, i);
         return root;
     }
    }
    string toString()
    {
        string  str = "";
        for (int i = 0; i < res.size(); i++) {
            /* code */
         str += res[i] +"?";
        }//最后一个位置多一个问号?
        return str;
    }
    /**
     * This method will be invoked second, the argument data is what exactly
     * you serialized at method "serialize", that means the data is not given by
     * system, it's given by your own serialize method. So the format of data is
     * designed by yourself, and deserialize it here as you serialize it in 
     * "serialize" method.
     */
    TreeNode * deserialize(string &data)
    {
        // write your code here
        vector<string> ret = splitString(data);
        int i = 0;
        return preOrderB(ret,i);
    }
    vector<string> splitString(string &data)
    {
        vector<string> ret;
        string :: size_type pos1 = 0, pos2 = 0;
        while(data.find("?",pos1) != string::npos)
        {
            pos2 = data.find("?", pos1);
            ret.push_back((data.substr(pos1, pos2 - pos1)));
            pos1  = pos2 + 1;
        }
        if(pos1 != data.size())
        {
            ret.push_back((data.substr(pos1)));
        }
        return ret;
    }
};
在二叉树中找到一个节点的后继节点
【题目】 现在有一种新的二叉树节点类型如下:
public class Node { public int value; public Node left; public Node right; public Node parent;
public Node(int data) { this.value = data; }
}
该结构比普通二叉树节点结构多了一个指向父节点的parent指针。假 设有一 棵Node类型的节点组成的二叉树,
树中每个节点的parent指针 都正确地指向 自己的父节点,头节点的parent指向null。只给一个在 二叉树中的
某个节点 node,请实现返回node的后继节点的函数。在二 叉树的中序遍历的序列中, node的下一个节点叫作
node的后继节点。
class Solution
{
public:
    TreeNode *res = NULL;
    TreeNode * findSuccessor(TreeNode *p)
    {
        if (p == NULL)
            return res;
        TreeNode *q = p;
        if(q->right)
        {
            q = q->right;
            while (q->left)
            {
                q = q->left;
            }
            res = q;
            return res;
        }
        else
        {
            proccess( p);
        }
        return res;
    }
    void  proccess(TreeNode *p)
    {
        TreeNode *q = p;
        TreeNode *parent = q->parent;
        while (parent!= NULL && parent->left != q)
        {
            q = q->parent;
            parent = q->parent;
        }
        res = parent;
    }
};
二叉搜索树的后继节点
class Solution{
public:
    /*
     * @param root: The root of the BST.
     * @param p: You need find the successor node of p.
     * @return: Successor of p.
     */
    TreeNode * inorderSuccessor(TreeNode * root, TreeNode * p) {
        // write your code here
        if(p == NULL)
            return NULL;
        inorder(root);
        int index = 0;
        int  aim = p->val;
        for (int i = 0; i <res.size(); i++)
        {
            /* code */
            if(aim == res[i]->val)
            {
                index = i+1;
                // cout << index <<endl;
                break;
            }
        }
        if (index == res.size()) {
            return NULL;
        }
        else
            return  res[index];
    }
    std::vector<TreeNode*> res ;
    void inorder(TreeNode *root)
    {
        if(root == NULL)
            return;
        inorder(root->left);
        res.push_back(root);
        inorder(root->right);
        
        
    }
};
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */


class Solution{
public:
    /*
     * @param root: The root of the BST.
     * @param p: You need find the successor node of p.
     * @return: Successor of p.
     */
    TreeNode *res = NULL;
    TreeNode * inorderSuccessor(TreeNode * root, TreeNode * p) {
        // write your code here
        if(p == NULL)
            return NULL;
        find(root, p);
        return res;
        
    }
    void  find(TreeNode *root,TreeNode *p)
    {
        if(p->right)//要在子节点中寻找
        {
            TreeNode  * pp = p->right;
            while(pp->left)
            {
                pp = pp->left;
            }
            res = pp;
            return;
        }
        else
        {//要在父节点中寻找
            proccess(root, p);
        }
    }
    void  proccess(TreeNode * root, TreeNode *p)
    {
        if(root == NULL)
        {
            return ;
        }
        if(root->val > p->val)//遍历左子树
        {
            res = root;//找到离p节点最近的比p的val值大的节点
            proccess(root->left, p);
        }
        else if(root->val < p->val)
        {
            proccess(root->right, p);
        }
        else
        {
            return ;
        }
    }
};
折纸问题

题目

请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。此时折痕是凹下去的,即折
痕突起的方向指向纸条的背面。如果从纸条的下边向上方连续对折2次,压出折痕后展开,此时有三条折痕,从上
到下依次是下折痕,下折痕和上折痕。给定一个输入参数N,代表纸条都从下边向上方连续对折N次,请从上到下打
印所有折痕的方向。例如 :

N = 1时,打印 :  down
N = 2时,打印 :  down down up

解析

可以用一张纸条自己折一下,会发现:

第一次折的时候,只有一条折痕,往里凸的,记为1down。
第二次折的时候,发现1down的上方为往里凸,记为2down,而下方为往外凸,记为2up。
第三次折的时候,发现2dowm的上方往里凸,记为3down,2down的下方往外凸,记为3up; 而2up的上方往里凸,
记为3down,2up的下方往外凸,记为3up;
从上面折痕可以发现新的折痕的上面总是为down,下面总是为up,所以我们可以构造出一颗二叉树,具体看下图
所以当前结点左子树总是down(true),右子树为up(false),所以我们只要按照中序遍历这颗二叉树就解决问题
了。
 class PaperFloding {//相当于中序遍历
 public:
     //打印的所有折痕方向的函数
     void printAllFolds(int N){
         printProcess(1,N,true);// 根节点的是down(第一次折的时候是往下的(往里凸))
     }
     
     void printProcess(int i, int N, bool down) {
         if(i > N){ //终止条件(相当于结点为null)
             return;
         }
         printProcess(i+1, N, true);// 相当于往左子树跑(因为左子树永远是down(下))
         string s =  down? "down " :"up ";
         cout << s;
         printProcess(i+1, N, false); //往右子树跑
     }
     
     
     void mains() {
         int N = 4;
         printAllFolds(N);
     }
 };

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值