剑指Offer面试题(第十七天)面试题27、28、29

* 面试题27:二叉树的镜像


     * 题目:请完成一个函数,输入一颗二叉树,该函数输出它的镜像。
     * 二叉树节点定义:
     * struct BinaryTreeNode{
     *     int m_nValue;
     *     BinaryTreeNode* m_pLeft;
     *     BinaryTreeNode* m_pRight;
     * }
     * 
     * 
     * 思路:递归的思想
     * 从根节点开始,判断是否有左子树或者右子树,然后交换两个子树;
     * 然后再继续判断左子树,看是否有左右子树,有的话交换左右子树,
     * 。。。。。。直到为空或者为叶子节点时,返回即可。
     * 这是一个迭代的过程: 1>  结束内容:if()return;
     *                  2>  数据处理内容:change(left<-->right)
     *                  3>  递归调用:若左子树||右子树不为空,则交换左右子树
     *            
     * 输出二叉树,使用先序遍历的方式遍历二叉树进行输出。
 

package Test;

import Test.No26isSubStruct.BinaryTreeNode;

public class No27BinaryTreeMirror {

	/*
	 * 面试题27:二叉树的镜像
	 * 题目:请完成一个函数,输入一颗二叉树,该函数输出它的镜像。
	 * 二叉树节点定义:
	 * struct BinaryTreeNode{
	 * 	int m_nValue;
	 * 	BinaryTreeNode* m_pLeft;
	 * 	BinaryTreeNode* m_pRight;
	 * }
	 * 
	 * 
	 * 思路:递归的思想
	 * 从根节点开始,判断是否有左子树或者右子树,然后交换两个子树;
	 * 然后再继续判断左子树,看是否有左右子树,有的话交换左右子树,
	 * 。。。。。。直到为空或者为叶子节点时,返回即可。
	 * 这是一个迭代的过程: 1>  结束内容:if()return;
	 * 				 2>  数据处理内容:change(left<-->right)
	 * 				 3>  递归调用:若左子树||右子树不为空,则交换左右子树
	 *            
	 * 输出二叉树,使用先序遍历的方式遍历二叉树进行输出。
	 * 
	 * */
	
	static class BinaryTreeNode{
		int val;
		BinaryTreeNode left;
		BinaryTreeNode right;
		
		BinaryTreeNode(int val){
			this.val = val;
		}
		
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		No27BinaryTreeMirror b = new No27BinaryTreeMirror();
		
		BinaryTreeNode root1 = new BinaryTreeNode(8);
		BinaryTreeNode one = new BinaryTreeNode(8);
		BinaryTreeNode two = new BinaryTreeNode(7);
		BinaryTreeNode three = new BinaryTreeNode(9);
		BinaryTreeNode four = new BinaryTreeNode(2);
		BinaryTreeNode five = new BinaryTreeNode(4);
		BinaryTreeNode six = new BinaryTreeNode(7);
		
		root1.left = one;
		root1.right = two;
		one.left = three;
		one.right = four;
		two.left = null;
		two.right = null;
		three.left = null;
		three.right = null;
		four.left = five;
		four.right = six;
		five.left = null;
		five.right = null;
		six.left = null;
		six.right = null;
		

		System.out.println("以先序遍历的方式输出二叉树:");
		if(root1 != null) {
			PrintBinaryTree(root1);
			//未通过b调用PrintBinaryTree()函数,所以该函数要设置为static形式
		}
		
		b.BinaryTreeMirror(root1);
		//通过对象b调用BinaryTreeMirror()函数,所以该函数不用static
		
		
		System.out.println("以先序遍历方式输出二叉树的镜像:");
		if(root1 != null) {
			PrintBinaryTree(root1);
			//未通过b调用PrintBinaryTree()函数,所以该函数要设置为static形式
		}
	}
	
	
	//输出二叉树节点值   根左右(先序遍历二叉树)
	public static void PrintBinaryTree(BinaryTreeNode root1) {
		System.out.println(root1.val);
		if(root1.left == null && root1.right == null) {
			return;
		}
		if(root1.left != null) {
			PrintBinaryTree(root1.left);
		}
		if(root1.right != null) {
			PrintBinaryTree(root1.right);
		}
		
		
	}

