Skip to content

Commit 8ba7a25

Browse files
authored
Add files via upload
1 parent 34e432d commit 8ba7a25

8 files changed

+1395
-0
lines changed

二叉树.md

+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
## *.重建二叉树
2+
```
3+
问题描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
4+
```
5+
```
6+
解析:这个问题的关键在于知晓前序遍历与中序遍历的关联,比如在中序遍历中找到前序遍历的首节点,则整个二叉树可以被分成左右两部分。通过这种规律我们可以递归的划分数组来构建二叉树。
7+
```
8+
```java
9+
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
10+
if (pre == null || in == null || pre.length != in.length)return null;
11+
return run(pre, 0, pre.length - 1, in, 0, in.length - 1);
12+
}
13+
public TreeNode run(int [] pre, int preleft, int preright,int [] in, int inleft, int inright){
14+
if (inleft > inright || preleft > preright)return null;
15+
TreeNode root = new TreeNode(pre[preleft]);
16+
for (int i = inleft; i <= inright; i++){
17+
if (pre[preleft] == in[i]){//找到当前树(子树)的根节点
18+
//递归的求解左右子树
19+
root.left = run(pre, preleft + 1, i - inleft + preleft, in, inleft, i - 1);
20+
root.right = run(pre, i - inleft + preleft + 1, preright, in, i + 1, inright);
21+
break;
22+
}
23+
}
24+
return root;
25+
}
26+
```
27+
## *.树的子结构
28+
```
29+
问题描述:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
30+
```
31+
```
32+
解析:判断A是不是B子结构就需要判断B中是不是有一个子树与A完全相同。策略为递归:判断当前树、判断左子树、判断右子树。
33+
```
34+
```java
35+
public boolean HasSubtree(TreeNode root1,TreeNode root2){
36+
if (root2 == null || root1 == null)return false;
37+
return isSub(root1, root2) || HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
38+
}
39+
public boolean isSub(TreeNode root1, TreeNode root2){
40+
if (root2 == null)return true;
41+
if (root1 == null)return false;
42+
if (root1.val == root2.val){
43+
return isSub(root1.left, root2.left) && isSub(root1.right, root2.right);
44+
}else{
45+
return false;
46+
}
47+
}
48+
```
49+
## *.二叉搜索树的后序序列
50+
```
51+
问题描述:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。
52+
```
53+
```
54+
解析:后序遍历的规律是根节点在最后并能将数组根据大小划分为作为子树。
55+
```
56+
```java
57+
public boolean VerifySquenceOfBST(int [] sequence) {
58+
if (sequence == null || sequence.length == 0)return false;
59+
return run(sequence, 0, sequence.length - 1);
60+
}
61+
public boolean run(int[] arr, int l, int r){
62+
if (r-l<= 0)return true;
63+
int i = l;
64+
boolean flag = true;
65+
while (i < r && arr[i] < arr[r]){
66+
i++;//找到左右子树的划分点
67+
}
68+
flag = flag&&run(arr, l, i-1);//递归左子树
69+
int ll = i;
70+
while (i < r){
71+
if (arr[i] < arr[r])return false;//判断右子树在大小上合不合法
72+
i++;
73+
}
74+
return flag&&run(arr, ll, r-1);//递归右子树
75+
}
76+
```
77+
## *.二叉树路径
78+
```
79+
问题描述:输入一颗二叉树的根节点和一个整数,按字典序打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
80+
```
81+
```
82+
解析:深度遍历的思想,到达该节点判断是否符合要求(值符合+叶节点)。
83+
```
84+
```java
85+
private ArrayList<ArrayList<Integer>>arr = new ArrayList<ArrayList<Integer>>();
86+
private ArrayList<Integer> list = new ArrayList<Integer>();
87+
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
88+
DFS(root, target);
89+
return arr;
90+
}
91+
public void DFS(TreeNode root,int target){
92+
if (root == null)return;
93+
list.add(root.val);
94+
int size = list.size();
95+
if (root.val == target && root.left == null && root.right == null){
96+
arr.add(new ArrayList<Integer>(list));
97+
}
98+
DFS(root.left, target - root.val);
99+
DFS(root.right, target - root.val);
100+
list.remove(list.size() - 1);
101+
}
102+
```
103+
## *.平衡二叉树
104+
```
105+
问题描述:输入一棵二叉树,判断该二叉树是否是平衡二叉树。在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树
106+
```
107+
```
108+
解析:平衡二叉树的关键是左右子树高度差不超过1,函数返回层数来判断高度差。只要有一棵子树不是平衡二叉树整棵树就不是平衡二叉树。
109+
```
110+
```java
111+
public boolean IsBalanced_Solution(TreeNode root) {
112+
boolean[] res = new boolean[1];
113+
res[0] = true;
114+
getHeight(root, 1, res);
115+
return res[0];
116+
}
117+
public int getHeight(TreeNode root, int level, boolean[] res){
118+
if (root == null)return level;
119+
int left = getHeight(root.left, level+1, res);
120+
if (!res[0])return level;
121+
int right = getHeight(root.right, level+1, res);
122+
if (!res[0])return level;
123+
if (Math.abs(left-right) > 1){
124+
res[0] = false;
125+
}
126+
return Math.max(left, right);
127+
}
128+
```
129+
## *.中序遍历的下一个节点
130+
```
131+
问题描述:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
132+
```
133+
```
134+
解析:若是该节点有右子树,则找右子树的最左,若是没有右子树,就向上寻找,直至满足该节点是其父节点的左孩子,返回父节点。
135+
```
136+
```java
137+
public TreeLinkNode GetNext(TreeLinkNode pNode)
138+
{
139+
if (pNode == null)return null;
140+
if (pNode.right != null){
141+
TreeLinkNode tmp = pNode.right;
142+
while(tmp.left != null){
143+
tmp = tmp.left;
144+
}
145+
return tmp;
146+
}
147+
TreeLinkNode parent = pNode.next;
148+
while(parent != null && pNode != parent.left){
149+
pNode = parent;
150+
parent = pNode.next;
151+
}
152+
return parent;
153+
}
154+
```
155+
## *.序列化与反序列化
156+
```
157+
问题描述:请实现两个函数,分别用来序列化和反序列化二叉树
158+
```
159+
```
160+
解析:若是两棵树完全相同,则其序列化相同
161+
```
162+
```java
163+
//先序
164+
public String Serialize(TreeNode head) {
165+
if (head == null) {
166+
return "#!";
167+
}
168+
String res = head.val + "!";
169+
res += Serialize(head.left);
170+
res += Serialize(head.right);
171+
return res;
172+
}
173+
public TreeNode Deserialize(String preStr) {
174+
String[] values = preStr.split("!");
175+
Queue<String> queue = new LinkedList<String>();
176+
for (int i = 0; i != values.length; i++) {
177+
queue.offer(values[i]);
178+
}
179+
return reconPreOrder(queue);
180+
}
181+
public static TreeNode reconPreOrder(Queue<String> queue) {
182+
String value = queue.poll();
183+
if (value.equals("#")) {
184+
return null;
185+
}
186+
TreeNode head = new TreeNode(Integer.valueOf(value));
187+
head.left = reconPreOrder(queue);
188+
head.right = reconPreOrder(queue);
189+
return head;
190+
}
191+
```
192+
193+

