一、算法题
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 ArrayList<List<Integer>>();
order(root,resList);
return resList;
}
public void order(TreeNode root,List<List<Integer>> resList){
if(root==null){
return;
}
Queue<TreeNode> que=new LinkedList<>();
que.add(root);
while (!que.isEmpty()) {
List<Integer> res=new ArrayList<>();
int len=que.size();
while (len>0) {
TreeNode tmp=que.poll();
res.add(tmp.val);
if(tmp.left!=null){
que.add(tmp.left);
}
if(tmp.right!=null){
que.add(tmp.right);
}
len--;
}
resList.add(res);
}
}
}
注意:
- 每遍历完一层结点,res要“刷新”,不能保留原来的数据,不然会造成最后结果重复加入元素
- 所以res的创建语句要放到循环里面
107.二叉树的层次遍历 II
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
//跟102的层序遍历思想一样,只是改变一下元素加入位置
LinkedList<List<Integer>> resList=new LinkedList<>();
if(root==null){
return resList;
}
Queue<TreeNode> que=new LinkedList<>();
que.offer(root);
while(!que.isEmpty()){
int len=que.size();
List<Integer> res=new ArrayList<>();
while(len>0){
TreeNode tmp=que.poll();
res.add(tmp.val);
if(tmp.left!=null){
que.offer(tmp.left);
}
if(tmp.right!=null){
que.offer(tmp.right);
}
len--;
}
resList.addFirst(res);
}
return resList;
}
}
199.二叉树的右视图
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res=new LinkedList<>();
if(root==null){
return res;
}
Queue<TreeNode> que=new LinkedList<>();
que.offer(root);
while (!que.isEmpty()) {
int len=que.size();
while(len>0){
TreeNode tmp=que.poll();
if(tmp.left!=null){
que.offer(tmp.left);
}
if(tmp.right!=null){
que.offer(tmp.right);
}
if(len==1){
res.add(tmp.val);
}
len--;
}
}
return res;
}
}
- 还是跟以前一样层序遍历,但是在加入元素的时候多了个判断条件
- 只有遍历到了该层最后一个元素的时候才把这个结点的值加入到列表中,即 len=1时
637.二叉树的层平均值
class Solution {
public List<Double> averageOfLevels(TreeNode root) {
List<Double> res=new ArrayList<>();
if(root==null){
return res;
}
Queue<TreeNode> que=new LinkedList<>();
que.offer(root);
while (!que.isEmpty()) {
int len=que.size();
int cnt=0;
double sum=0;
double avg=0;
while(len>0){
TreeNode tmp=que.poll();
if(tmp.left!=null){
que.offer(tmp.left);
}
if(tmp.right!=null){
que.offer(tmp.right);
}
len--;
cnt++;
sum+=tmp.val;
}
avg=sum/cnt;
res.add(avg);
}
return res;
}
}
429.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>> list = new ArrayList<>();
if(root==null){
return list;
}
Deque<Node> que = new LinkedList<>();
que.add(root);
while (!que.isEmpty()) {
List<Integer> res=new ArrayList<>();
int size=que.size();
while(size>0){
Node tmp=que.poll();
res.add(tmp.val);
List<Node> child=tmp.children;
if(child==null){
continue;
}
for(Node c:child){
que.add(c);
}
size--;
}
list.add(res);
}
return list;
}
}
难点:
- 一个结点不再是只有左右孩子而是有n个孩子结点
- 所以在往队列中加入poll出的元素的子节点时,要针对这个元素把它所有的孩子结点遍历出来加入队列
- 孩子结点保存在一个列表中,所以要用一个列表拿到这些孩子结点,再用遍历的方式把每个孩子结点遍历出来
515.在每个树行中找最大值
class Solution {
public List<Integer> largestValues(TreeNode root) {
List<Integer> res=new LinkedList<>();
if(root==null){
return res;
}
Queue<TreeNode> que=new LinkedList<>();
que.offer(root);
while (!que.isEmpty()) {
int len=que.size();
int max=Integer.MIN_VALUE;
while(len>0){
TreeNode tmp=que.poll();
if(tmp.val>max){
max=tmp.val;
}
if(tmp.left!=null){
que.offer(tmp.left);
}
if(tmp.right!=null){
que.offer(tmp.right);
}
len--;
}
res.add(max);
}
return res;
}
}
116.填充每个节点的下一个右侧节点指针
class Solution {
public Node connect(Node root) {
if(root==null){
return root;
}
Queue<Node> que=new LinkedList<>();
que.offer(root);
while (!que.isEmpty()) {
int len=que.size();
for(int i=0;i<len;i++){
Node tmp=que.poll();
if(i<len-1){
tmp.next=que.peek();
}
if(tmp.left!=null){
que.offer(tmp.left);
}
if(tmp.right!=null){
que.offer(tmp.right);
}
}
}
return root;
}
}
- if(i<len-1){ tmp.next=que.peek(); }
- 一定要 i< len-1
- 因为在执行 tmp.next=que.peek()语句时,只要处理到每一层的倒数第二个节点就行,因为题目中给出初始状态下,所有 next 指针都被设置为NULL,所以每一层最后一个结点已经指向NULL了
117.填充每个节点的下一个右侧节点指针II
class Solution {
public Node connect(Node root) {
if(root==null){
return root;
}
Queue<Node> que=new LinkedList<>();
que.offer(root);
while (!que.isEmpty()) {
int len=que.size();
for(int i=0;i<len;i++){
Node tmp=que.poll();
if(i<len-1){
tmp.next=que.peek();
}
if(tmp.left!=null){
que.offer(tmp.left);
}
if(tmp.right!=null){
que.offer(tmp.right);
}
}
}
return root;
}
}
104.二叉树的最大深度
class Solution {
public int maxDepth(TreeNode root) {
if(root==null){
return 0;
}
Queue<TreeNode> que=new LinkedList<>();
que.offer(root);
int len=0;
while (!que.isEmpty()) {
int size=que.size();
while(size>0){
TreeNode tmp=que.poll();
if(tmp.left!=null){
que.offer(tmp.left);
}
if(tmp.right!=null){
que.offer(tmp.right);
}
size--;
}
len++;
}
return len;
}
}
111.二叉树的最小深度
class Solution {
public int minDepth(TreeNode root) {
if(root==null){
return 0;
}
Queue<TreeNode> que=new LinkedList<>();
que.offer(root);
int len=0;
while (!que.isEmpty()) {
int size=que.size();
while(size>0){
TreeNode tmp=que.poll();
if(tmp.left!=null){
que.offer(tmp.left);
}
if(tmp.right!=null){
que.offer(tmp.right);
}
if(tmp.left==null&&tmp.right==null){
return len+1;
}
size--;
}
len++;
}
return len;
}
}
226.翻转二叉树
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null){
return root;
}
reverse(root);
return root;
}
public void reverse(TreeNode root){
if(root==null){
return;
}
TreeNode tmp=root.left;
root.left=root.right;
root.right=tmp;
reverse(root.left);
reverse(root.right);
}
}
- 使用前序遍历,根据每个中间结点,对它的左右结点进行操作,交换位置
101. 对称二叉树
class Solution {
public boolean isSymmetric(TreeNode root) {
if(root==null){
return false;
}
return reverse(root.left, root.right);
}
public boolean reverse(TreeNode left,TreeNode right){
if(left==null&&right!=null){
return false;
}
if(left!=null&&right==null){
return false;
}
if(left==null&&right==null){
return true;
}
if(left.val!=right.val){
return false;
}
return reverse(left.left, right.right) &&reverse(right.left, left.right);
}
}
首先把根节点的左右节点分成两部分
要对比的就是左右两部分节点是不是对称相等
如果对称位置的左右节点都为空,此时是对称的,返回true
if(left==null&&right==null){ return true; }
如果对称位置的左右节点,其中有一个为空,说明此时不对称
if(left==null||right==null){ return false; }
如果对称位置的左右节点值不相等,此时不对称
if(left.val!=right.val){ return false; }
递归代码
return reverse(left.left,right.right)&&reverse(left.right,right.left);
对称位置就是外层跟内层的位置数值要相等
比如左节点的左字节点与右节点的右子节点
reverse(left.left,right.right);
- 比如左节点的右字节点与右节点的左子节点
reverse(left.right,right.left);