	//对二叉树求其镜像
	public void BinaryTreeMirror(BinaryTreeNode root1) {
		// TODO Auto-generated method stub
		
		//根节点不变,根结点的左子树和右子树进行交换,再将左子树的左右子树进行交换,右子树的左右子树进行交换。
		//以此类推,一直找下去,直到左右子树为叶子节点(左子树+右子树为空)
		
		if(root1 == null) {
			return;
		}
		if(root1.left == null && root1.right == null) {
			return;
		}
		
		//交换左右子树
		BinaryTreeNode tempNode = root1.left;
		root1.left = root1.right;
		root1.right = tempNode;
		
		//若不为空则交换左右子树
		if(root1.left != null) {
			BinaryTreeMirror(root1.left);
		}
		if(root1.right != null) {
			BinaryTreeMirror(root1.right);
		}
		
		
		
	}

}

 * 面试题28:对称的二叉树


     * 题目:请实现一个函数,用来判断一颗二叉树是不是对称的。
     * 如果一棵二叉树和它的镜像一样,那么它是对称的。
     * 例如:8->(left)2  8->(right)2  对称的
     *        8->(left)3  8->(right)2 非对称的
     * 
     * 
     * 思路:使用递归的思想
     * 使用两个相同的二叉树,从根节点开始,比较其左右子树的根节点值是否相等,不想等,返回false;
     * 相等的话,继续比较  看是否左节点值 = 右节点值并且右节点值 = 左节点值
     * 。。。。。。继续比较,直到比较到为空  或者是不想等,或者是叶子节点为止,同时到达叶子节点,则证明是对称的,返回true;
     * 但是若一个到了叶子节点,但是另一个没有到达,证明不是对称的 ,返回false
     * 递归内容:1>结束内容(条件):若是两个都为空指针,则返回true
     *                         若两个其中一个为空指针(到达叶子节点),则返回false
     *                         若是两个值不想等,则返回false
     *           2>数据库处理内容: 无(判断两个值是否相等)
     *           3>递归调用内容:将左子树,右子树    或者    右子树,左子树再进行判断是否对称,重复之前的操作。

package Test;

import Test.No27BinaryTreeMirror.BinaryTreeNode;

public class No28isSymmetrical {

	/*
	 * 面试题28:对称的二叉树
	 * 题目:请实现一个函数,用来判断一颗二叉树是不是对称的。
	 * 如果一棵二叉树和它的镜像一样,那么它是对称的。
	 * 例如:8->(left)2  8->(right)2  对称的
	 * 	   8->(left)3  8->(right)2 非对称的
	 * 
	 * 
	 * 思路:使用递归的思想
	 * 使用两个相同的二叉树,从根节点开始,比较其左右子树的根节点值是否相等,不想等,返回false;
	 * 相等的话,继续比较  看是否左节点值 = 右节点值并且右节点值 = 左节点值
	 * 。。。。。。继续比较,直到比较到为空  或者是不想等,或者是叶子节点为止,同时到达叶子节点,则证明是对称的,返回true;
	 * 但是若一个到了叶子节点,但是另一个没有到达,证明不是对称的 ,返回false
	 * 递归内容:1>结束内容(条件):若是两个都为空指针,则返回true
	 * 						若两个其中一个为空指针(到达叶子节点),则返回false
	 * 						若是两个值不想等,则返回false
	 * 		  2>数据库处理内容: 无(判断两个值是否相等)
	 * 		  3>递归调用内容:将左子树,右子树    或者    右子树,左子树再进行判断是否对称,重复之前的操作。
	 * */
	
	
	static class BinaryTreeNode{
		int val;
		BinaryTreeNode left;
		BinaryTreeNode right;
		
		BinaryTreeNode(int val){
			this.val = val;
		}
		
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		No28isSymmetrical s = new No28isSymmetrical();
		
		BinaryTreeNode root1 = new BinaryTreeNode(8);
		BinaryTreeNode one = new BinaryTreeNode(8);
		BinaryTreeNode two = new BinaryTreeNode(7);
		BinaryTreeNode three = new BinaryTreeNode(9);
		BinaryTreeNode four = new BinaryTreeNode(2);
		BinaryTreeNode five = new BinaryTreeNode(4);
		BinaryTreeNode six = new BinaryTreeNode(7);
		
		root1.left = one;
		root1.right = two;
		one.left = three;
		one.right = four;
		two.left = null;
		two.right = null;
		three.left = null;
		three.right = null;
		four.left = five;
		four.right = six;
		five.left = null;
		five.right = null;
		six.left = null;
		six.right = null;
		
		if(s.isSymmetrical(root1)) {
			System.out.println("二叉树是对称的!");
		}
		else {
			System.out.println("二叉树不是对称的!!!!");
		}
		
		
		
		 
	}
	
