代码随想录第十八天

复习

前中后序递归

以前序为例

前序: 中左右
中序: 左中右
后序: 左右中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
List<Integer> result = new ArrayList<>();

public List<Integer> preorderTraversal(TreeNode root) {
preorder(root);
return result;
}

public void preorder(TreeNode root){
if (root == null) return;
result.add(root.val);
preorder(root.left);
preorder(root.right);
}
}

前中后序统一迭代

以中序为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
List<Integer> result = new ArrayList();
public List<Integer> inorderTraversal(TreeNode root) {
if (root == null) return result;

Stack<TreeNode> stack = new Stack<>();

stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();

if (node != null){
if (node.right != null) stack.push(node.right);
stack.push(node);
stack.push(null);
if (node.left != null) stack.push(node.left);
} else {
result.add(stack.pop().val);
}
}

return result;
}
}

前序迭代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();

if (root == null) return result;

Stack<TreeNode> stack = new Stack<>();

stack.push(root);

while (!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);

if (node.right != null) stack.push(node.right);
if (node.left != null) stack.push(node.left);
}

return result;
}
}

中序迭代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {

public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null) return result;

Stack<TreeNode> stack = new Stack<>();

TreeNode cur = root;

while (cur != null || !stack.isEmpty()){
if (cur != null){
stack.push(cur);
cur = cur.left;
} else {
cur = stack.pop();
result.add(cur.val);
cur = cur.right;
}
}

return result;
}
}

后序迭代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null) return result;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);

while (!stack.isEmpty()){
TreeNode node = stack.pop();
result.add(node.val);
if (node.left != null) stack.push(node.left);
if (node.right != null) stack.push(node.right);
}

Collections.reverse(result);
return result;
}
}

DFS 层序打出数个数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> levelOrder(TreeNode root) {
dfs(root, 0);

return result;
}

public void dfs(TreeNode root, int depth){
if (root == null) return;
depth++;
if (result.size() < depth){
result.add(new ArrayList<Integer>());
}
result.get(depth - 1).add(root.val);

if (root.left != null) dfs(root.left, depth);
if (root.right != null) dfs(root.right, depth);
}
}

BFS 层序遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
if (root == null) return result;
Queue<TreeNode> queue = new ArrayDeque<>();
queue.add(root);
while (!queue.isEmpty()){
int length = queue.size();
List<Integer> itemList = new ArrayList<>();

while (length-- > 0){
TreeNode node = queue.poll();
itemList.add(node.val);
if (node.left != null) queue.add(node.left);
if (node.right != null) queue.add(node.right);
}
result.add(itemList);
}

return result;
}
}

翻转二叉树

前序和后序都可,中序不可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) return null;
swapChildren(root);
invertTree(root.left);
invertTree(root.right);
return root;
}

public void swapChildren(TreeNode node){
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
}
}

前序统一迭代法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) return null;

Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();
if (node != null){
if(node.right != null) stack.push(node.right);
if (node.left != null) stack.push(node.left);
stack.push(node);
stack.push(null);
} else {
swapChildren(stack.pop());
}
}

return root;
}

public void swapChildren(TreeNode node){
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
}
}

层序迭代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) return null;

Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
int length = queue.size();
while (length-- > 0){
TreeNode node = queue.poll();
swapChildren(node);
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
}

return root;
}

public void swapChildren(TreeNode node){
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
}
}

对称二叉树

注意对比过程和递归过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

class Solution {
public boolean isSymmetric(TreeNode root) {
if (root == null) return false;
return compare(root.left, root.right);
}

public boolean compare(TreeNode left, TreeNode right){
if (left == null && right == null) return true;
if (left == null || right == null || left.val != right.val) return false;

boolean compareOutside = compare(left.left, right.right);
boolean compareInside = compare(left.right, right.left);
return compareOutside && compareInside;
}
}

迭代法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

