Skip to content

Commit e204c3f

Browse files
committed
modify code
1 parent 1cd505f commit e204c3f

File tree

4 files changed

+277
-0
lines changed

4 files changed

+277
-0
lines changed

src/class46/Code01_BurstBalloons.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,43 @@
33
// 本题测试链接 : https://leetcode.com/problems/burst-balloons/
44
public class Code01_BurstBalloons {
55

6+
public static int maxCoins0(int[] arr) {
7+
// [3,2,1,3]
8+
// [1,3,2,1,3,1]
9+
int N = arr.length;
10+
int[] help = new int[N + 2];
11+
for (int i = 0; i < N; i++) {
12+
help[i + 1] = arr[i];
13+
}
14+
help[0] = 1;
15+
help[N + 1] = 1;
16+
return func(help, 1, N);
17+
}
18+
19+
// L-1位置,和R+1位置,永远不越界,并且,[L-1] 和 [R+1] 一定没爆呢!
20+
// 返回,arr[L...R]打爆所有气球,最大得分是什么
21+
public static int func(int[] arr, int L, int R) {
22+
if (L == R) {
23+
return arr[L - 1] * arr[L] * arr[R + 1];
24+
}
25+
// 尝试每一种情况,最后打爆的气球,是什么位置
26+
// L...R
27+
// L位置的气球,最后打爆
28+
int max = func(arr, L + 1, R) + arr[L - 1] * arr[L] * arr[R + 1];
29+
// R位置的气球,最后打爆
30+
max = Math.max(max, func(arr, L, R - 1) + arr[L - 1] * arr[R] * arr[R + 1]);
31+
// 尝试所有L...R,中间的位置,(L,R)
32+
for (int i = L + 1; i < R; i++) {
33+
// i位置的气球,最后打爆
34+
int left = func(arr, L, i - 1);
35+
int right = func(arr, i + 1, R);
36+
int last = arr[L - 1] * arr[i] * arr[R + 1];
37+
int cur = left + right + last;
38+
max = Math.max(max, cur);
39+
}
40+
return max;
41+
}
42+
643
public static int maxCoins1(int[] arr) {
744
if (arr == null || arr.length == 0) {
845
return 0;

src/class46/Code02_RemoveBoxes.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,23 @@
33
// 本题测试链接 : https://leetcode.com/problems/remove-boxes/
44
public class Code02_RemoveBoxes {
55

6+
// arr[L...R]消除,而且前面跟着K个arr[L]这个数
7+
// 返回:所有东西都消掉,最大得分
8+
public static int func1(int[] arr, int L, int R, int K) {
9+
if (L > R) {
10+
return 0;
11+
}
12+
int ans = func1(arr, L + 1, R, 0) + (K + 1) * (K + 1);
13+
14+
// 前面的K个X,和arr[L]数,合在一起了,现在有K+1个arr[L]位置的数
15+
for (int i = L + 1; i <= R; i++) {
16+
if (arr[i] == arr[L]) {
17+
ans = Math.max(ans, func1(arr, L + 1, i - 1, 0) + func1(arr, i, R, K + 1));
18+
}
19+
}
20+
return ans;
21+
}
22+
623
public static int removeBoxes1(int[] boxes) {
724
int N = boxes.length;
825
int[][][] dp = new int[N][N][N];
@@ -41,10 +58,15 @@ public static int process2(int[] boxes, int L, int R, int K, int[][][] dp) {
4158
if (dp[L][R][K] > 0) {
4259
return dp[L][R][K];
4360
}
61+
// 找到开头,
62+
// 1,1,1,1,1,5
63+
// 3 4 5 6 7 8
64+
// !
4465
int last = L;
4566
while (last + 1 <= R && boxes[last + 1] == boxes[L]) {
4667
last++;
4768
}
69+
// K个1 (K + last - L) last
4870
int pre = K + last - L;
4971
int ans = (pre + 1) * (pre + 1) + process2(boxes, last + 1, R, 0, dp);
5072
for (int i = last + 2; i <= R; i++) {

src/class46/Code03_DeleteAdjacentSameCharacter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ public static int restMin2(String s) {
5959
return process(str, 0, str.length - 1, false);
6060
}
6161

62+
// str[L...R] 前面有没有跟着[L]字符,has T 有 F 无
63+
// L,R,has
64+
// 最少能剩多少字符,消不了
6265
public static int process(char[] str, int L, int R, boolean has) {
6366
if (L > R) {
6467
return 0;
@@ -72,6 +75,7 @@ public static int process(char[] str, int L, int R, boolean has) {
7275
K++;
7376
index++;
7477
}
78+
// index表示,第一个不是[L]字符的位置
7579
int way1 = (K > 1 ? 0 : 1) + process(str, index, R, false);
7680
int way2 = Integer.MAX_VALUE;
7781
for (int split = index; split <= R; split++) {

src/class46/HuffmanTree.java

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
package class46;
2+
3+
import java.util.Comparator;
4+
import java.util.HashMap;
5+
import java.util.Map.Entry;
6+
import java.util.PriorityQueue;
7+
8+
// 本文件不牵扯任何byte类型的转化
9+
// 怎么转byte自己来,我只负责huffman算法本身的正确实现
10+
// 字符串为空的时候,自己处理边界吧
11+
// 实现的代码通过了大样本随机测试的对数器
12+
// 可以从main函数的内容开始看起
13+
public class HuffmanTree {
14+
15+
// 根据文章str, 生成词频统计表
16+
public static HashMap<Character, Integer> countMap(String str) {
17+
HashMap<Character, Integer> ans = new HashMap<>();
18+
char[] s = str.toCharArray();
19+
for (char cha : s) {
20+
if (!ans.containsKey(cha)) {
21+
ans.put(cha, 1);
22+
} else {
23+
ans.put(cha, ans.get(cha) + 1);
24+
}
25+
}
26+
return ans;
27+
}
28+
29+
public static class Node {
30+
public int count;
31+
public Node left;
32+
public Node right;
33+
34+
public Node(int c) {
35+
count = c;
36+
}
37+
}
38+
39+
public static class NodeComp implements Comparator<Node> {
40+
41+
@Override
42+
public int compare(Node o1, Node o2) {
43+
return o1.count - o2.count;
44+
}
45+
46+
}
47+
48+
// 根据由文章生成词频表countMap,生成哈夫曼编码表
49+
// key : 字符
50+
// value: 该字符编码后的二进制形式
51+
// 比如,频率表 A:60, B:45, C:13 D:69 E:14 F:5 G:3
52+
// A 10
53+
// B 01
54+
// C 0011
55+
// D 11
56+
// E 000
57+
// F 00101
58+
// G 00100
59+
public static HashMap<Character, String> huffmanForm(HashMap<Character, Integer> countMap) {
60+
HashMap<Character, String> ans = new HashMap<>();
61+
if (countMap.size() == 1) {
62+
for (char key : countMap.keySet()) {
63+
ans.put(key, "0");
64+
}
65+
return ans;
66+
}
67+
HashMap<Node, Character> nodes = new HashMap<>();
68+
PriorityQueue<Node> heap = new PriorityQueue<>(new NodeComp());
69+
for (Entry<Character, Integer> entry : countMap.entrySet()) {
70+
Node cur = new Node(entry.getValue());
71+
char cha = entry.getKey();
72+
nodes.put(cur, cha);
73+
heap.add(cur);
74+
}
75+
while (heap.size() != 1) {
76+
Node a = heap.poll();
77+
Node b = heap.poll();
78+
Node h = new Node(a.count + b.count);
79+
h.left = a;
80+
h.right = b;
81+
heap.add(h);
82+
}
83+
Node head = heap.poll();
84+
fillForm(head, "", nodes, ans);
85+
return ans;
86+
}
87+
88+
public static void fillForm(Node head, String pre, HashMap<Node, Character> nodes, HashMap<Character, String> ans) {
89+
if (nodes.containsKey(head)) {
90+
ans.put(nodes.get(head), pre);
91+
} else {
92+
fillForm(head.left, pre + "0", nodes, ans);
93+
fillForm(head.right, pre + "1", nodes, ans);
94+
}
95+
}
96+
97+
// 原始字符串str,根据哈夫曼编码表,转译成哈夫曼编码返回
98+
public static String huffmanEncode(String str, HashMap<Character, String> huffmanForm) {
99+
char[] s = str.toCharArray();
100+
StringBuilder builder = new StringBuilder();
101+
for (char cha : s) {
102+
builder.append(huffmanForm.get(cha));
103+
}
104+
return builder.toString();
105+
}
106+
107+
// 原始字符串的哈夫曼编码huffmanEncode,根据哈夫曼编码表,还原成原始字符串
108+
public static String huffmanDecode(String huffmanEncode, HashMap<Character, String> huffmanForm) {
109+
TrieNode root = createTrie(huffmanForm);
110+
TrieNode cur = root;
111+
char[] encode = huffmanEncode.toCharArray();
112+
StringBuilder builder = new StringBuilder();
113+
for (int i = 0; i < encode.length; i++) {
114+
int index = encode[i] == '0' ? 0 : 1;
115+
cur = cur.nexts[index];
116+
if (cur.nexts[0] == null && cur.nexts[1] == null) {
117+
builder.append(cur.value);
118+
cur = root;
119+
}
120+
}
121+
return builder.toString();
122+
}
123+
124+
public static TrieNode createTrie(HashMap<Character, String> huffmanForm) {
125+
TrieNode root = new TrieNode();
126+
for (char key : huffmanForm.keySet()) {
127+
char[] path = huffmanForm.get(key).toCharArray();
128+
TrieNode cur = root;
129+
for (int i = 0; i < path.length; i++) {
130+
int index = path[i] == '0' ? 0 : 1;
131+
if (cur.nexts[index] == null) {
132+
cur.nexts[index] = new TrieNode();
133+
}
134+
cur = cur.nexts[index];
135+
}
136+
cur.value = key;
137+
}
138+
return root;
139+
}
140+
141+
public static class TrieNode {
142+
public char value;
143+
public TrieNode[] nexts;
144+
145+
public TrieNode() {
146+
value = 0;
147+
nexts = new TrieNode[2];
148+
}
149+
}
150+
151+
// 为了测试
152+
public static String randomNumberString(int len, int range) {
153+
char[] str = new char[len];
154+
for (int i = 0; i < len; i++) {
155+
str[i] = (char) ((int) (Math.random() * range) + 'a');
156+
}
157+
return String.valueOf(str);
158+
}
159+
160+
// 为了测试
161+
public static void main(String[] args) {
162+
// 根据词频表生成哈夫曼编码表
163+
HashMap<Character, Integer> map = new HashMap<>();
164+
map.put('A', 60);
165+
map.put('B', 45);
166+
map.put('C', 13);
167+
map.put('D', 69);
168+
map.put('E', 14);
169+
map.put('F', 5);
170+
map.put('G', 3);
171+
HashMap<Character, String> huffmanForm = huffmanForm(map);
172+
for (Entry<Character, String> entry : huffmanForm.entrySet()) {
173+
System.out.println(entry.getKey() + " : " + entry.getValue());
174+
}
175+
System.out.println("====================");
176+
// str是原始字符串
177+
String str = "CBBBAABBACAABDDEFBA";
178+
System.out.println(str);
179+
// countMap是根据str建立的词频表
180+
HashMap<Character, Integer> countMap = countMap(str);
181+
// hf是根据countMap生成的哈夫曼编码表
182+
HashMap<Character, String> hf = huffmanForm(countMap);
183+
// huffmanEncode是原始字符串转译后的哈夫曼编码
184+
String huffmanEncode = huffmanEncode(str, hf);
185+
System.out.println(huffmanEncode);
186+
// huffmanDecode是哈夫曼编码还原成的原始字符串
187+
String huffmanDecode = huffmanDecode(huffmanEncode, hf);
188+
System.out.println(huffmanDecode);
189+
System.out.println("====================");
190+
System.out.println("大样本随机测试开始");
191+
// 字符串最大长度
192+
int len = 500;
193+
// 所含字符种类
194+
int range = 26;
195+
// 随机测试进行的次数
196+
int testTime = 100000;
197+
for (int i = 0; i < testTime; i++) {
198+
int N = (int) (Math.random() * len) + 1;
199+
String test = randomNumberString(N, range);
200+
HashMap<Character, Integer> counts = countMap(test);
201+
HashMap<Character, String> form = huffmanForm(counts);
202+
String encode = huffmanEncode(test, form);
203+
String decode = huffmanDecode(encode, form);
204+
if (!test.equals(decode)) {
205+
System.out.println(test);
206+
System.out.println(encode);
207+
System.out.println(decode);
208+
System.out.println("出错了!");
209+
}
210+
}
211+
System.out.println("大样本随机测试结束");
212+
}
213+
214+
}

0 commit comments

Comments
 (0)