https://leetcode-cn.com/problems/climbing-stairs/
22. 括号生成
怎么检验合法性:
左括号随时可以加,只要不超过个数
右括号的个数必须小于等于左括号个数
这是递归,不是回溯。递归只需要每次往下走一层,回溯还需要剪枝
class Solution {
List<String> result = new ArrayList<>();
public List<String> generateParenthesis(int n) {
generate(n, 0, 0, "");
return result;
}
public void generate(int n, int left, int right, String s) {
if (left == n && right == n) { // 递归结束条件左右括号数都等于n
result.add(s);
return;
}
if (left < n) { // 如果左括号数小于n,加左括号
generate(n, left + 1, right, s + '(');
}
if (right < left) { // 如果右括号数小于左括号数,加右括号
generate(n, left, right + 1, s + ')');
}
}
}
590. N 叉树的后序遍历
class Solution {
List<Integer> res = new ArrayList<>();
public List<Integer> postorder(Node root) {
// 结束条件
if (root == null) {
return new ArrayList<>();
}
// 需要做的操作
for (Node n : root.children) { // 遍历子节点
postorder(n);
}
res.add(root.val); // 遍历完子节点后,把root加入res
return res;
}
}
226. 翻转二叉树
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
TreeNode left = invertTree(root.right);
TreeNode right = invertTree(root.left);
root.left = left;
root.right = right;
return root;
}
}
98. 验证二叉搜索树
class Solution {
public boolean isValidBST(TreeNode root) {
if (root == null) {
return true;
}
Stack<TreeNode> stack = new Stack<>();
long pre = Long.MIN_VALUE;
while (!stack.isEmpty() || root != null) {
if (root != null) {
stack.push(root);
root = root.left;
} else {
root = stack.pop();
if (pre >= root.val) {
return false;
}
pre = root.val;
root = root.right;
}
}
return true;
}
}
104. 二叉树的最大深度
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return left > right ? left + 1 : right + 1;
}
}
111. 二叉树的最小深度
class Solution {
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
int left = minDepth(root.left);
int right = minDepth(root.right);
if (left == 0 && right == 0) { // root是叶子节点
return 1;
} else if (left == 0) { // 如果root左为空
return right + 1;
} else if (right == 0) { // 如果root右为空
return left + 1;
} else { // 如果root左右都不为空
return left > right ? right + 1 : left + 1;
}
}
}
297. 二叉树的序列化与反序列化
- 序列化:通过层序遍历,序列化成字符串
- 反序列化:先把字符串分割成数组,然后把数组放进队列中,通过递归构造二叉树。
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) {
return "#_";
}
String res = "";
res += root.val;
res += "_";
res += serialize(root.left);
res += serialize(root.right);
return res;
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
String[] strings = data.split("_");
Deque<String> queue = new LinkedList<>();
for (int i = 0; i < strings.length; i++) {
queue.add(strings[i]);
}
return recur(queue);
}
public TreeNode recur(Deque<String> queue) {
if (queue.isEmpty()) {
return null;
}
String s = queue.poll();
if (s.equals("#")) {
return null;
}
TreeNode root = new TreeNode(Integer.valueOf(s));
root.left = recur(queue);
root.right = recur(queue);
return root;
}
}
236. 二叉树的最近公共祖先
有三种情况
- p、q在root两端
- p = root,且 q 在 root 的左或右子树中
- q = root,且 p 在 root 的左或右子树中
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root == null) {
return root;
}
if (root == p || root == q) {
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if (left != null && right != null) {
return root;
} else if (left != null) {
return left;
} else {
return right;
}
}
}
105. 从前序与中序遍历序列构造二叉树
前序:【根,[左子树的前序遍历结果],[右子树的前序遍历结果]】
中序:【[左子树的中序遍历结果],根,[右子树的中序遍历结果]】
class Solution {
// 把中序遍历的值和下标放进map中,方便定位
Map<Integer, Integer> map = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
for (int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i); // 把中序遍历的值和下标放进map中,方便定位
}
return buildTreeHelp(preorder, inorder, 0, preorder.length - 1, 0, inorder.length - 1);
}
// 参数:前序遍历和中序遍历的范围
public TreeNode buildTreeHelp(int[] preorder, int[] inorder, int preLeft, int preRight, int inLeft, int inRight) {
if (preLeft > preRight) {
return null;
}
// 前序遍历第一个节点就是根节点
int rootVal = preorder[preLeft];
// 新建根节点
TreeNode root = new TreeNode(rootVal);
// 在中序遍历中定位根节点
int inRoot = map.get(rootVal);
// 左子树的数量
int leftSize = inRoot - inLeft;
TreeNode left = buildTreeHelp(preorder, inorder, preLeft + 1, preLeft + leftSize, inLeft, inRoot - 1);
TreeNode right = buildTreeHelp(preorder, inorder, preLeft + leftSize + 1, preRight, inRoot + 1, inRight);
root.left = left;
root.right = right;
return root;
}
}