leetCode. Populating Next Right Pointers in Each Node;Binary Tree Level Order Traversal;

文章详细介绍了如何对完美二叉树进行按层打印和ZigZag打印。提供了两种方法实现节点间的next指针连接,一种利用两个节点变量记录行边界,另一种设计自定义队列。同时,给出了二叉树水平遍历的解决方案。文章还讨论了在遍历过程中如何切换打印方向以及维护节点连接的逻辑。
摘要由CSDN通过智能技术生成

参考资料:《程序员代码面试指南》第二版——二叉树的按层打印与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

  1. 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;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值