Skip to content

Commit 28fc8d1

Browse files
author
anduo
committed
binary tree & divide conqueer & dfs / bfs
1 parent f2fe778 commit 28fc8d1

15 files changed

+711
-2
lines changed

readme.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,22 @@ doc中有好几份文档,比较经典,可以参考。
184184

185185
# 刷题总结
186186

187+
## chapter01 基础编程面试总结
188+
**面试考察的编程基本功**
189+
190+
- 程序风格(缩进,括号,变量名)
191+
- Coding习惯(异常检查,边界处理)
192+
- 沟通(让面试官时刻明白你的意图)
193+
- 测试(主动写出合理的Testcase)
194+
195+
**算法其实很简单**
196+
197+
- 在刷题时,总结、归类相似题目
198+
- 找出适合同一类题目的模板程序
199+
200+
**排列组合模板**
201+
202+
187203
## chapter02 binary search & sorted array
188204
这一部分都可以使用bs模板来解决问题 [二分搜索模板](./src/template/bs_template.md)
189205

@@ -221,4 +237,25 @@ doc中有好几份文档,比较经典,可以参考。
221237
3. Find Median in Two Sorted Array **find kth**
222238
4. Reverse in 3 steps
223239

240+
## chapter03 Binary Tree & Divide Conquer & DFS/BFS
241+
242+
*任何二叉树的问题都可以尝试使用分治法解决*
243+
244+
二叉树的遍历问题,递归转为非递归的写法都是使用人工栈模拟系统栈的方式
245+
246+
宽度优先遍历的方法
247+
- 2 Queues
248+
- 1 Queues + Dummy Node
249+
- 1 Queues(best)
250+
251+
**参考模板** [dfs_template](./src/template/dfs_template.md)
252+
253+
- [question01 binary tree preorder traversal](./src/ninechapter/ch03_binary_tree_and_divide_conquer_and_dfs_bfs/Question01BinaryTreePreorderTraversal.java)
254+
- [question02 maximum depth of binary tree](./src/ninechapter/ch03_binary_tree_and_divide_conquer_and_dfs_bfs/Question02MaximumDepthOfBinaryTree.java)
255+
- [question03 balanced binary tree](./src/ninechapter/ch03_binary_tree_and_divide_conquer_and_dfs_bfs/Question03BalancedBinaryTree.java)
256+
- [question04 binary tree maximum path sum](./src/ninechapter/ch03_binary_tree_and_divide_conquer_and_dfs_bfs/Question04BinaryTreeMaximumPathSum.java)
257+
258+
259+
260+
224261

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package ninechapter.ch01;
2+
3+
/**
4+
* Created by anduo on 17-3-13.
5+
*/
6+
public class Question01StrStr {
7+
8+
// 模式匹配算法总结 http://dsqiu.iteye.com/blog/1700312
9+
// 需要知道概念和原理
10+
public int strStr(String source, String target) {
11+
if (source == null || target == null) {
12+
return -1;
13+
}
14+
int i, j;
15+
16+
// source最多比较的字符个数应该是 len(source) - len(target)
17+
int range = source.length() - target.length();
18+
for (i = 0; i < range; i++) {
19+
for (j = 0; j < target.length(); j++) {
20+
// 如果存在滑动窗口内的对应位置元素不相同,就将source的字符往下移动
21+
if (source.charAt(i + j) != target.charAt(j)) {
22+
break;
23+
}
24+
}
25+
if (j == target.length()) {// 全部匹配完成
26+
return i;
27+
}
28+
}
29+
30+
return -1;
31+
}
32+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package ninechapter.ch01;
2+
3+
import java.util.ArrayList;
4+
import java.util.Arrays;
5+
6+
/**
7+
* Created by anduo on 17-3-13.
8+
*/
9+
public class Question02SubSets {
10+
11+
public ArrayList<ArrayList<Integer>> subsets(int[] nums) {
12+
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
13+
if (nums == null || nums.length == 0) {
14+
return result;
15+
}
16+
ArrayList<Integer> list = new ArrayList<>();
17+
18+
// 先把集合排序 nlog(n)
19+
Arrays.sort(nums);
20+
21+
dfs(result, list, nums, 0);
22+
return result;
23+
}
24+
25+
/**
26+
* 构造子集合
27+
*
28+
* @param result
29+
* @param list
30+
* @param num
31+
* @param pos
32+
*/
33+
private void dfs(ArrayList<ArrayList<Integer>> result,
34+
ArrayList<Integer> list,
35+
int[] num,
36+
int pos) {
37+
result.add(new ArrayList<>(list));
38+
// 从nums的pos位置开始,先把自己加进去,然后把自己的子集合加进去
39+
for (int i = pos; i < num.length; i++) {
40+
list.add(num[i]);
41+
dfs(result, list, num, i + 1);
42+
list.remove(list.size() - 1);// 需要移除最后一个元素
43+
}
44+
}
45+
46+
47+
// 非递归解法
48+
public ArrayList<ArrayList<Integer>> subsetsNoRecursion(int[] nums) {
49+
ArrayList<ArrayList<Integer>> result = new ArrayList<>();
50+
int n = nums.length;
51+
Arrays.sort(nums);
52+
53+
// 1 << n is 2^n
54+
// each subset equals to an binary integer between 0 .. 2^n - 1
55+
// 0 -> 000 -> []
56+
// 1 -> 001 -> [1]
57+
// 2 -> 010 -> [2]
58+
// ..
59+
// 7 -> 111 -> [1,2,3]
60+
61+
int total = 1 << n;// 一共有2^n个子集合
62+
for (int i = 0; i < total; i++) {
63+
ArrayList<Integer> subset = new ArrayList<>();
64+
for (int j = 0; j < n; j++) {
65+
// check whether the jth digit in i's binary representation is 1
66+
if ((i & (1 << j)) != 0) {
67+
subset.add(nums[j]);
68+
}
69+
}
70+
result.add(subset);
71+
}
72+
73+
return result;
74+
}
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package ninechapter.ch03_binary_tree_and_divide_conquer_and_dfs_bfs;
2+
3+
import entity.TreeNode;
4+
5+
import java.util.ArrayList;
6+
import java.util.Stack;
7+
8+
// 1
9+
// \
10+
// 2
11+
// /
12+
// 3
13+
// result: 1->2->3
14+
15+
/**
16+
* http://www.lintcode.com/problem/binary-tree-preorder-traversal
17+
* 二叉树的前序遍历
18+
* Created by anduo on 17-3-13.
19+
*/
20+
public class Question01BinaryTreePreorderTraversal {
21+
// 非递归算法 Non-Recursion (Recommend)
22+
public ArrayList<Integer> preorderTraversal1(TreeNode root) {
23+
ArrayList<Integer> result = new ArrayList<>();
24+
if (root == null) {
25+
return result;
26+
}
27+
Stack<TreeNode> stack = new Stack<>();
28+
stack.push(root);
29+
while (!stack.empty()) {
30+
TreeNode node = stack.pop();
31+
result.add(node.val);
32+
if (node.left != null) {
33+
stack.push(node.left);
34+
}
35+
if (node.right != null) {
36+
stack.push(node.right);
37+
}
38+
}
39+
return result;
40+
}
41+
42+
// version2 递归解法
43+
public ArrayList<Integer> preorderTraversal2(TreeNode root) {
44+
ArrayList<Integer> result = new ArrayList<>();
45+
if (root == null) {
46+
return result;
47+
}
48+
traverse(root, result);
49+
return result;
50+
}
51+
52+
private void traverse(TreeNode root, ArrayList<Integer> result) {
53+
if (root == null) return;
54+
result.add(root.val);
55+
traverse(root.left, result);
56+
traverse(root.right, result);
57+
}
58+
59+
/***************************************************************/
60+
// version3 : divide & conquer
61+
// 分治法
62+
// Merge Sort:局部有序,然后整体有序
63+
// Quick Sort:整体有序,然后局部有序
64+
// Most of the Binary Tree Problem!
65+
public ArrayList<Integer> preorderTraversal3(TreeNode root) {
66+
ArrayList<Integer> result = new ArrayList<>();
67+
if (root == null) {
68+
return result;
69+
}
70+
71+
// Divide
72+
ArrayList<Integer> left = preorderTraversal3(root.left);
73+
ArrayList<Integer> right = preorderTraversal3(root.right);
74+
75+
// Conquer
76+
result.add(root.val);
77+
result.addAll(left);
78+
result.addAll(right);
79+
return result;
80+
81+
82+
}
83+
84+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package ninechapter.ch03_binary_tree_and_divide_conquer_and_dfs_bfs;
2+
3+
import entity.TreeNode;
4+
5+
//二叉树的最大深度
6+
// 1
7+
// / \
8+
// 2 3
9+
// / \
10+
// 4 5
11+
12+
/**
13+
* http://www.lintcode.com/problem/maximum-depth-of-binary-tree
14+
* <p>
15+
* Created by anduo on 17-3-13.
16+
*/
17+
public class Question02MaximumDepthOfBinaryTree {
18+
19+
public int maxDepth(TreeNode root) {
20+
if (root == null) return 0;
21+
if (root.left == null && root.right == null) {
22+
return 1;
23+
}
24+
// 分治法
25+
int leftDepth = maxDepth(root.left);
26+
int rightDepth = maxDepth(root.right);
27+
return Math.max(leftDepth, rightDepth) + 1;
28+
}
29+
30+
31+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package ninechapter.ch03_binary_tree_and_divide_conquer_and_dfs_bfs;
2+
3+
// <h1>平衡二叉树</h1>
4+
// 给定一个二叉树,确定它是高度平衡的。
5+
// 对于这个问题,一棵高度平衡的二叉树的定义是:
6+
// 一棵二叉树中每个节点的两个子树的深度相差不会超过1。
7+
// A) 3 B) 3
8+
// / \ \
9+
// 9 20 20
10+
// / \ / \
11+
// 15 7 15 7
12+
// 二叉树A是高度平衡的二叉树,但是B不是
13+
14+
import entity.TreeNode;
15+
16+
/**
17+
* http://www.lintcode.com/zh-cn/problem/balanced-binary-tree/
18+
* Created by anduo on 17-3-13.
19+
*/
20+
public class Question03BalancedBinaryTree {
21+
/**
22+
* @param root: The root of binary tree.
23+
* @return: True if this Binary tree is Balanced, or false.
24+
*/
25+
public boolean isBalanced(TreeNode root) {
26+
return height(root) != -1;
27+
}
28+
29+
private int height(TreeNode root) {
30+
if (root == null) return 0;
31+
int leftHeight = height(root.left);
32+
int rightHeight = height(root.right);
33+
if (leftHeight == -1 || rightHeight == -1 || Math.abs(leftHeight - rightHeight) > 1) {
34+
return -1;
35+
}
36+
return Math.max(leftHeight, rightHeight) + 1;
37+
}
38+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package ninechapter.ch03_binary_tree_and_divide_conquer_and_dfs_bfs;
2+
3+
// 二叉树中的最大路径和
4+
// 给出一棵二叉树,寻找一条路径使其路径和最大,
5+
// 路径可以在任一节点中开始和结束(路径和为两个节点之间所在路径上的节点权值之和)
6+
// 1
7+
// / \
8+
// 2 3
9+
// 返回 6
10+
11+
import entity.TreeNode;
12+
13+
import static java.lang.Math.max;
14+
15+
/**
16+
* http://www.lintcode.com/zh-cn/problem/binary-tree-maximum-path-sum/
17+
* Created by anduo on 17-3-13.
18+
*/
19+
// TODO(分治法的最高境界)
20+
public class Question04BinaryTreeMaximumPathSum {
21+
22+
private class ResultType {
23+
// singlePath: 从root往下走到任意点的最大路径,这条路径可以不包含任何点
24+
// maxPath: 从树中任意到任意点的最大路径,这条路径至少包含一个点
25+
int singlePath, maxPath;
26+
27+
ResultType(int singlePath, int maxPath) {
28+
this.singlePath = singlePath;
29+
this.maxPath = maxPath;
30+
}
31+
}
32+
33+
private ResultType help(TreeNode root) {
34+
if (root == null) {// 极端情况
35+
return new ResultType(0, Integer.MIN_VALUE);
36+
}
37+
// Divide
38+
ResultType left = help(root.left);
39+
ResultType right = help(root.right);
40+
41+
// Conquer
42+
// 合并从root开始往下走的路径和
43+
int singlePath = max(left.singlePath, right.singlePath) + root.val;
44+
singlePath = max(singlePath, 0);
45+
46+
// 当前节点到左右子树的最大路径
47+
int maxPath = max(left.maxPath, right.maxPath);
48+
// 当前节点跨根节点的最大路径
49+
maxPath = max(maxPath, left.singlePath + right.singlePath + root.val);
50+
51+
return new ResultType(singlePath, maxPath);
52+
}
53+
54+
public int maxPathSum(TreeNode root) {
55+
// 分治法
56+
// 三种情况:
57+
// 1、左子树
58+
// 2、右子树
59+
// 3、跨根节点
60+
61+
ResultType result = help(root);
62+
return result.maxPath;
63+
}
64+
}

0 commit comments

Comments
 (0)