	//比较二叉树的左右子树的值是否相等   将二叉树的两个参数传递过去
	public boolean isSymmetrical(BinaryTreeNode root1) {
		// TODO Auto-generated method stub
		return isSymmertical(root1,root1);
	}

	//比较二叉树左右子树是否相等
	private boolean isSymmertical(BinaryTreeNode root1, BinaryTreeNode root2) {
		// TODO Auto-generated method stub
		//若左右子树同时到达末尾,则是对称的
		if(root1 == null && root2 == null) {
			return true;
		}
		//若只有一侧到达末尾,证明不是对称的,一侧有数据,另一侧已经到了底部
		if(root1 == null ||root2 == null) {
			return false;
		}
		//若两个值不等
		if(root1.val != root2.val) {
			return false;
		}
		//若两个值相等,则返回一个左子树,一个右子树对比的 + 一个右子树,一个左子树对比的
		return isSymmertical(root1.left,root2.right) && isSymmertical(root1.right,root2.left);
		
		
		
	}
	
	

}

*面试题29:顺时针打印矩阵

*题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。

例如:如下矩阵   1  2  3  4

                            5  6  7  8

                             9  10  11 12

                            13  14  15  16      依次 打印出数字:1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10


     * 思路:用一个循环来打印矩阵,每次打印矩阵中的一圈
     *     clockwisely   顺时针地    matrix   矩阵
     *     循环停止条件 : columns<=start*2  && rows<=start*2    5<=2*2;6<=2*2;6<=3*2
     *     
     *     其中  startX  起始行号———   startY 起始列号|
     *            endX    结束行号———    endY  结束列号|
     *         columns  行数———       rows  列数|
 

package Test;

public class No29PrintMatrixClockwisely {

	/*
	 * 面试题29:逆时针打印矩阵
	 * 题目:输入一个矩阵,按照从外向里以顺时针的顺序一次打印出每一个数字。
	 * 例如:输入 1,2,3,4(第一行),5,6,7,8(第二行),9,10,11,12(第三行),13,14,15,16
	 * 
	 * 		  
	 * 思路:用一个循环来打印矩阵,每次打印矩阵中的一圈
	 *     clockwisely   顺时针地    matrix   矩阵
	 *     循环停止条件 : columns<=start*2  && rows<=start*2    5<=2*2;6<=2*2;6<=3*2
	 *     
	 *     其中  startX  起始行号———   startY 起始列号|
	 *     	   endX    结束行号———    endY  结束列号|
	 *         columns  行数———       rows  列数|
	 *         
	 * */
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		No29PrintMatrixClockwisely p = new No29PrintMatrixClockwisely();
		
		int[][] numbers = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
		
		int columns = 4;
		int rows = 4;
		
		p.PrintMatrixClockwisely(numbers, columns, rows);
		
		
		
		
	}
	
	
	public void PrintMatrixClockwisely(int[][] numbers,int columns,int rows){

	        if(numbers == null || columns <= 0 || rows <= 0){

	                return;

	        }

	        int startX = 0;

	        int startY = 0;

	       //循环结束条件   columns<=start*2  && rows<=start*2

	        while(columns > startX*2 && rows > startY*2){

	               //循环打印矩阵,打印一圈

	                PrintMatrixInCircle(numbers,columns,rows,startX,startY);

	                ++startX;
	                ++startY;

	        }

	}

	//打印矩阵中的一圈

	public void PrintMatrixInCircle(int[][] numbers,int columns,int rows,int startX,int startY){

	        int endX = columns - 1 - startX;//列   startX

	        int endY = rows - 1 - startY;   //行   startY

	        

	        //第一步:从左到右  行不变  列变  小数开始到大数

	        for(int i = startY;i <= endY;i ++){
	            
	            System.out.println(numbers[startX][i]+"  ");
	        }
	        
	        //第二步:从上到下  列不变  行变   小数开始到大数
	        if(startY < endY){
	            for(int i = startX+1;i <= endX;i ++){
	                System.out.println(numbers[i][endY]+"  ");
	            }
	        
	        }

	      //第三步:从右到左  行不变,列变   从大数开始到小数  
	        if(startY < endY && startX < endX){
	            for(int i = endY-1;i >= startY;i --){
	                System.out.println(numbers[endX][i]+"  ");
	            } 
	        }

	        //第四步:从下到上  列不变,行变   从大到小
	        if(startY < endY && startX < endX - 1){
	            for(int i = endX - 1;i >= startX+1;i--){
	                System.out.println(numbers[i][startY]+"  ");
	            }
	        }
	}
	
}

猜你喜欢

转载自blog.csdn.net/weixin_43137176/article/details/89179734