102:二叉树的层序遍历
感觉比较像一生二,二生四的原理,每次队列中维持的元素都是一层的所有元素,而每次把队列中的元素出队的同时,也把元素结点的左右结点入队。
/**
* 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>> resList = new LinkedList<>();
if (root==null) {
return resList;
}
Queue<TreeNode> queue = new LinkedList<>();//用来维护每一层的结点队列
queue.offer(root);//先把根节点入队
while (!queue.isEmpty()) {//当队列元素不为空的时候
List<Integer> list = new ArrayList<>();//记录每一层元素的list
int len = queue.size();//队列长度
while (len>0) {//遍历队列元素,依次出队
TreeNode node = queue.poll();//弹出队头元素
list.add(node.val);//队列元素加入list
if (node.left!=null) {//同时把该结点的左结点入队
queue.offer(node.left);
}
if (node.right!=null) {//同时把该结点的右结点入队
queue.offer(node.right);
}
len--;
}
resList.add(list);
}
return resList;
}
}
107:二叉树的层序遍历||
将102得到的队列进行一次reverse操作即可。
199:二叉树的右视图
把每层的最后一个元素记录下来即可。
/**
* 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<Integer> rightSideView(TreeNode root) {
List<Integer> resList = new LinkedList<>();
if (root==null) {
return resList;
}
Queue<TreeNode> queue = new LinkedList<>();//用来维护每一层的结点队列
queue.offer(root);//先把根节点入队
while (!queue.isEmpty()) {//当队列元素不为空的时候
int len = queue.size();//队列长度
while (len>0) {//遍历队列元素,依次出队
TreeNode node = queue.poll();//弹出队头元素
if (len==1) {
resList.add(node.val);//队列元素加入list
}
if (node.left!=null) {//同时把该结点的左结点入队
queue.offer(node.left);
}
if (node.right!=null) {//同时把该结点的右结点入队
queue.offer(node.right);
}
len--;
}
}
return resList;
}
}
637:二叉树的层平均值
计算每层的平均值
/**
* 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<Double> averageOfLevels(TreeNode root) {
List<Double> resList = new LinkedList<>();
if (root==null) {
return resList;
}
Queue<TreeNode> queue = new LinkedList<>();//用来维护每一层的结点队列
queue.offer(root);//先把根节点入队
while (!queue.isEmpty()) {//当队列元素不为空的时候
int len = queue.size();//队列长度
int count = len;
double sum = 0;
while (len>0) {//遍历队列元素,依次出队
TreeNode node = queue.poll();//弹出队头元素
sum += node.val;
if (node.left!=null) {//同时把该结点的左结点入队
queue.offer(node.left);
}
if (node.right!=null) {//同时把该结点的右结点入队
queue.offer(node.right);
}
len--;
}
resList.add(sum/count);
}
return resList;
}
}
429:n叉树的层序遍历
把n个子结点入队。
/*
// Definition for a Node.
class Node {
public int val;
public List<Node> children;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, List<Node> _children) {
val = _val;
children = _children;
}
};
*/
class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> resList = new LinkedList<>();
if (root==null) {
return resList;
}
Queue<Node> queue = new LinkedList<>();//用来维护每一层的结点队列
queue.offer(root);//先把根节点入队
while (!queue.isEmpty()) {//当队列元素不为空的时候
List<Integer> list = new ArrayList<>();//记录每一层元素的list
int len = queue.size();//队列长度
while (len>0) {//遍历队列元素,依次出队
Node node = queue.poll();//弹出队头元素
list.add(node.val);//队列元素加入list
for (Node n : node.children) {
queue.offer(n);
}
len--;
}
resList.add(list);
}
return resList;
}
}
515:在每个树行中找最大值
/**
* 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<Integer> largestValues(TreeNode root) {
List<Integer> resList = new LinkedList<>();
if (root==null) {
return resList;
}
Queue<TreeNode> queue = new LinkedList<>();//用来维护每一层的结点队列
queue.offer(root);//先把根节点入队
while (!queue.isEmpty()) {//当队列元素不为空的时候
int len = queue.size();//队列长度
int max = Integer.MIN_VALUE;
for (int i = 0; i < len; i++) {
TreeNode node = queue.poll();//弹出队头元素
if (node.val>max) {
max = node.val;
}
if (node.left!=null) {//同时把该结点的左结点入队
queue.offer(node.left);
}
if (node.right!=null) {//同时把该结点的右结点入队
queue.offer(node.right);
}
}
resList.add(max);//max加入list
}
return resList;
}
}
116:填充每个结点的下一个右侧结点
两道题目代码是一样的,原理类似。
/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right;
public Node next;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, Node _left, Node _right, Node _next) {
val = _val;
left = _left;
right = _right;
next = _next;
}
};
*/
class Solution {
public Node connect(Node root) {
if (root==null) {
return root;
}
Queue<Node> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int len = queue.size();
for (int i = 0; i < len; i++) {
Node node = queue.poll();
if (i==len-1) {
node.next = null;
}else {
node.next = queue.peek();
}
if (node.left!=null) {
queue.offer(node.left);
}
if (node.right!=null) {
queue.offer(node.right);
}
}
}
return root;
}
}
104:二叉树的最大深度
/**
* 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 int maxDepth(TreeNode root) {
int depth = 0;
if (root == null) {
return 0;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int len = queue.size();
for (int i = 0; i < len; i++) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
depth++;
}
return depth;
}
}
111:二叉树的最小深度
“需要注意的是,只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点”
/**
* 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 int minDepth(TreeNode root) {
int depth = 0;
if (root == null) {
return 0;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int len = queue.size();
for (int i = 0; i < len; i++) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
if ((node.left==null)&&(node.right==null)) {
return depth+1;
}
}
depth++;
}
return depth;
}
}
226:翻转二叉树
前序遍历或者后序遍历并进行结点交换。
把遍历和要做的操作分开考虑,不容易混乱。
递归法:
/**
* 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 TreeNode invertTree(TreeNode root) {
if (root == null) {
return root;
}
swap(root);
invertTree(root.left);
invertTree(root.right);
return root;
}
public void swap(TreeNode root) {
TreeNode tempNode = root.left;
root.left = root.right;
root.right = tempNode;
}
}
迭代法:
/**
* 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 TreeNode invertTree(TreeNode root) {
if (root == null) {
return root;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
swap(node);
if (node.right!=null) {
stack.push(node.right);
}
if (node.left!=null) {
stack.push(node.left);
}
}
return root;
}
public void swap(TreeNode root) {
TreeNode tempNode = root.left;
root.left = root.right;
root.right = tempNode;
}
}
层级遍历:
/**
* 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 TreeNode invertTree(TreeNode root) {
if (root == null) {
return root;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int len = queue.size();
for (int i = 0; i < len; i++) {
TreeNode node = queue.poll();
swap(node);
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
}
return root;
}
public void swap(TreeNode root) {
TreeNode tempNode = root.left;
root.left = root.right;
root.right = tempNode;
}
}
101:对称二叉树
“比较的是根节点的两个子树是否是相互翻转的”。
递归法:
1、递归函数:
递归每次返回一个是否对称的结果,因此返回值为boolean。每次比较两个子树是否是相互翻转的,所以参数应该是左子树的头结点和右子树的头结点。boolean judge(TreeNode left, TreeNode right)。
2、递归终止条件:
递归最后肯定是剩下两个结点,由如下情况:
left | right | return |
null | 非null | false |
非null | null | false |
null | null | true |
非null,值为val1 | 非null,值为val2 | false |
非null,值为val | 非null,值为val | 需要继续递归比较 |
3、单层递归逻辑
左右节点都不为空,且数值相同的情况需要再次进入单层递归比较:
- 比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
- 比较内测是否对称,传入左节点的右孩子,右节点的左孩子。
- 如果左右都对称就返回true ,有一侧不对称就返回false 。
/**
* 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 boolean isSymmetric(TreeNode root) {
if (root==null) {
return true;
}
return judge(root.left, root.right);
}
public boolean judge(TreeNode left, TreeNode right) {
if (left==null && right!=null) {
return false;
}else if (left!=null && right==null) {
return false;
}else if (left==null && right==null) {
return true;
}else if (left.val != right.val) {
return false;
}
boolean outside = judge(left.left, right.right);
boolean inside = judge(left.right, right.left);
return outside&&inside;
}
}
迭代法:
1、用队列
class Solution {
public boolean isSymmetric(TreeNode root) {
if (root==null) {
return true;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root.left);
queue.offer(root.right);
while (!queue.isEmpty()) {
TreeNode left = queue.poll();
TreeNode right = queue.poll();
if (left==null && right==null) {
continue;
}
if (left==null || right==null || left.val != right.val) {
return false;
}
queue.offer(left.left);
queue.offer(right.right);
queue.offer(left.right);
queue.offer(right.left);
}
return true;
}
}
2、栈
class Solution {
public boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root.left);
stack.push(root.right);
while (!stack.isEmpty()) {
TreeNode right = stack.pop();
TreeNode left = stack.pop();
if (left == null && right == null) {
continue;
}
if (left == null || right == null || left.val != right.val) {
return false;
}
stack.push(left.left);
stack.push(right.right);
stack.push(left.right);
stack.push(right.left);
}
return true;
}
}
总结:今天感觉递归更熟练了,但是迭代法写着还是生疏。