257. 二叉树的所有路径
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
输入:
1
/
2 3
5
输出: [“1->2->5”, “1->3”]
解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3
题解:
1)dfs
2)bfs 队列判断是不是叶子节点,不是放队尾,是添加到路径直到队伍空
solution:
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> res=new ArrayList<>();
if(root==null) return res;
dfs(root,"",res);
return res;
}
public void dfs(TreeNode root,String cur,List<String> res){
if(root==null) return;
cur+=root.val;
if(root.left==null&&root.right==null) res.add(cur);
else {
dfs(root.left,cur+"->",res);
dfs(root.right,cur+"->",res);
}
}
}
543. 二叉树的直径
给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。
题解:递归 遍历每一个结点,计算最长路径(左子树边长+右子树边长),更新全局变量max。
class Solution {
int max = 0;
public int diameterOfBinaryTree(TreeNode root) {
if (root == null) {
return 0;
}
dfs(root);
return max;
}
private int dfs(TreeNode root) {
if (root.left == null && root.right == null) {
return 0;
}
int leftSize = root.left == null? 0: dfs(root.left) + 1;
int rightSize = root.right == null? 0: dfs(root.right) + 1;
max = Math.max(max, leftSize + rightSize);
return Math.max(leftSize, rightSize);
}
}
563. 二叉树的坡度
给定一个二叉树,计算整个树的坡度。
一个树的节点的坡度定义即为,该节点左子树的结点之和和右子树结点之和的差的绝对值。空结点的的坡度是0。
整个树的坡度就是其所有节点的坡度之和,
题解:
1)递归
整个树的坡度就是其所有节点的坡度之和,递归计算每个节点的坡度。即求每个节点的左子树坡度和 与 右子树坡度和;
子树的坡度和 = 子树根节点值 + 子树左子树坡度和 + 子树右子树坡度之和;继续分解,直到分解到空树,空树的坡度为0,为递归出口。
sloution:
1)java Math.abs()方法求绝对值
class Solution {
public int findTilt(TreeNode root) {
if(root==null) return 0;
return Math.abs(s(root.left)-s(root.right)) +findTilt(root.left)+findTilt(root.right);
}
private int s(TreeNode root){
if(root == null) return 0;
return root.val + s(root.right) +s(root.left);
}
}
617. 合并二叉树
给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
题解:
递归:前序遍历的应用
sloution:
class Solution {
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
if (t1 == null && t2 == null) {
return null;}
TreeNode root = new TreeNode((t1 == null ? 0 : t1.val) + (t2 == null ? 0 : t2.val));
root.left = mergeTrees(t1 == null ? null : t1.left, t2 == null ? null : t2.left);
root.right = mergeTrees(t1 == null ? null : t1.right, t2 == null ? null : t2.right);
return root;
}
}
226. /27.翻转二叉树
题解:
1)递归
2)迭代:队列。只要这个队列不空,就一直从队列中出队节点,然后互换这个节点的左右孩子节点,接着再把孩子节点入队到队列,最后返回根节点
sloution:
1)递归 c++
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if (root == NULL) {
return NULL;
}
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
2)迭代 官方java
public TreeNode invertTree(TreeNode root) {
if (root == null) return null;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode current = queue.poll();
TreeNode temp = current.left;
current.left = current.right;
current.right = temp;
if (current.left != null) queue.add(current.left);
if (current.right != null) queue.add(current.right);
}
return root;
}
101. 对称二叉树
给定一个二叉树,检查它是否是镜像对称的。
题解:
1)递归 复杂度O(n)
2)迭代:引入队列,递归改写成迭代的常用方法。
每次pop两个结点比较值,再将两个结点的左右子结点按相反的顺序插入队列中。
sloution:
1)递归 java
class Solution {
public boolean isSymmetric(TreeNode root) {
return cmp(root,root);
}
private boolean cmp(TreeNode t1,TreeNode t2){
if(t1==null && t2==null) return true;
if(t1==null || t2==null) return false;
if(t1.val!=t2.val) return false;
return cmp(t1.left,t2.right) && cmp(t1.right,t2.left);
}
}
2)迭代 c++官方题解:
class Solution {
public:
bool check(TreeNode *u, TreeNode *v) {
queue <TreeNode*> q;
q.push(u); q.push(v);
while (!q.empty()) {
u = q.front(); q.pop();
v = q.front(); q.pop();
if (!u && !v) continue;
if ((!u || !v) || (u->val != v->val)) return false;
q.push(u->left);
q.push(v->right);
q.push(u->right);
q.push(v->left);
}
return true;
}
bool isSymmetric(TreeNode* root) {
return check(root, root);
}
};
222. 完全二叉树的节点个数
给出一个完全二叉树,求出该树的节点个数。
完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
即:一棵空树或者它的叶子节点只出在最后两层,若最后一层不满则叶子节点只在最左侧。
题解:
1)java递归 ->没有用到完全二叉树的性质
class Solution {
public int countNodes(TreeNode root) {
if(root==null) return 0;
return countNodes(root.left)+countNodes(root.right)+1;
}
}
2)定义左子树层高left,右子树层高right。
若相等,左子树是满二叉树,左子树的节点总数是2^left -1,加上当前这个root节点,则是2^left ,再对右子树进行递归统计。
否则右子树是满二叉树,右子树节点+root节点,总数为2^right。再对左子树进行递归查找。
注:位运算 左移相当于*2
class Solution {
public int countNodes(TreeNode root) {
if (root == null) {
return 0;
}
int left = countLevel(root.left);
int right = countLevel(root.right);
if (left == right) {
return countNodes(root.right) + (1 << left);
} else {
return countNodes(root.left) + (1 << right);
}
}
//计算层数
private int countLevel(TreeNode root) {
int level = 0;
while (root != null) {
level++;
root = root.left;
}
return level;
}
}
100. 相同的树
给定两个二叉树,编写一个函数来检验它们是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
题解:
递归 需要判断的三种
1、都为空、相同
2、一个空、一个非空,不同
3、都不为空但val不同
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p==null&&q==null) return true;
if(p!=null && q!=null && p.val==q.val){
return isSameTree(p.left,q.left) && isSameTree(p.right,q.right);
}
else return false;
}
}
572. 另一个树的子树
给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。
题解:
双递归
要么这两个树相等
要么这个树是左树的子树
要么这个树是右树的子树
sloution:
class Solution {
public boolean isSubtree(TreeNode s, TreeNode t) {
if (t==null) return true;
if (s==null) return false;
return isSubtree(s.right,t) || isSubtree(s.left,t) || isSameTree(s,t);
}
public boolean isSameTree(TreeNode s, TreeNode t){
if(s==null&t==null) return true;
if(s!=null && t!=null && s.val==t.val){
return isSameTree(s.left,t.left) && isSameTree(s.right,t.right);
}
else return false;
}
}
404.二叉搜索树的第k大节点
给定一棵二叉搜索树,找出其中第k大的节点。
题解:
1)中序遍历得到的序列是有序的(递增)
2)由题第k大则为中序遍历倒序:右根左 第k小:左根右
sloution:
1)中序遍历用ArrayList记录
class Solution {
public int kthLargest(TreeNode root, int k) {
List<Integer> list = new ArrayList<>();
helper(root, list);
return list.get(list.size() - k);
}
private void helper(TreeNode root, List<Integer> list) {
if (root == null) return;
if (root.left != null) helper(root.left, list);
list.add(root.val);
if (root.right != null) helper(root.right, list);
}
}
2)递归优化:遍历到第k大就停止
class Solution {
private int ans = 0, cnt = 0;
public int kthLargest(TreeNode root, int k) {
dfs(root, k);
return ans;
}
private void dfs(TreeNode root, int k) {
if(root == null) return ;
dfs(root.right, k);
if(++cnt == k) {
ans = root.val;
}
dfs(root.left, k);
}
}
3)迭代:利用栈