您现在的位置是:首页 >技术交流 >leetCode. Populating Next Right Pointers in Each Node;Binary Tree Level Order Traversal;网站首页技术交流
leetCode. Populating Next Right Pointers in Each Node;Binary Tree Level Order Traversal;
参考资料:《程序员代码面试指南》第二版——二叉树的按层打印与ZigZag打印
116. Populating Next Right Pointers in Each Node
You are given a perfect binary tree where all leaves are on the same level, and every parent has two children. The binary tree has the following definition:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.
Initially, all next pointers are set to NULL.
Example 1:
Input: root = [1,2,3,4,5,6,7]
Output: [1,#,2,3,#,4,5,6,7,#]
Explanation: Given the above perfect binary tree (Figure A), your function should populate each next pointer to point to its next right node, just like in Figure B. The serialized output is in level order as connected by the next pointers, with ‘#’ signifying the end of each level.
思路:宽度优先遍历
关键点:如何知道什么时候换行
- 方法一:使用两个node变量last, nlast 记录当前行的最右节点、下一行的最右节点。具体地,当遍历到当前行的最右节点时, cur==last is true, then update last as nlast, and go to the next level.
- 方法二:设计一个新类MyQueue, 内部是链表,对于connect函数的贡献在于 在收录下一行结点的同时,可以计算当前行的结点数,即 queue.size。整个算法的优势体现在,仅仅使用了有限几个变量就可以完成。
public Node connect(Node root)
{
if(root==null)
{
return null;
}
Node pre=null;
Node cur=root;
Node last = root;
Node nlast = null;
Queue<Node> queue = new LinkedList<>();
queue.add(cur);
while(!queue.isEmpty())
{
cur = queue.poll();
if(cur.left!=null)
{
queue.add(cur.left);
nlast=cur.left;
}
if(cur.right!=null)
{
queue.add(cur.right);
nlast=cur.right;
}
if(cur==last)
{
if(pre!=null)
{
pre.next=cur;
pre=null;
}
cur.next=null;
last=nlast;
nlast=null;
}else{
if(pre!=null)
{
pre.next=cur;
}
pre=cur;
}
}
return root;
}
方法二的实现:
package topinterviewquestions;
public class Problem_0116_PopulatingNextRightPointersInEachNode {
public static class Node {
public int val;
public Node left;
public Node right;
public Node next;
}
// the trainer provides a more difficult solution whose advantage is that only several vars are required.
// use class MyQueue to arrange 'next' pointers of all the nodes in the current line
public static class MyQueue {
public Node head;
public Node tail;
public int size;
public MyQueue() {
head = null;
tail = null;
size = 0;
}
public boolean isEmpty() {
return size == 0;
}
public void offer(Node cur) {
size++;
if (head == null) {
head = cur;
tail = cur;
} else {
tail.next = cur;
tail = cur;
}
}
public Node poll() {
size--;
Node ans = head;
head = head.next;
ans.next = null;// !!
return ans;
}
}
public static Node connect(Node root) {
if (root == null) {
return root;
}
MyQueue queue = new MyQueue();
queue.offer(root);
while (!queue.isEmpty()) {
// 第一个弹出的节点
Node pre = null;
int size = queue.size;// #nodes in the current line
for (int i = 0; i < size; i++) {
Node cur = queue.poll();// by default, cur.next=null once it is popped
if (cur.left != null) {
queue.offer(cur.left);
}
if (cur.right != null) {
queue.offer(cur.right);
}
if (pre != null) {
pre.next = cur;
}
pre = cur;
}
}
return root;
}
}
102 Binary Tree level order traversal
- Binary Tree Level Order Traversal
Given the root of a binary tree, return the level order traversal of its nodes’ values. (i.e., from left to right, level by level).
Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: [[3],[9,20],[15,7]]
思路:宽度遍历二叉树,把非空的子节点依次装进Queue中,用整型变量size记录当前层有多少结点。在开始当前行之前,预备List<Integer>
用于记录当前层。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ans = new ArrayList();
if(root==null)
{
return ans;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty())
{
int size=queue.size();
List<Integer> curLevel = new ArrayList<>();
for(int i=0;i<size;i++)
{
TreeNode cur = queue.poll();
curLevel.add(cur.val);
if(cur.left!=null)
{
queue.add(cur.left);
}
if(cur.right!=null)
{
queue.add(cur.right);
}
}
ans.add(curLevel);
}
return ans;
}
}
Zigzag
思路:框架和上面按层打印二叉树一样,用整型变量size表示一行节点数,用for循环“打印”当前行,与此同时把处于当前行的结点的孩子,也就是下一行放入到LinkedList容器dq中。
细节上需要注意:根据布尔型变量isHead决定打印、弹出方向;
对于isHead的每一个取值,LinkedList容器dq都要有从一端加node,从另外一端删node,先加左孩子还是先加右孩子。方向isHead一变,dq的增删结点方向、加左右孩子的顺序都要随之改变。
say,
if isHead=true, then we can choose “pollFirst, addLast(cur.left), then addLast(cur.right)”
if isHead=false, then we can choose “pollLast, addFirst(cur.right), then addFirst(cur.left)”
say,
if isHead=true, then we can choose “pollFirst, addLast(cur.left), then addLast(cur.right)”
if isHead=false, then we can choose “pollLast, addFirst(cur.right), then addFirst(cur.left)”
总之,要一一对应。
方法一:用size记录当前行的节点数,一次打印一行。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
// <-- // l,r
// -->
// <--
List<List<Integer>> ans = new ArrayList<>();
if(root==null)
{
return ans;
}
LinkedList<TreeNode> dq = new LinkedList<>();
dq.addFirst(root);
boolean isHead = true;
while(!dq.isEmpty())
{
int size = dq.size();
List<Integer> curLevel = new ArrayList<>();
for(int i=0;i<size;i++)
{
if(isHead)
{
TreeNode cur = dq.pollFirst();
curLevel.add(cur.val);
if(cur.left!=null)
{
dq.addLast(cur.left);
}
if(cur.right!=null)
{
dq.addLast(cur.right);
}
}else {
TreeNode cur = dq.pollLast();
curLevel.add(cur.val);
if(cur.right!=null)
{
dq.addFirst(cur.right);
}
if(cur.left!=null)
{
dq.addFirst(cur.left);
}
}
}// end for
ans.add(curLevel);
isHead=!isHead;
}
return ans;
}
}
方法二:使用两个TreeNode变量标记 当前行的结束和下一行的结束。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root)
{
List<List<Integer>> ans = new ArrayList<>();
if(root==null)
{
return ans;
}
LinkedList<TreeNode> dq = new LinkedList<>();
dq.addFirst(root);
boolean isHead = true;
TreeNode last = root;
TreeNode nlast = null;
TreeNode cur = null;
int level=0;
while(!dq.isEmpty())
{
if(isHead)
{
cur = dq.pollFirst();
if(nlast==null)
{
ans.add(new ArrayList<>());
}
ans.get(level).add(cur.val);
if(cur.left!=null)
{
dq.addLast(cur.left);
nlast = nlast==null?cur.left:nlast;
}
if(cur.right!=null)
{
dq.addLast(cur.right);
nlast = nlast==null?cur.right:nlast;
}
}else {
cur = dq.pollLast();
if(nlast==null)
{
ans.add(new ArrayList<>());
}
ans.get(level).add(cur.val);
if(cur.right!=null)
{
dq.addFirst(cur.right);
nlast = nlast==null?cur.right:nlast;
}
if(cur.left!=null)
{
dq.addFirst(cur.left);
nlast = nlast==null?cur.left:nlast;
}
}
if(cur==last)
{
last = nlast;
nlast = null;
isHead=!isHead;
level++;
}
}// end while
int n=ans.size();
List<List<Integer>> res = new ArrayList<>();
for(int i=0;i<n;i++)// drop some empty lists at the end of ans
{
if(ans.get(i).isEmpty())
{
break;
}
res.add(ans.get(i));
}
return res;
}
}