剑指Offer 55-I.二叉树的深度
解析过程:
要判断数的深度,那么只需要知道左子树和右子树的深度哪个最大,然后再加上根结点,即为数的深度,所以此时找到递归的终止条件,也就是当root为空时,则return 0,否则继续向下查找。
代码实现:
class Solution {
public int maxDepth(TreeNode root) {
if(root == null)return 0;
return Math.max(maxDepth(root.left)+1,maxDepth(root.right)+1);
}
}
剑指Offer 55-II.平衡二叉树
解析过程:
解题的时候要注意,一定不要去想递归是怎么个递归法,然后脑回路跟着往下走,这样的话,容易陷进去。
题目要求说左右子树深度相差不超过1,那就简单了,我们刚不是写过深度问题吗?那我就去判断一下当前结点的左右子树深度差值是否超过1,然后继续向下判断就好了。
代码实现:
class Solution {
public boolean isBalanced(TreeNode root) {
if(root == null)return true;
return Math.abs(depth(root.left)-depth(root.right)) <= 1 && isBalanced(root.left) && isBalanced(root.right);
}
public static int depth(TreeNode root){
if(root == null)return 0;
return Math.max(depth(root.left)+1,depth(root.right)+1);
}
}
剑指Offer 34.二叉树中和为某一值的路径
解析过程:
每次看到链表嵌套的题目都感觉不简单呐!
解析题目有两个步骤:
第一步:从根节点往下遍历,遍历的同时对target和遍历过的结点值进行相减,将所有路径都遍历一遍。
第二步:对遍历到叶子结点进行条件判断,查看遍历到这里时,是否刚好减到0,并且也要查看该节点是否就为叶子结点。
注:需要维护两个链表,一个是嵌套链表,也就是需要返回的链表,一个是存储路径的链表。
代码实现:
class Solution {
LinkedList<List<Integer>> res = new LinkedList<>();
LinkedList<Integer> list = new LinkedList<>();
public List<List<Integer>> pathSum(TreeNode root, int target) {
resMethod(root,target);
return res;
}
void resMethod(TreeNode root,int target){
if(root == null) return;
list.add(root.val);
target -= root.val;
if(target == 0 && root.left == null && root.right == null){
res.add(new LinkedList(list));
}
resMethod(root.left,target);
resMethod(root.right,target);
list.removeLast();
}
}
剑指Offer 12.矩阵中的路径
解析过程:
首先这道题包含了很多种可能性,但是我们都可以归总为一种,就是对某一个位置开始搜索,那么就只有上下左右四种可能,如果索引越界或者是字符不相同,则代表从该位置开始搜索行不通。
为了防止搜索过的位置再次被遍历,那么我们就可以对其进行特殊值设置,因为题目中说到word是一个单词,我们就可以认为它只包含字母,所以这里我将特殊值设置为零。当然在递归返回的时候我们需要将其再设置回来,这里不要将思维绕进去,我们是判断了字符相同才对其进行特殊值修改的,所以再设置回来时,只需要word对应位置的字符赋值给它就好了。
刚才说的是对于某一个位置开始的搜索。那么对于整个矩阵中的所有位置都是我们可能进行搜索的开始位置,所以用嵌套循环就解决了!
代码实现:
class Solution {
public boolean exist(char[][] board, String word) {
char[] charWord = word.toCharArray();
for(int i = 0;i < board.length;i++){
for(int j = 0;j < board[0].length;j++){
if(dfs(board,charWord,i,j,0))return true;
}
}
return false;
}
public static boolean dfs(char[][] board,char[] charWord,int i,int j,int k){
if(i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != charWord[k]) return false;
if(k == charWord.length - 1) return true;
board[i][j] = '0';
boolean res = dfs(board,charWord,i+1,j,k+1) || dfs(board,charWord,i,j+1,k+1) || dfs(board,charWord,i-1,j,k+1) || dfs(board,charWord,i,j-1,k+1);
board[i][j] = charWord[k];
return res;
}
}
剑指Offer 26.树的子结构
解析过程:
首先,题目说明了空树不是任意一个树的子结构,所以当A为空或者B为空则一定是false。那么要判断B是不是A的子结构,就一共有三种情况,第一,根节点就是子结构B的开始,第二,子结构B在左子树中,第三,子结构B在右子树中。
找到了开始位置,那么如何判断两个结构相同呢?根相同,左子树相同,右子树相同,即相同。那么如果已经判断到B==null了,就代表为真,如果A空了,B还没有空,或者是A和B的值不同,那么就一定为假了。
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
return (A != null && B != null) && (method(A,B) || isSubStructure(A.left,B) || isSubStructure(A.right,B));
}
public static boolean method(TreeNode A,TreeNode B){
if(B == null) return true;
if(A == null || A.val != B.val) return false;
return method(A.left,B.left) && method(A.right,B.right);
}
}