《剑指offer》– 二叉树的下一个结点、对称二叉树、按之字性顺序打印二叉树、把二叉树打印成多行

《剑指offer》– 二叉树的下一个结点、对称二叉树、按之字性顺序打印二叉树、把二叉树打印成多行

一、二叉树的下一个结点:

1、题目:

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

2、解题思路:

分析二叉树的下一个节点,一共有以下情况:
(1)二叉树为空,则返回空;
(2)节点右孩子存在,则设置一个指针从该节点的右孩子出发,一直沿着指向左子结点的指针找到的叶子节点即为下一个节点;
(3)节点不是根节点。如果该节点是其父节点的左孩子,则返回父节点;否则继续向上遍历其父节点的父节点,重复第三步的判断,返回结果。

3、代码实现:

public class Test15 {
	
	 public TreeLinkNode GetNext(TreeLinkNode pNode){
		 
		 if(pNode == null){
			 return null;
		 }
		 if(pNode.right != null){
			 pNode = pNode.right;
			 while(pNode.left!=null){
				 pNode = pNode.left;
			 }
			 return pNode;
		 }
		 while(pNode.next!=null){
			 TreeLinkNode parent = pNode.next;
			 if(parent.left==pNode){
				 return parent;
			 }
			 pNode = pNode.next;
		 }
		 return null;
    }
}

class TreeLinkNode {
    int val;
    TreeLinkNode left = null;
    TreeLinkNode right = null;
    TreeLinkNode next = null;//指向改节点的父节点
    TreeLinkNode(int val) {
        this.val = val;
    }
}

 

二、对称二叉树:

1、题目:

请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

2、解题思路:

最简单的方式可以使用递归方式,但是使用递归无法挖掘这道题的价值,因此我们可以使用DFS和BFS。

3、代码实现:

(1)第一种:递归算法:

①只要pRoot.left和pRoot.right是否对称即可。

②左右节点的值相等且对称子树left.left,right.right ;left.rigth,right.left也对称。

public class Test16 {

	boolean isSymmetrical(TreeNode pRoot){
		if(pRoot == null) return true;
		return judge(pRoot.left,pRoot.right);
    }
	
	boolean judge(TreeNode leftNode,TreeNode rightNode){
		if(leftNode == null) return rightNode==null;
		if(rightNode == null) return false;
		if(leftNode.val != rightNode.val) return false;
		return judge(leftNode.left,rightNode.right) && judge(leftNode.right,rightNode.left);
	}
	
}

class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;

    }
}

(2)第二种方法:DFS深度优先遍历:

DFS使用stack来保存成对的节点,

①出栈的时候也是成对成对的:

若都为空,继续;

一个为空,返回false;

不为空,比较当前值,值不等,返回false;

②确定入栈顺序,每次入栈都是成对成对的,如left.left,right.right ;left.rigth,right.left

	boolean isSymmetrical2(TreeNode pRoot){
		//第二种方法:使用深度遍历:利用Stack实现
		if(pRoot==null) return true;
		
		Stack<TreeNode> stack = new Stack<>();
		//入栈和出栈都需要成对
		stack.push(pRoot.left);
		stack.push(pRoot.right);
		while(!stack.isEmpty()){
			//成对取出
			TreeNode right = stack.pop();
			TreeNode left = stack.pop();
			if(left==null && right==null) continue;
			if(left==null ||right==null) return false;
			if(left.val!=right.val) return false;
			
			//成对入栈:
			stack.push(left.left);
			stack.push(right.right);
			stack.push(right.left);
			stack.push(left.right);
		}
		return true;
	}

(3)第三种方法:BFS广度优先遍历:

BFS使用Queue来保存成对的节点,代码和上面极其相似

①出队的时候也是成对成对的 

若都为空,继续;

一个为空,返回false;

不为空,比较当前值,值不等,返回false;

②确定入队顺序,每次入队都是成对成对的,如left.left,right.right ;left.rigth,right.left。

	boolean isSymmetrical3(TreeNode pRoot){
		//第三种方法:使用广度遍历:使用队列实现
		if(pRoot==null) return true;
		Queue<TreeNode> queue = new LinkedList<>();
		
		queue.offer(pRoot.left);
		queue.offer(pRoot.right);
		
		while(!queue.isEmpty()){
			//成对取出
			TreeNode right = queue.poll();
			TreeNode left = queue.poll();
			
			if(left ==null && right ==null) continue;
			if(left==null || right==null) return false;
			if(left.val != right.val) return false;
			
			//成对插入
			queue.offer(left.left);
			queue.offer(right.right);
			queue.offer(left.right);
			queue.offer(right.left);
		}
		return true;
	}

 

三、按之字性顺序打印二叉树:

1、题目:

请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

2、解题思路:

利用栈先进后出的性质,创建两个栈分别存放奇数层与偶数层的节点。

3、代码实现:

