《剑指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;} }?
總結
以上是生活随笔為你收集整理的《剑指offer》-- 二叉树的下一个结点、对称二叉树、按之字性顺序打印二叉树、把二叉树打印成多行的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《剑指offer》-- 复杂链表的复制、
- 下一篇: 《剑指offer》-- 序列化二叉树、二