class Solution {
public boolean isSymmetric(TreeNode root) {
if (root == null) return false;
Queue<TreeNode> queue = new LinkedList<>();

queue.offer(root.left);
queue.offer(root.right);

while (!queue.isEmpty()){
TreeNode left = queue.poll();
TreeNode right = queue.poll();

if (left == null && right == null) continue;
if (left == null || right == null || left.val != right.val) return false;

queue.offer(left.left);
queue.offer(right.right);
queue.offer(left.right);
queue.offer(right.left);
}

return true;

}
}

二叉树最大深度

此为后序遍历 递归

1
2
3
4
5
6
7
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) return 0;
return 1 + Math.max(maxDepth(root.left), maxDepth(root.right));
}
}

前序递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
int depth = 0;
public int maxDepth(TreeNode root) {
if (root == null) return 0;
getDepth(root, 0);
return depth;
}
public void getDepth(TreeNode node, int deep){
if (node == null) return;
deep++;
depth = Math.max(deep,depth);
if (node.left != null) getDepth(node.left, deep);
if (node.right != null) getDepth(node.right, deep);
}
}

层序遍历迭代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

class Solution {
public int maxDepth(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> queue= new LinkedList<>();
queue.offer(root);
int depth = 0;
while (!queue.isEmpty()){
depth++;
int length = queue.size();
while(length-- > 0){
TreeNode node = queue.poll();
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
}

return depth;
}
}

二叉树的最小深度

前序求深度,后序求高度

层序遍历到第一个叶子结点的层数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
public int minDepth(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int depth = 0;
while(!queue.isEmpty()){
int length = queue.size();
depth++;
while (length-- > 0){
TreeNode node = queue.poll();
if (node.left == null && node.right == null){
return depth;
}
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
}

return depth;
}
}

递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public int minDepth(TreeNode root) {
if (root == null) return 0;
return getDepth(root);
}

public int getDepth(TreeNode root){
if (root == null) return 0;
int leftDepth = getDepth(root.left);
int rightDepth = getDepth(root.right);

if (root.left == null && root.right != null) return 1 + rightDepth;
if (root.left != null && root.right == null) return 1 + leftDepth;

int result = 1 + Math.min(leftDepth, rightDepth);

return result;
}
}

完全二叉树的节点个数

递归, 后序递归

1
2
3
4
5
6
7
class Solution {
public int countNodes(TreeNode root) {
if (root == null) return 0;
return 1 + countNodes(root.left) + countNodes(root.right);
}
}

层级遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public int countNodes(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int sum = 0;
while(!queue.isEmpty()){
int length = queue.size();
sum += length;
while (length-- > 0){
TreeNode node = queue.poll();
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
}

return sum;
}
}

完全二叉树性质

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
public int countNodes(TreeNode root) {
if (root == null) return 0;

TreeNode left = root.left;
TreeNode right = root.right;

int leftDepth = 0;
int rightDepth = 0;

while (left != null){
left = left.left;
leftDepth++;
}

while (right != null){
right = right.right;
rightDepth++;
}

if (leftDepth == rightDepth){
return (2 << leftDepth) - 1;
}

return 1 + countNodes(root.left) + countNodes(root.right);
}
}

平衡二叉树

因为要求高度,则需要后序遍历
递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

class Solution {
public boolean isBalanced(TreeNode root) {
return getHeight(root) != -1;
}

public int getHeight(TreeNode node){
if (node == null) return 0;
int leftHeight = getHeight(node.left);

if (leftHeight == -1) return -1;
int rightHeight = getHeight(node.right);

if (rightHeight == -1) return -1;

if (Math.abs(leftHeight - rightHeight) > 1){
return -1;
}
return 1 + Math.max(leftHeight, rightHeight);
}
}

二叉树的所有路径

要测路径就要用前序遍历

递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> result = new ArrayList<>();
List<Integer> paths = new ArrayList<>();
getPaths(root, result, paths);
return result;
}
public void getPaths(TreeNode root, List<String> result, List<Integer> paths){
paths.add(root.val);

if (root.left == null && root.right == null){
StringBuilder sb = new StringBuilder();

for (int i = 0; i < paths.size() - 1; i++){
sb.append(paths.get(i)).append("->");
}
sb.append(paths.get(paths.size() - 1));
result.add(sb.toString());
return;
}

if (root.left != null) {
getPaths(root.left, result, paths);
paths.remove(paths.size() - 1);
}

if (root.right != null){
getPaths(root.right, result, paths);
paths.remove(paths.size() - 1);
}
}
}

