这几天刷的算法题都是二叉树相关的,这里就放一点二叉树的知识:
首先是遍历:
前序遍历:根结点 ---> 左子树 ---> 右子树
中序遍历:左子树---> 根结点 ---> 右子树
后序遍历:左子树 ---> 右子树 ---> 根结点
层次遍历:一层一层输出
1.前序遍历:根左右
递归
public void inorder(TreeNode root) {
if (root == null) {
return;
}
System.out.println(root.val);
inorder(root.left, res);
inorder(root.right, res);
}
非递归:
如果采用非递归的实现,顺序不变依然是根然后左右,因为是先左之后还要找到根的右孩子,所以要保存根节点,采用栈进行保存。
从最开始的根节点开始,
1。如果不是空,那么输出该根节点数据同时将该节点入栈,并将其左孩子节点定为目标节点
2。然后再判断当前节点是否为空,如果是空则出栈,将出栈的结点的右孩子节点定位目标节点,否则重复第一步直到栈空且结点为空
public void preOrderTraverse2(TreeNode root) { LinkedList<TreeNode> stack = new LinkedList<>(); TreeNode pNode = root; while (pNode != null || !stack.isEmpty()) { if (pNode != null) { System.out.print(pNode.val+" "); stack.push(pNode); pNode = pNode.left; } else { //pNode == null && !stack.isEmpty() TreeNode node = stack.pop(); pNode = node.right; } } }
2.中序遍历:左根右
递归
public void inorder(TreeNode root) { if (root == null) { return; } System.out.println(root.val); inorder(root.left, res); inorder(root.right, res); }
非递归:
和前序遍历相似,只是将输出根节点的时刻放到右孩子之前
public void preOrderTraverse2(TreeNode root) { LinkedList<TreeNode> stack = new LinkedList<>(); TreeNode pNode = root; while (pNode != null || !stack.isEmpty()) { if (pNode != null) { stack.push(pNode); pNode = pNode.left; } else { //pNode == null && !stack.isEmpty() TreeNode node = stack.pop(); System.out.print(node.val+" "); pNode = node.right; } } }
3.后序遍历:左右根
递归
public void inorder(TreeNode root) { if (root == null) { return; } inorder(root.left, res); inorder(root.right, res); System.out.println(root.val); }
非递归
后序遍历的非递归是最难的,要保证左右全部访问之后再重新回到根节点,
不太好写,等以后搞明白了再来吧
4.层次遍历:
比较简单,用队列保存结点就可以,需要注意的是,一定要注意root为空或者左右孩子为空的情况
class Solution { public List<List<Integer>> levelOrder(TreeNode root) { if(root==null){ return new ArrayList<>(); } Queue<TreeNode> queue=new LinkedList<>(); List<List<Integer>> res=new ArrayList<>(); queue.add(root); while(!queue.isEmpty()){ int len=queue.size(); List<Integer> r=new ArrayList<>(); for(int i=0;i<len;i++){ TreeNode node=queue.poll(); r.add(node.val); if(node.left!=null) queue.add(node.left); if(node.right!=null) queue.add(node.right); } res.add(r); } return res; } }
5.二叉树左右孩子交换
层次:
class Solution { public TreeNode invertTree(TreeNode root) { if(root==null){ return root; } Queue<TreeNode> queue=new LinkedList<>(); TreeNode res=root; queue.add(root); while(!queue.isEmpty()){ int len=queue.size(); for(int i=0;i<len;i++){ TreeNode node=queue.poll(); if(node.left!=null){queue.add(node.left);} if(node.right!=null){queue.add(node.right);} TreeNode childnode=node.left; node.left=node.right; node.right=childnode; } } return res; } }
先序:
class Solution { // 先序遍历--从顶向下交换 public TreeNode invertTree(TreeNode root) { if (root == null) return null; // 保存右子树 TreeNode rightTree = root.right; // 交换左右子树的位置 root.right = invertTree(root.left); root.left = invertTree(rightTree); return root; } }