算法---队列+宽搜
1.N叉树的层序遍历
题目链接:429. N 叉树的层序遍历 - 力扣(LeetCode)
题目解析:返回N叉树层序遍历的结果,层序遍历就是从上到下,一层一层得遍历,每一层的遍历从左往右开始
算法讲解:队列
首先创建一个队列,此时开始层序遍历N叉树,一层一层得遍历,将每一层遍历的结果存储到队列中,在进行下一层的遍历时,要将上一层遍历的结果记录到结果集中,也就是要对存储到队列中的节点进行出队列的操作,每次将一个节点出队列之后,就要将出队列的节点的孩子节点存储到队列中
此时可能队列中会存储到了N叉树中不同层次的节点,因为要区分不同层的节点,所以对上一层队列中存储的节点进行出队列操作时,就要对上一层入队列的节点的个数进行记录
代码实现:
class Solution {public List<List<Integer>> levelOrder(Node root) {Queue<Node> q = new LinkedList<>();List<List<Integer>> ret = new ArrayList<>();if(root==null) return ret;q.offer(root);while(!q.isEmpty()){int sz = q.size();List<Integer> tmp = new ArrayList<>();for(int i=0;i<sz;i++){Node head = q.poll();tmp.add(head.val);//将出队列节点的孩子节点入队列for(Node child:head.children){if(child!=null){q.offer(child);}}}ret.add(tmp);}return ret;}
}
2.二叉树的锯齿形层序遍历
题目链接:103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode)
题目解析:返回二叉树进行锯齿形遍历的结果
算法讲解:队列+宽搜
这道题的解题思路和上一题的思路一模一样,只不过在记录奇数层的结果时,要先对该层的遍历结果逆序之后,再将该该层的遍历结果加入到最终的结果中
此时可以创建一个boolean类型的变量或者一个int类型的变量来判断该层是偶数层还是奇数层
代码实现:
class Solution {public List<List<Integer>> zigzagLevelOrder(TreeNode root) {Queue<TreeNode> q = new LinkedList<>();List<List<Integer>> ret = new LinkedList<>();if(root==null) return ret;q.offer(root);int flag=1;while(!q.isEmpty()){//sz是某一层的节点个数int sz=q.size();List<Integer> tmp = new LinkedList<>();for(int i=0;i<sz;i++){TreeNode top = q.poll();if(top.left!=null) q.offer(top.left);if(top.right!=null) q.offer(top.right);tmp.add(top.val);}if(flag%2==0){Collections.reverse(tmp);}ret.add(tmp);flag++;}return ret;}
}
3.二叉树的最大宽度
题目链接:662. 二叉树最大宽度 - 力扣(LeetCode)
题目解析:返回该二叉树的最大宽度
算法讲解:队列
这道题的难点就是在要考虑null节点,如果某一层的开始节点和结束节点中有空节点,我们在计算宽度时也要将空节点考虑进去
此时可以根据二叉树的另一种表达方法来解决问题,我们知道二叉树是可以用数组来表示的,假设一个父节点在数组的下标为i(假设根节点的下标为1),那么该根节点的左孩子结点对应到数字的下标就为2*i,该根节点的右孩子节点对应到数组的下标就为2*i+1
如果根节点的下标为0的话,那么此时左孩子节点对应到数组的下标就是2*i+1,右孩子对应到数组的小标就是2*i+2
则此时我们就可以通过对二叉树的节点进行编号,此时二叉树中某一层的宽度就是该层的开始节点的编号减去该层最后一个节点的编号+1
则此时可以创建一个Queue<Pair<TreeNode,Integer>>的队列,此时依旧是前面两道题的思路,先将根节点放进队列中,然后依次对节点进行出队列,每一个节点出队列后,要将该节点的左右孩子节点入队列
此时就是有一个不同点,就是在遍历二叉树的某一层时,要记得记录该层的第一个节点的编号和该层最后一个节点的编号
代码实现:
class Solution {public int widthOfBinaryTree(TreeNode root) {Queue<Pair<TreeNode,Integer>> q = new LinkedList<>();q.offer(new Pair<>(root,1));int ret=1;while(!q.isEmpty()){int sz=q.size();int left = 0;//left记录该层第一个节点的编号int right = 0;//right记录该层最后一个节点的编号for(int i=0;i<sz;i++){Pair<TreeNode,Integer> pair = q.poll();TreeNode node = pair.getKey();int index = pair.getValue();if(i==0) left=index;//此时index是该层第一个节点的编号if(i==sz-1) right=index;//此时index是该层最后一个节点的编号if(node.left!=null) q.offer(new Pair<>(node.left,index*2));if(node.right!=null) q.offer(new Pair<>(node.right,index*2+1));}ret=Math.max(ret,right-left+1);}return ret;}
}
4.在每个树行中找最大值
题目链接:515. 在每个树行中找最大值 - 力扣(LeetCode)
算法讲解:队列+层序遍历
其实这道题的解题思路几乎和前面的题目一模一样,不过就是在层序遍历的过程中要创建一个变量来记录每一层的最大值
代码实现:
class Solution {public List<Integer> largestValues(TreeNode root) {List<Integer> ret = new LinkedList<>();Queue<TreeNode> q = new LinkedList<>();if(root==null) return ret;q.offer(root);while(!q.isEmpty()){int sz = q.size();int max=Integer.MIN_VALUE;for(int i=0;i<sz;i++){TreeNode node = q.poll();int tmp = node.val;max=Math.max(max,tmp);if(node.left!=null) q.offer(node.left);if(node.right!=null) q.offer(node.right);}ret.add(max);}return ret;}
}