左叶子之和

需要通过父节点查看左叶子结点是不是叶子结点
前序遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
int sum = 0;
public int sumOfLeftLeaves(TreeNode root) {
if (root == null) return 0;
if (root.left == null && root.right == null) return 0;
if (root.left != null && root.left.left == null && root.left.right == null){
sum += root.left.val;
}

if (root.left != null) sumOfLeftLeaves(root.left);
if (root.right != null) sumOfLeftLeaves(root.right);
return sum;
}
}

后序遍历迭代

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

class Solution {
public int sumOfLeftLeaves(TreeNode root) {
if (root == null) return 0;

Stack<TreeNode> stack = new Stack<>();

stack.push(root);
int sum = 0;
while(!stack.isEmpty()){
TreeNode node = stack.pop();

if (node.left != null){
if (node.left.left == null && node.left.right == null){
sum += node.left.val;
}
stack.push(node.left);
}
if (node.right != null){
stack.push(node.right);
}
}

return sum;
}
}

513 找树左下角的值

层序遍历经典题目

迭代法
更新最左边的值指到遍历所有层,获得结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

class Solution {
public int findBottomLeftValue(TreeNode root) {
if (root == null) return 0;
int result = 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);

while (!queue.isEmpty()){
int length = queue.size();
for (int i = 0; i < length; i++){
TreeNode node = queue.poll();
if (i == 0) result = node.val;
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
}
return result;
}
}

DFS模版

注意判断最大depth的值和更新result的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {

int result = 0;
int maxDepth = 0;
public int findBottomLeftValue(TreeNode root) {
traversal(root, 0);
return result;
}

public void traversal(TreeNode root, int depth){
if (root == null) return;
depth++;
if (root.left == null && root.right == null){
if (depth > maxDepth){
maxDepth = depth;
result = root.val;
}
}

if (root.left != null) traversal(root.left, depth);
if (root.right != null) traversal(root.right, depth);
}

}

路径总和

自己写的办法,利用找path的迭代方法,找出总和等不等于的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Solution {
boolean hasPath = false;
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) return hasPath;
List<Integer> paths = new ArrayList<>();
getPathSum(root, paths, targetSum);

return hasPath;
}

public void getPathSum(TreeNode node, List<Integer> paths, int targetSum){
paths.add(node.val);
if (node.left == null && node.right == null){
int sum = 0;
for (int i : paths){
sum += i;
}

if (sum == targetSum){
hasPath = true;
return;
}
}

if (node.left != null) {
getPathSum(node.left, paths, targetSum);
paths.remove(paths.size() - 1);
}

if (node.right != null) {
getPathSum(node.right, paths, targetSum);
paths.remove(paths.size() - 1);
}
}
}

不需要确定path的方法,只需要计算等不等于targetsum

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) return false;

targetSum -= root.val;

if (root.left == null && root.right == null){
if (targetSum == 0) return true;
}

if (root.left != null){
boolean left = hasPathSum(root.left, targetSum);
if (left) return true;
}

if (root.right != null){
boolean right = hasPathSum(root.right, targetSum);
if (right) return true;
}

return false;
}
}

迭代法先跳过
利用前序遍历,先推中间,再右,再左
用两个stack,一个记录node,一个记录sum值,找到就返回true

113 路径之和II

自己写的办法,利用找path的迭代方法,并能打印出path

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

class Solution {
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
if (root == null) return result;
List<Integer> paths = new ArrayList<>();

getPaths(root, paths, targetSum);

return result;
}
public void getPaths(TreeNode root, List<Integer> paths, int targetSum){
paths.add(root.val);
if (root.left == null && root.right == null){
int sum = 0;
for (int i : paths){

sum += i;
}

if (sum == targetSum){
result.add(new ArrayList<>(paths));
}
return;
}

if (root.left != null){
getPaths(root.left, paths, targetSum);
paths.remove(paths.size() - 1);

}
if (root.right != null){
getPaths(root.right, paths, targetSum);
paths.remove(paths.size() - 1);
}
}

}