public class Test18 {
	public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
		int layer = 1;
		//s1存奇数层节点:
		Stack<TreeNode> s1 = new Stack<TreeNode>();
		s1.push(pRoot);
		//s2存放偶数层节点:
		Stack<TreeNode> s2 = new Stack<TreeNode>();
		ArrayList<ArrayList<Integer>> list = new ArrayList<ArrayList<Integer>>();
		
		while(!s1.empty() || !s2.empty()){
			if(layer%2 !=0){
				//奇数层:
				ArrayList<Integer> temp = new ArrayList<Integer>();
				while(!s1.empty()){
					TreeNode node = s1.pop();
					if(node!=null){
						temp.add(node.val);
						s2.push(node.left);
						s2.push(node.right);
					}
				}
				if(!temp.isEmpty()){
					list.add(temp);
					layer++;
				}
			}else{
				//偶数层:
				ArrayList<Integer> temp = new ArrayList<Integer>();
				while(!s2.isEmpty()){
					TreeNode node = s2.pop();
					if(node!=null){
						temp.add(node.val);
						s1.push(node.right);
						s1.push(node.left);
					}
				}
				if(!temp.isEmpty()){
					list.add(temp);
					layer++;
				}
			}
		}
		return list;
    }
}

class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}

 

四、把二叉树打印成多行:

1、题目:

从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

2、代码实现:

public class Test19 {
	
	 ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
		 ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
		 if(pRoot == null){
			 return result;
		 }
		 
		 Queue<TreeNode> queue = new LinkedList<TreeNode>();
		 ArrayList<Integer> queueList = new ArrayList<Integer>();
		 queue.add(pRoot);
		 int start = 0 ,end = 1;

		 while(!queue.isEmpty()){
			 TreeNode current = queue.remove();
			 queueList.add(current.val);
			 start++;
			 if(current.left!=null){
				 queue.add(current.left);
			 }
			 if(current.right!=null){
				 queue.add(current.right);
			 }
			 if(start == end){
				 end = queue.size();
				 start=0;
				 result.add(queueList);
				 queueList = new ArrayList<Integer>();
			 }
			 
		 }
		 return result;
    }
}

class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/114693.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • JavaScript将数组拼接成一个字符串[通俗易懂]

    JavaScript将数组拼接成一个字符串[通俗易懂]将数组拼接成字符串,在JavaScript中,有两种方式。一种是Array对象提供的join()方法,另一种是Array对象提供的toString()方法。下面分别来介绍:join()定义和用法:join()方法用于把数组中的所有元素放入一个字符串。元素是通过指定的分隔符进行分隔的。用法:把数组中的所有元素放入一个字符串,默认以逗号分隔vararr=[‘sun’,’moon’,’start’]console.log(arr.join())//’sun,moon,start’

    2022年5月3日
    198
  • spring官网下载[通俗易懂]

    spring官网下载[通俗易懂]1、第一步:打开官网:http://projects.spring.io/2、第二步:点击“SPRINGFRAMEWORK”图片3、第三步:点击“小猫”图标4、第四步:拉到页面中部的位置,找到

    2022年7月1日
    33
  • 电商项目中的SPU和SKU概念

    电商项目中的SPU和SKU概念SPUSPU:StandardProductUnit,标准产品单位。概念:SPU是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。通俗点讲,属性值、特性相同的货品就可以称为一个SPUSPU是用来定位的例如:iphone8就是一个SPU,与商家、颜色、款式、套餐都无关SKUSKU:StockKeepingUnit,库存量单…

    2022年10月20日
    1
  • mysql截取_mysql截取字符串的方法[通俗易懂]

    mysql截取_mysql截取字符串的方法[通俗易懂]1、从左开始截取字符串left(str,length)说明:left(被截取字段,截取长度)例:selectleft(content,200)asabstractfrommy_content_t2、从右开始截取字符串right(str,length)说明:right(被截取字段,截取长度)例:selectright(content,200)asabstractfrommy_…

    2022年6月11日
    32
  • 远程桌面 指定端口_request获取ip地址

    远程桌面 指定端口_request获取ip地址iocp模型的tcp服务端若采用AcceptEx接受连接,在有客户端连接后要获取客户端的ip和端口信息流程:AcceptEx在工作线程收到客户端连接时复制listensocket的信息到新客户端的socketsetsockopt(pOverlapped->hSocket,SOL_SOCKET,SO_UPDATE_ACCEPT_CONTEXT,(cha…

    2022年9月1日
    2
  • android之存储篇_SQLite数据库_让你彻底学会SQLite的使用「建议收藏」

    SQLite最大的特点是你可以把各种类型的数据保存到任何字段中,而不用关心字段声明的数据类型是什么。例如:可以在Integer类型的字段中存放字符串,或者在布尔型字段中存放浮点数,或者在字符型字段中存放日期型值。但有一种情况例外:定义为INTEGERPRIMARYKEY的字段只能存储64位整数,当向这种字段保存除整数以外的数据时,将会产生错误。另外,SQLite在解析CR…

    2022年3月10日
    30

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号