515.在每个树行中找最大值
class Solution {
public List<Integer> largestValues(TreeNode root) {
Queue<TreeNode> q=new LinkedList<>();
List<Integer> level=new ArrayList<>();
if(root!=null){
q.offer(root);
}
while(!q.isEmpty()){
int size=q.size();
int max=Integer.MIN_VALUE;
for(int i=0;i<size;i++){
TreeNode cur=q.poll();
max=Math.max(max,cur.val);
if(cur.left!=null){
q.offer(cur.left);
}
if(cur.right!=null){
q.offer(cur.right);
}
}
level.add(max);
}
return level;
}
}
116.填充每个节点的下一个右侧节点指针
方法一
本题依然是层序遍历,只不过在单层遍历的时候记录一下本层的头部节点,然后在遍历的时候让前一个节点指向本节点就可以了
class Solution {
public Node connect(Node root) {
Queue<Node> q=new LinkedList<>();
if(root!=null){
q.offer(root);
}
while(!q.isEmpty()){
int size=q.size();
Node temp=q.poll();
if(temp.left!=null){
q.offer(temp.left);
}
if(temp.right!=null){
q.offer(temp.right);
}
for(int i=1;i<size;i++){
Node cur=q.poll();
if(cur.left!=null){
q.offer(cur.left);
}
if(cur.right!=null){
q.offer(cur.right);
}
temp.next=cur;
temp=cur;
}
}
return root;
}
}
class Solution {
public Node connect(Node root) {
if(root==null) return null;
traverse(root.left,root.right);
return root;
}
public void traverse(Node node1,Node node2){
if(node1==null||node2==null) return;
node1.next=node2;
traverse(node1.left,node1.right);
traverse(node1.right,node2.left);
traverse(node2.left,node2.right);
}
}
117.填充每个节点的下一个右侧节点指针II
class Solution {
public Node connect(Node root) {
Queue<Node> q=new LinkedList<>();
if(root!=null){
q.offer(root);
}
while(!q.isEmpty()){
int size=q.size();
Node temp=null;
Node cur=null;
for(int i=0;i<size;i++){
if (i == 0) {
temp = q.poll(); // 取出本层头一个节点
cur = temp;
} else {
cur = q.poll();
temp.next = cur; // 本层前一个节点 next 指向当前节点
temp= temp.next;
}
if(cur.left!=null){
q.offer(cur.left);
}
if(cur.right!=null){
q.offer(cur.right);
}
}
temp.next = null;
}
return root;
}
}
104.二叉树的最大深度
方法一.
思路:遍历一遍二叉树,用一个外部变量记录每个节点所在深度,取最大值即可得到最大深度
class Solution {
//记录最大深度
int res=0;
//记录遍历到的节点的深度
int depth=0;
public int maxDepth(TreeNode root) {
traverse(root);
return res;
}
public void traverse(TreeNode root){
if(root==null) return ;
//前序位置:进入一个节点
depth++;
traverse(root.left);
traverse(root.right);
//if循环放在depth++之后depth--之前的任何位置均可只要保证在节点进入之后和节点离开之前即可
if(root.left==null&&root.right==null){
res=Math.max(res,depth);
}
//后序位置,离开一个节点的时候
depth--;
}
}
方法二.通过分解问题得到答案,一个二叉树的最大深度可以通过子树的最大深度推导出来
class Solution {
public int maxDepth(TreeNode root) {
if(root==null) return 0;
int left=maxDepth(root.left);
int right=maxDepth(root.right);
return Math.max(left,right)+1;
}
}
方法三:层序遍历的方法
在二叉树中,一层一层的来遍历二叉树,记录一下遍历的层数就是二叉树的深度
class Solution {
public int maxDepth(TreeNode root) {
Queue<TreeNode> q=new LinkedList<>();
int level=0;
if(root!=null){
q.offer(root);
}
while(!q.isEmpty()){
int size=q.size();
for(int i=0;i<size;i++){
TreeNode cur=q.poll();
if(cur.left!=null){
q.offer(cur.left);
}
if(cur.right!=null){
q.offer(cur.right);
}
}
level++;
}
return level;
}
}
111.二叉树的最小深度
需要注意的是,只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点
class Solution {
public int minDepth(TreeNode root) {
Queue<TreeNode> q=new LinkedList<>();
int level=0;
if(root!=null){
q.offer(root);
}
while(!q.isEmpty()){
int size=q.size();
level++;
for(int i=0;i<size;i++){
TreeNode cur=q.poll();
if(cur.left==null&&cur.right==null){
return level;
}
if(cur.left!=null){
q.offer(cur.left);
}
if(cur.right!=null){
q.offer(cur.right);
}
}
}
return level;
}
}
.226. 翻转二叉树
方法一:前序遍历或后序遍历
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) return root;
swap(root);//写在这是前序
invertTree(root.left);
invertTree(root.right);
//swap(root) 也可以写在这,写在这是后序
return root;
}
public void swap(TreeNode root){
TreeNode temp=root.left;
root.left=root.right;
root.right=temp;
}
}
方法二:层序遍历
class Solution {
public TreeNode invertTree(TreeNode root) {
Queue<TreeNode> q=new LinkedList<>();
int level=0;
if(root!=null){
q.offer(root);
}
while(!q.isEmpty()){
int size=q.size();
for(int i=0;i<size;i++){
TreeNode cur=q.poll();
swap(cur);
if(cur.left!=null){
q.offer(cur.left);
}
if(cur.right!=null){
q.offer(cur.right);
}
}
}
return root;
}
public void swap(TreeNode root) {
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
}
}
101. 对称二叉树
本题遍历只能是“后序遍历”,因为我们要通过不断收集左右孩子的信息返回给上一节点,在收集上一节点左右孩子的信息返回给上一节点
正是因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。
递归三部曲
确定递归函数的参数和返回值
要比较的是两个树,参数自然也是左子树节点和右子树节点。
返回值自然是bool类型。
终止条件
左节点为空,右节点不为空,不对称,return false
左不为空,右为空,不对称 return false
左右都为空,对称,返回true
左右都不为空,比较节点数值,不相同就return false
剩下的就是 左右节点都不为空,且数值相同的情况,就要向下一层遍历
单层递归逻辑
单层递归的逻辑就是处理 左右节点都不为空,且数值相同的情况。
比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
比较内测是否对称,传入左节点的右孩子,右节点的左孩子。
如果左右都对称就返回true ,有一侧不对称就返回false 。
class Solution {
public boolean isSymmetric(TreeNode root) {
return compare(root.left,root.right);
}
public boolean compare(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;
}else{
boolean compareOutside=compare(left.left,right.right);
boolean compareInside=compare(left.right,right.left);
return compareInside&&compareOutside;
}
}
}
100. 相同的树
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
return compare(p,q);
}
public boolean compare(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;
}else{
boolean compareOutside=compare(left.left,right.left);
boolean compareInside=compare(left.right,right.right);
return compareInside&&compareOutside;
}
}
}
572. 另一棵树的子树
class Solution {
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
if(subRoot==null) return true;
if(root==null) return false;
return isSubtree(root.left,subRoot)||isSubtree(root.right,subRoot)||compare(root,subRoot);
}
public boolean compare(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;
}else{
boolean compareOutside=compare(left.left,right.left);
boolean compareInside=compare(left.right,right.right);
return compareInside&&compareOutside;
}
}
}