动态规划.md

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# 背包问题
2+
```
3+
1.如果是0-1背包,即数组中的元素不可重复使用;
4+
for(int i=1;i<=n;i++){
5+
for(int j=m;j>=a[i];j--){
6+
f[j]=max(f[j], f[j-a[i]]+b[i]);
7+
}
8+
}
9+
2.如果是完全背包,即数组中的元素可重复使用。
10+
for(int i=1;i<=n;i++){
11+
for(int j = a[i];j <= m;j++){
12+
f[j] = max(f[j], f[j-a[i]]+b[i]);
13+
}
14+
}
15+
16+
3.多重背包
17+
```
18+
19+
## 377. 组合总和 Ⅳ
20+
```
21+
问题描述:给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数。
22+
```
23+
```
24+
1.如果是0-1背包,即数组中的元素不可重复使用,nums放在外循环,target在内循环,且内循环倒序;
25+
for num in nums:
26+
for i in range(target, num-1, -1):
27+
28+
2.如果是完全背包,即数组中的元素可重复使用,nums放在外循环,target在内循环。且内循环正序。
29+
for num in nums:
30+
for i in range(num, target+1):
31+
32+
3.如果组合问题需考虑元素之间的顺序,需将target放在外循环,将nums放在内循环。
33+
for i in range(1, target+1):
34+
for num in nums:
35+
36+
```
37+
38+
```java
39+
public int combinationSum4(int[] nums, int target) {
40+
if (nums == null || nums.length < 1) return 0;
41+
int[] dp = new int[target + 1];
42+
dp[0] = 1;
43+
for (int i = 1; i <= target; i++){
44+
for (int num : nums){
45+
if (i >= num){
46+
dp[i] += dp[i - num];
47+
}
48+
}
49+
}
50+
return dp[target];
51+
}
52+
53+
```

0 commit comments

Comments
 (0)