优化,不用for loop判断targetsum
利用递归参与到判断targetSum中

targetSum - root.val;
每次都减去root.val;
不用记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
if (root == null) return result;
List<Integer> paths = new ArrayList<>();

getPaths(root, paths, targetSum);

return result;
}
public void getPaths(TreeNode root, List<Integer> paths, int targetSum){
paths.add(root.val);
if (root.left == null && root.right == null){

if (targetSum - root.val == 0){
result.add(new ArrayList<>(paths));
}
return;
}

if (root.left != null){
getPaths(root.left, paths, targetSum-root.val);
paths.remove(paths.size() - 1);

}
if (root.right != null){
getPaths(root.right, paths, targetSum-root.val);
paths.remove(paths.size() - 1);
}
}

}

从中序与后序遍历序列构造二叉树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (postorder.length == 0 || inorder.length == 0){
return null;
}

return buildHelper(inorder, 0 , inorder.length, postorder, 0, postorder.length);
}

public TreeNode buildHelper(int[] inorder, int inStart, int inEnd, int[] postorder, int postStart, int postEnd){
if (postStart == postEnd){
return null;
}

int rootVal = postorder[postEnd - 1];
TreeNode node = new TreeNode(rootVal);

int middleIndex;
for (middleIndex = 0; middleIndex < inEnd; middleIndex++){
if (inorder[middleIndex] == rootVal) break;
}

int leftInStart = inStart;
int leftInEnd = middleIndex;
int rightInStart = middleIndex + 1;
int rightInEnd = inEnd;

int leftPostStart = postStart;
int leftPostEnd = postStart + (middleIndex - inStart);
int rightPostStart = leftPostEnd;
int rightPostEnd = postEnd - 1;

node.left = buildHelper(inorder, leftInStart, leftInEnd, postorder, leftPostStart, leftPostEnd);
node.right = buildHelper(inorder, rightInStart, rightInEnd, postorder, rightPostStart, rightPostEnd);

return node;
}
}

利用map查找index 更省时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

class Solution {
Map<Integer, Integer> map = new HashMap<>();
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (inorder.length == 0) return null;
for (int i = 0; i < inorder.length; i++){
map.put(inorder[i], i);
}

return buildHelper(inorder, 0, inorder.length, postorder, 0, postorder.length);
}

private TreeNode buildHelper(int[] inorder, int inS, int inE, int[] postorder, int postS, int postE){
if (inS == inE || postS == postE) return null;
int rootValue = postorder[postE - 1];
TreeNode node = new TreeNode(rootValue);
int rootIndex = map.get(rootValue);
int lenOfLeft = rootIndex - inS;
node.left = buildHelper(inorder, inS, rootIndex, postorder, postS, postS + lenOfLeft);
node.right = buildHelper(inorder, rootIndex + 1, inE, postorder, postS + lenOfLeft, postE - 1);
return node;
}
}

从前序与中序遍历序列构造二叉树

通过递归注意边界
通过map查找更快

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

class Solution {
Map<Integer, Integer> map = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder.length == 0) return null;

for(int i = 0; i < inorder.length; i++){
map.put(inorder[i], i);
}

return buildHelper(preorder, 0, preorder.length, inorder, 0, inorder.length);
}

public TreeNode buildHelper(int[] preorder, int preS, int preE, int[] inorder, int inS, int inE){
if (preS >= preE || inS >= inE) return null;

int rootVal = preorder[preS];
TreeNode root = new TreeNode(rootVal);
int midIndex = map.get(rootVal);
int lenOfLeft = midIndex - inS;

root.left = buildHelper(preorder, preS + 1, preS + lenOfLeft + 1, inorder, inS, midIndex);
root.right = buildHelper(preorder, preS + lenOfLeft + 1, preE, inorder, midIndex + 1, inE);
return root;
}
}