129. 求根到叶子节点数字之和
方法1:广度优先搜索
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int sumNumbers(TreeNode root) {
return bfs(root);
}
public int bfs(TreeNode root){
if(root==null) return 0;
Queue<TreeNode> qu=new LinkedList<TreeNode>();
Queue<Integer> quNum=new LinkedList<Integer>();
int sum=0;
qu.offer(root);
quNum.offer(root.val);
while(!qu.isEmpty()){
TreeNode p=qu.poll();
int num=quNum.poll();
if(p.left==null&&p.right==null){
sum+=num;
}
if(p.left!=null){
qu.offer(p.left);
quNum.offer(num*10+p.left.val);
}
if(p.right!=null){
qu.offer(p.right);
quNum.offer(num*10+p.right.val);
}
}
return sum;
}
}
方法2:深度优先搜索
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int sumNumbers(TreeNode root) {
//假设根节点的父节点值为0
return dfs(root,0);
}
public int dfs(TreeNode root,int preNode){
if(root==null) return 0;
int sum=preNode*10+root.val;
if(root.left==null&&root.right==null){
return sum;
}else{
return dfs(root.left,sum)+dfs(root.right,sum);
}
}
}
863. 二叉树中所有距离为 K 的结点
方法1:深度优先搜索
先利用深度优先遍历找到每个结点的父节点,再利用深度优先遍历查找结点。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> distanceK(TreeNode root, TreeNode target, int K) {
List<Integer> list=new ArrayList<>();
Map<TreeNode,TreeNode> parentMap=new HashMap<>();
searchParent(root,parentMap);
boolean [] visited=new boolean[501];
dfs(target,K,parentMap,visited,list);
return list;
}
//找到每个结点的父节点
public void searchParent(TreeNode root,Map<TreeNode,TreeNode> parentMap){
if(root==null) return;
if(root.left!=null){
parentMap.put(root.left,root);
}
if(root.right!=null){
parentMap.put(root.right,root);
}
searchParent(root.left,parentMap);
searchParent(root.right,parentMap);
}
//深度优先遍历
public void dfs(TreeNode target,int k,Map<TreeNode,TreeNode> parentMap,boolean[] visited,List<Integer> list){
if(target == null || k < 0 || visited[target.val]) return;
if(k==0 && !visited[target.val]){
list.add(target.val);
visited[target.val]=true;
return;
}
visited[target.val]=true;
dfs(target.left,k-1,parentMap,visited,list);
dfs(target.right,k-1,parentMap,visited,list);
dfs(parentMap.get(target),k-1,parentMap,visited,list);
}
}
方法2:计算结点之间的距离(待定)
剑指 Offer 34. 二叉树中和为某一值的路径
方法1:先序遍历
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
List<List<Integer>> lists=new LinkedList<>();
LinkedList<Integer> path=new LinkedList<>();
public List<List<Integer>> pathSum(TreeNode root, int sum) {
dfs(root,sum);
return lists;
}
//先序遍历
public void dfs(TreeNode root,int sum){
if(root==null) return;
path.add(root.val);
sum-=root.val;
if(sum==0&&root.left==null&&root.right==null) {
lists.add(new LinkedList(path));
}
dfs(root.left,sum);
dfs(root.right,sum);
path.removeLast();
}
}
剑指 Offer 32 - III. 从上到下打印二叉树 III
方法1:借助广度优先搜索,每次打印两层,先打印奇数层,再打印偶数层,如果没有偶数层,则结束循环。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
if(root==null) return new ArrayList<>();
List<List<Integer>> lists=new ArrayList<>();//二维数组存放输出数据
Deque<TreeNode> qu=new LinkedList<>();//借助LinkedList实现双端队列
qu.offer(root);
//每次循环打印两层
while(!qu.isEmpty()){
LinkedList<Integer> list=new LinkedList<>();
//先打印奇数层
for(int i=qu.size();i>0;i--){
TreeNode q=qu.removeFirst();
list.add(q.val);
if(q.left!=null) qu.addLast(q.left);
if(q.right!=null) qu.addLast(q.right);
}
lists.add(list);
//若没有偶数层了,就退出循环
if(qu.isEmpty()) break;
//再打印偶数层
list=new LinkedList<>();
for(int i=qu.size();i>0;i--){
TreeNode q=qu.removeLast();
list.add(q.val);
if(q.right!=null) qu.addFirst(q.right);
if(q.left!=null) qu.addFirst(q.left);
}
lists.add(list);
}
return lists;
}
}
方法2:利用二维数组的行数判断层数,每次打印一层。
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
List<List<Integer>> res = new ArrayList<>();
if(root != null) queue.add(root);
while(!queue.isEmpty()) {
LinkedList<Integer> tmp = new LinkedList<>();
for(int i = queue.size(); i > 0; i--) {
TreeNode node = queue.poll();
if(res.size() % 2 == 0) tmp.addLast(node.val); // 偶数层 -> 队列头部
else tmp.addFirst(node.val); // 奇数层 -> 队列尾部
if(node.left != null) queue.add(node.left);
if(node.right != null) queue.add(node.right);
}
res.add(tmp);
}
return res;
}
}
匹配类二叉树题目总结:剑指 Offer 26. 树的子结构、1367. 二叉树中的列表、101. 对称二叉树、572. 另一个树的子树
剑指 Offer 26. 树的子结构
方法:递归的方式实现
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
return (A!=null&&B!=null)&&(judge(A,B)||isSubStructure(A.left,B)||isSubStructure(A.right,B));
}
public boolean judge(TreeNode A,TreeNode B){
if(B==null) return true;
if(A==null||A.val!=B.val) return false;
return judge(A.left,B.left)&&judge(A.right,B.right);
}
}
1367. 二叉树中的列表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
/**
* 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 isSubPath(ListNode head, TreeNode root) {
if(root==null) return false;
return dfs(head,root)||isSubPath(head,root.left)||isSubPath(head,root.right);
}
public boolean dfs(ListNode head,TreeNode root){
if(head==null) return true;
if(root==null||head.val!=root.val) return false;
return dfs(head.next,root.left)||dfs(head.next,root.right);
}
}
572. 另一个树的子树
/**
* 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 isSubtree(TreeNode s, TreeNode t) {
if(s==null) return false;
return dfs(s,t)||isSubtree(s.left,t)||isSubtree(s.right,t);
}
public boolean dfs(TreeNode s,TreeNode t){
if(t==null&&s==null) return true;
if(t==null||s==null||s.val!=t.val) return false;
return dfs(s.left,t.left)&&dfs(s.right,t.right);
}
}
剑指 Offer 07. 重建二叉树
方法:递归实现。使用一个 Map 存储中序遍历的每个元素及其对应的下标,目的是为了快速获得一个元素在中序遍历中的位置。调用递归方法,对于前序遍历和中序遍历,下标范围都是从 0 到 n-1,其中 n 是二叉树节点个数。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
int[] preorder;
Map<Integer,Integer> treeMap=new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
this.preorder=preorder;
int n=preorder.length;
if(n==0) return null;
for(int i=0;i<n;i++){
treeMap.put(inorder[i],i);
}
return build(0,0,n-1);
}
public TreeNode build(int root,int left,int right){
if(left>right) return null;
TreeNode node=new TreeNode(preorder[root]);
int i=treeMap.get(preorder[root]);
node.left=build(root+1,left,i-1);
node.right=build(root-left+i+1,i+1,right);
return node;
}
}