后序遍历

permutations II(全排列 2)

∥☆過路亽.° 提交于 2020-01-23 01:19:52
题目要求 Given a collection of numbers that might contain duplicates, return all possible unique permutations. For example, [1,1,2] have the following unique permutations: [ [1,1,2], [1,2,1], [2,1,1] ] 对于其基础题PermutationsI请参考我的 另一篇博客 这里添加的难度在于,排列组合的数字中可能存在重复。这就需要想方法,将结果集中重复的结果删去。而这里,我参考了另一名答题者的答案, 在试图将数字添入结果集中时,就判断会不会产生重复的结果 ,从而使避免重复。 PermutationsI也可以使用此方法。。 代码和解析 这里采用了递归的思路。 避免重复的核心思路在于 ,使用一个boolean数组来代表当前的数值是否已经被使用过。当前的值如果已经被使用过,则继续判断下一个数值。如果当前的值为重复值,则只要前面的值没有被使用过,则当前值就不可以被使用。这样确保了只有第一个出现的重复值可以算进结果集,后序重复的情况不会被添加进结果集。 例如,假设输入的数组为 [1,1,2] 。则当第一个1被添加进结果集时,可以继续使用第二个1作为元素添加进结果集从而生成112。同理

Morris遍历遍历二叉树

孤街浪徒 提交于 2020-01-22 22:51:29
遍历二叉树的递归方法使用了函数栈,非递归方法使用了申请的栈, 两者的额外空间都与树的高度有关,所以空间复杂度为O(h),h为二叉树的高度。 可以使用二叉树叶子节点中大量指向null的指针实现空间复杂度O(1)的遍历。 Morris遍历的实质就是避免使用栈结构,让下层到上层有指针, 具 体是通过让底层节点指向null的空闲指针指回上层的某个节点,从而完成下层到上层的移动。 先序中序后序主要基于两个主要步骤,然后输出的位置有所不同,以中序遍历为例。 中序遍历: 1、假设当前子树的头节点为h,让h的左子树中最右节点的right指针指向h, 然后h的左子树继续步骤1的处理过程,直到遇到某一个节点没有左子树时记为node,进入步骤2。 2、从node开始通过每个节点的right指针进行移动并以此打印,假设移动到的节点为cur。 对每一个cur节点都判断cur节点的左子树中最右节点是否指向cur。 Ⅰ 如果是,令cur节点的左子树中最右节点的right指针指向null,即恢复树的本来面貌, 然后打印cur,继续通过cur的right指针移动到下一个节点。重复步骤2。 Ⅱ 如果不是,以cur为头的子树重回步骤1执行。 public void morrisIn(TreeNode root) { if (root == null) return; TreeNode cur1 = root;

前序与中序遍历序列构造二叉树 中序与后序遍历序列构造二叉树

对着背影说爱祢 提交于 2020-01-22 07:22:29
105. 从前序与中序遍历序列构造二叉树 根据前序遍历和中序遍历,我们可以发现前序遍历的第一个元素就为根元素,在中序遍历中找到这个元素,那么中序遍历中左边为根元素的左子树,右边为右子树,依次递归。 /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { public TreeNode buildTree(int[] preorder, int[] inorder) { int len1 = preorder.length-1; int len2 = inorder.length-1; TreeNode root = bulidTree(preorder,0,len1,inorder,0,len2); return root; } public TreeNode bulidTree(int[] preorder, int start1,int end1,int[] inorder,int start2, int end2){ if(start1>end1 || start2>end2){ return

Morris 遍历二叉树

跟風遠走 提交于 2020-01-21 08:37:47
Morris Traversal 方法实现前序、中序以及后序遍历二叉树。相比使用栈或者递归(也是通过栈空间)方法,Morris 方法可以在空间复杂度为 O(1) ,时间复杂度为 O(n) 的条件下实现对二叉树的遍历。 前序遍历 如果当前节点左孩子 cur->left 为空,输出当前节点 cur 并指向右孩子 cur->right。 如果当前节点左孩子 cur->left 不为空,那么在当前节点的左子树中找出前驱节点 pre,也就是左子树中最大的点。 如果前驱节点的右孩子 pre->right 为空,那么将右孩子指向当前节点。 输出当前节点 。当前节点更新为当前节点的左孩子。 如果前驱节点的右孩子 pre->right 不为空,也就是指向当前节点。重新将右孩子设为空。当前节点更新为当前节点的右孩子。 重复 1、2 直到当前节点为空。 class Solution { public: vector<int> preorderTraversal(TreeNode* root) { TreeNode* cur = root; TreeNode* pre = NULL; vector<int> result; while(cur!=NULL){ if (cur->left == NULL){ result.push_back(cur->val); cur = cur->right;

二叉树遍历

天大地大妈咪最大 提交于 2020-01-21 07:54:32
二叉树遍历最简单的就是递归了。因为递归实质上是栈存了一些中间值,所以我们可以使用stack实现迭代版的遍历。 中序遍历 步骤: 首先将root节点作为当前节点。 1.如果当前节点不为空,压入当前节点。将左节点作为当前节点。 2.否则弹出栈顶节点作为当前节点,输出当前节点。 3.如果右节点不为空,右节点作为当前节点。 4.否则将当前节点置为空。 重复1、2、3、4直到栈为空。 void InorderTraversal(TreeNode *root){ if(!root)return; TreeNode *node=root; stack<TreeNode*> mystk; while(node||mystk.size()){ while(node){ mystk.push(node); node=node->left; } node=mystk.top(); mystk.pop(); cout<<node->val<<'\t'; if(node->right){ node=node->right; }else{ node=NULL; } } } 前序遍历 前序遍历和中序遍历差不多,只是输出节点值的时机不同。 步骤: 以root节点作为当前节点 1.如果当前节点不为空,将当前节点压入栈,同时输出当前节点。并将左节点作为当前节点。 2.否则弹出栈顶作为当前节点。 3.如果右节点不为空

二叉树非递归遍历的实现

◇◆丶佛笑我妖孽 提交于 2020-01-21 07:30:58
/*二叉树的遍历之非递归实现*/ /*非递归实现采用栈去模拟实现*/ //参考代码http://blog.csdn.net/ns_code/article/details/12977901 节点访问 1 void visit(BTNode*b) 2 { 3 //输出格式依赖于elementType 4 printf("%c",b->data); 5 } 先序遍历 根据先序遍历的顺序,先访问根节点,再访问左子树,后访问右子树,而对于每个子树来说, 又按照同样的访问顺序进行遍历。非递归的实现思路如下: 对于任一节点P, 1)输出节点P,然后将其入栈,再看P的左孩子是否为空; 2)若P的左孩子不为空,则置P的左孩子为当前节点,重复1)的操作; 3)若P的左孩子为空,则将栈顶节点出栈,但不输出,并将出栈节点的右孩子置为当前节点, 看其是否为空; 4)若不为空,则循环至1)操作; 5)如果为空,则继续出栈,但不输出,同时将出栈节点的右孩子置为当前节点,看其是否 为空,重复4)和5)操作; 6)直到当前节点P为NULL并且栈空,遍历结束。 void PreOrder(BTree bt) { PSTACK stack=NULL; stack=CreateStack(); //创建一个空栈 elementType node_pop; //用来保存出栈节点 elementType pCur=bt;

浅谈数据结构-二叉树

浪子不回头ぞ 提交于 2020-01-20 17:35:34
二叉树是树的特殊一种,具有如下特点:1、每个结点最多有两颗子树,结点的度最大为2。2、左子树和右子树是有顺序的,次序不能颠倒。3、即使某结点只有一个子树,也要区分左右子树。 一、特殊的二叉树及特点 1、斜树 所有的结点都只有左子树(左斜树),或者只有右子树(右斜树)。这就是斜树,应用较少 2、满二叉树 所有的分支结点都存在左子树和右子树,并且所有的叶子结点都在同一层上,这样就是满二叉树。就是完美圆满的意思,关键在于树的平衡。 根据满二叉树的定义,得到其特点为: 叶子只能出现在最下一层。 非叶子结点度一定是2. 在同样深度的二叉树中,满二叉树的结点个数最多,叶子树最多。 3、完全二叉树 对一棵具有n个结点的二叉树按层序排号,如果编号为i的结点与同样深度的满二叉树编号为i结点在二叉树中位置完全相同,就是完全二叉树。满二叉树必须是完全二叉树,反过来不一定成立。 其中关键点是按层序编号,然后对应查找。 在上图中,树1,按层次编号5结点没有左子树,有右子树,10结点缺失。树2由于3结点没有字数,是的6,7位置空挡了。树3中结点5没有子树。 上图就是一个完全二叉树。 结合完全二叉树定义得到其特点: 叶子结点只能出现在最下一层(满二叉树继承而来) 最下层叶子结点一定集中在左 部连续位置。 倒数第二层,如有叶子节点,一定出现在右部连续位置。 同样结点树的二叉树,完全二叉树的深度最小

二叉树的遍历与建立

主宰稳场 提交于 2020-01-20 07:00:03
内容简介 本次作业在二叉树的建立方面,我使用了先序输入的方法来建立,即使用递归来实现。在遍历输出方面,有先序、中序、和后序三种。 其中,本次建立二叉树时,输入结束的条件为输入数据为0。 本程序创建的二叉树如下: 相关代码: include using namespace std; typedef struct node//创建节点结构 { char data;//数据元素 struct node Lchild;//指向左孩子结点 struct node Rchild;//指向右孩子结点 }BinNode,*BinTree; void CreateTree(BinTree &T);//递归法建立二叉树 void PreOrder(BinTree &T);//先序遍历 void InOrder(BinTree &T);//中序遍历 void PostOrder(BinTree &T);//后序遍历 int main() { BinTree T; cout<<"请输入二叉树节点:"; CreateTree(T); cout<<"先序遍历:"; PreOrder(T); cout<<endl; cout<<"中序遍历:"; InOrder(T); cout<<endl; cout<<"后序遍历:"; PostOrder(T); cout<<endl; return 0; } void

树的建立及遍历

天涯浪子 提交于 2020-01-20 05:39:08
内容简介 本次作业在建立二叉树方面,使用了先序输入建立的方法(递归实现)。在遍历输出方面,有先序/中序/后序遍历三种。 其中,本次建立二叉树时,输入结束的条件为输入数据为'.'。 用链式结构存储,生成的树大体如上图 二叉树的建立 树的结构体 typedef struct dfs *tree; struct dfs { tree lchild ,rchild; char data; }; 按先序输入建立二叉树 tree DFS() { char m; cin>>m; tree father; father=new struct dfs; if(m=='.') father = NULL; else { father->data=m; father->lchild=DFS(); father->rchild=DFS(); } return father; } 这里用递归法创建树,每次递归返回父节点指针,当碰到表示为空的'.'时,使父节点为空。先序输入建立二叉树是从根节点出发, 先建立每个父节点的左孩子,当没有左孩子时依次返回建立每个父节点右孩子,直至最后一个右孩子被创建,返回所有父节点, 生成一棵二叉树。 二叉树的遍历 1.先序遍历 思路:先访问根结点 -> 遍历左子树 -> 遍历右子树;先访问根结点 void frontorder(tree root) { if(root) {

剑指offer——java刷题总结【三】

最后都变了- 提交于 2020-01-19 03:36:07
Note 题解汇总: 剑指offer题解汇总 代码地址: Github 剑指offer Java实现汇总 点击目录中的题名链接可直接食用题解~ 有些解法博文中未实现,不代表一定很难,可能只是因为博主太懒```(Orz) 如果博文中有明显错误或者某些题目有更加优雅的解法请指出,谢谢~ 目录 题号 题目名称 21 栈的压入、弹出序列 22 从上往下打印二叉树 23 二叉搜索树的后序遍历序列 24 二叉树中和为某一值的路径 25 复杂链表的复制 26 二叉搜索树与双向链表 27 字符串的排列 28 数组中出现次数超过一半的数字 29 最小的K个数 30 连续子数组的最大和 正文 21、栈的压入、弹出序列 题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的) 题目分析 解法一: 设置一个指向pop数组的index指针,遍历push数组,针对每一个遍历值做如下操作: 1、将当前遍历值压入栈中; 2、查看栈顶元素和pop数组的当前弹出值是否相等,如果相等则模拟出栈操作,将stack的栈顶元素弹出,并对pop数组的指针进行后移