update on 2020-05-16

pull/3/head
algorithmzuo 5 years ago
parent 29042a284a
commit 5817dce9cf

@ -101,6 +101,7 @@ public class Code04_SerializeAndReconstructTree {
if (poslist == null || poslist.size() == 0) { if (poslist == null || poslist.size() == 0) {
return null; return null;
} }
// 左右中 -> stack(中右左)
Stack<String> stack = new Stack<>(); Stack<String> stack = new Stack<>();
while (!poslist.isEmpty()) { while (!poslist.isEmpty()) {
stack.push(poslist.poll()); stack.push(poslist.poll());

@ -14,6 +14,10 @@ public class Code02_PrintAllSubsquences {
return ans; return ans;
} }
// str固定不变
// index此时来到的位置, 要 or 不要
// 如果index来到了str中的终止位置把沿途路径所形成的答案放入ans中
// 之前做出的选择就是path
public static void process1(char[] str, int index, List<String> ans, String path) { public static void process1(char[] str, int index, List<String> ans, String path) {
if (index == str.length) { if (index == str.length) {
ans.add(path); ans.add(path);
@ -37,7 +41,9 @@ public class Code02_PrintAllSubsquences {
return ans; return ans;
} }
public static void process2(char[] str, int index, HashSet<String> set, String path) { // str index set
public static void process2(char[] str, int index,
HashSet<String> set, String path) {
if (index == str.length) { if (index == str.length) {
set.add(path); set.add(path);
return; return;

@ -15,17 +15,22 @@ public class Code03_PrintAllPermutations {
return res; return res;
} }
public static void process(char[] str, int i, ArrayList<String> res) { // str[0..i-1]已经做好决定的
// str[i...]都有机会来到i位置
// i终止位置str当前的样子就是一种结果 -> ans
public static void process(char[] str, int i, ArrayList<String> ans) {
if (i == str.length) { if (i == str.length) {
res.add(String.valueOf(str)); ans.add(String.valueOf(str));
} }
for (int j = i; j < str.length; j++) { // 如果i没有终止i... 都可以来到i位置
for (int j = i; j < str.length; j++) { // j i后面所有的字符都有机会
swap(str, i, j); swap(str, i, j);
process(str, i + 1, res); process(str, i + 1, ans);
swap(str, i, j); swap(str, i, j);
} }
} }
public static ArrayList<String> permutationNoRepeat(String str) { public static ArrayList<String> permutationNoRepeat(String str) {
ArrayList<String> res = new ArrayList<>(); ArrayList<String> res = new ArrayList<>();
if (str == null || str.length() == 0) { if (str == null || str.length() == 0) {
@ -36,17 +41,26 @@ public class Code03_PrintAllPermutations {
return res; return res;
} }
// str[0..i-1]已经做好决定的
// str[i...]都有机会来到i位置
// i终止位置str当前的样子就是一种结果 -> ans
public static void process2(char[] str, int i, ArrayList<String> res) { public static void process2(char[] str, int i, ArrayList<String> res) {
if (i == str.length) { if (i == str.length) {
res.add(String.valueOf(str)); res.add(String.valueOf(str));
return;
} }
boolean[] visit = new boolean[26]; // visit[0 1 .. 25] boolean[] visit = new boolean[26]; // visit[0 1 .. 25]
for (int j = i; j < str.length; j++) { for (int j = i; j < str.length; j++) {
// str[j] = 'a' -> 0 visit[0] -> 'a'
// str[j] = 'z' -> 25 visit[25] -> 'z'
if (!visit[str[j] - 'a']) { if (!visit[str[j] - 'a']) {
visit[str[j] - 'a'] = true; visit[str[j] - 'a'] = true;
swap(str, i, j); swap(str, i, j);
process2(str, i + 1, res); process2(str, i + 1, res);
swap(str, i, j); swap(str, i, j);
} }
} }
} }

@ -9,6 +9,7 @@ public class Code06_ConvertToLetterString {
return process(str.toCharArray(), 0); return process(str.toCharArray(), 0);
} }
// str[0...i-1]已经转化完了,固定了
// i之前的位置如何转化已经做过决定了, 不用再关心 // i之前的位置如何转化已经做过决定了, 不用再关心
// i... 有多少种转化的结果 // i... 有多少种转化的结果
public static int process(char[] str, int i) { public static int process(char[] str, int i) {
@ -19,6 +20,8 @@ public class Code06_ConvertToLetterString {
if (str[i] == '0') { if (str[i] == '0') {
return 0; return 0;
} }
// i没有到终止位置
// str[i]字符不是0 // str[i]字符不是0
if (str[i] == '1') { if (str[i] == '1') {
int res = process(str, i + 1); // i自己作为单独的部分后续有多少种方法 int res = process(str, i + 1); // i自己作为单独的部分后续有多少种方法

@ -6,7 +6,11 @@ public class Code07_Knapsack {
return process(w, v, 0, 0, bag); return process(w, v, 0, 0, bag);
} }
// 不变 w[] v[] bag
// index... 最大价值 // index... 最大价值
// 0..index-1上做了货物的选择使得你已经达到的重量是多少alreadyW
// 如果返回-1认为没有方案
// 如果不返回-1认为返回的值是真实价值
public static int process(int[] w, int[] v, int index, int alreadyW, int bag) { public static int process(int[] w, int[] v, int index, int alreadyW, int bag) {
if (alreadyW > bag) { if (alreadyW > bag) {
return -1; return -1;
@ -30,11 +34,11 @@ public class Code07_Knapsack {
} }
// 只剩下rest的空间了 // 只剩下rest的空间了
// index...货物自由选择,但是不要超过rest的空间 // index...货物自由选择,但是剩余空间不要小于0
// 返回能够获得的最大价值 // 返回 index...货物能够获得的最大价值
public static int process(int[] w, int[] v, int index, int rest) { public static int process(int[] w, int[] v, int index, int rest) {
if (rest <= 0) { // base case 1 if (rest < 0) { // base case 1
return 0; return -1;
} }
// rest >=0 // rest >=0
if (index == w.length) { // base case 2 if (index == w.length) { // base case 2
@ -42,9 +46,10 @@ public class Code07_Knapsack {
} }
// 有货也有空间 // 有货也有空间
int p1 = process(w, v, index + 1, rest); int p1 = process(w, v, index + 1, rest);
int p2 = Integer.MIN_VALUE; int p2 = -1;
if (rest >= w[index]) { int p2Next = process(w, v, index + 1, rest - w[index]);
p2 = v[index] + process(w, v, index + 1, rest - w[index]); if(p2Next!=-1) {
p2 = v[index] + p2Next;
} }
return Math.max(p1, p2); return Math.max(p1, p2);
} }

@ -6,21 +6,32 @@ public class Code08_CardsInLine {
if (arr == null || arr.length == 0) { if (arr == null || arr.length == 0) {
return 0; return 0;
} }
return Math.max(f(arr, 0, arr.length - 1), s(arr, 0, arr.length - 1)); return Math.max(
f(arr, 0, arr.length - 1),
s(arr, 0, arr.length - 1)
);
} }
public static int f(int[] arr, int i, int j) { public static int f(int[] arr, int L, int R) {
if (i == j) { if (L == R) {
return arr[i]; return arr[L];
} }
return Math.max(arr[i] + s(arr, i + 1, j), arr[j] + s(arr, i, j - 1));
return Math.max(
arr[L] + s(arr, L + 1, R),
arr[R] + s(arr, L, R - 1)
);
} }
// i..j
public static int s(int[] arr, int i, int j) { public static int s(int[] arr, int i, int j) {
if (i == j) { if (i == j) {
return 0; return 0;
} }
return Math.min(f(arr, i + 1, j), f(arr, i, j - 1)); return Math.min(
f(arr, i + 1, j), // arr[i]
f(arr, i, j - 1) // arr[j]
);
} }
public static int win2(int[] arr) { public static int win2(int[] arr) {
@ -40,9 +51,11 @@ public class Code08_CardsInLine {
} }
public static void main(String[] args) { public static void main(String[] args) {
int[] arr = { 1, 9, 1 }; int[] arr = { 4,7,9,5 };
System.out.println(win1(arr)); // A 4 9
System.out.println(win2(arr)); // B 7 5
System.out.println(f(arr,0,3));
System.out.println(s(arr,0,3));
} }

@ -14,12 +14,13 @@ public class Code09_NQueens {
// 潜台词record[0..i-1]的皇后,任何两个皇后一定都不共行、不共列,不共斜线 // 潜台词record[0..i-1]的皇后,任何两个皇后一定都不共行、不共列,不共斜线
// 目前来到了第i行 // 目前来到了第i行
// record[0..i-1]表示之前的行,放了的皇后位置 // record[0..i-1]表示之前的行,放了的皇后位置
// n代表整体一共有多少行 // n代表整体一共有多少行 0~n-1行
// 返回值是,摆完所有的皇后,合理的摆法有多少种 // 返回值是,摆完所有的皇后,合理的摆法有多少种
public static int process1(int i, int[] record, int n) { public static int process1(int i, int[] record, int n) {
if (i == n) { // 终止行 if (i == n) { // 终止行
return 1; return 1;
} }
// 没有到终止位置,还有皇后要摆
int res = 0; int res = 0;
for (int j = 0; j < n; j++) { // 当前行在i行尝试i行所有的列 -> j for (int j = 0; j < n; j++) { // 当前行在i行尝试i行所有的列 -> j
// 当前i行的皇后放在j列会不会和之前(0..i-1)的皇后,不共行共列或者共斜线, // 当前i行的皇后放在j列会不会和之前(0..i-1)的皇后,不共行共列或者共斜线,
@ -37,6 +38,7 @@ public class Code09_NQueens {
// 返回i行皇后放在了j列是否有效 // 返回i行皇后放在了j列是否有效
public static boolean isValid(int[] record, int i, int j) { public static boolean isValid(int[] record, int i, int j) {
for (int k = 0; k < i; k++) { // 之前的某个k行的皇后 for (int k = 0; k < i; k++) { // 之前的某个k行的皇后
// k, record[k] i, j
if (j == record[k] || Math.abs(record[k] - j) == Math.abs(i - k)) { if (j == record[k] || Math.abs(record[k] - j) == Math.abs(i - k)) {
return false; return false;
} }
@ -49,25 +51,32 @@ public class Code09_NQueens {
if (n < 1 || n > 32) { if (n < 1 || n > 32) {
return 0; return 0;
} }
// 如果你是13皇后问题limit 最右13个1其他都是0
int limit = n == 32 ? -1 : (1 << n) - 1; int limit = n == 32 ? -1 : (1 << n) - 1;
return process2(limit, 0, 0, 0); return process2(limit, 0, 0, 0);
} }
// limit 划定了问题的规模 -> 固定
// colLim 列的限制1的位置不能放皇后0的位置可以 // colLim 列的限制1的位置不能放皇后0的位置可以
// leftDiaLim 左斜线的限制1的位置不能放皇后0的位置可以 // leftDiaLim 左斜线的限制1的位置不能放皇后0的位置可以
// rightDiaLim 右斜线的限制1的位置不能放皇后0的位置可以 // rightDiaLim 右斜线的限制1的位置不能放皇后0的位置可以
public static int process2(int limit, public static int process2(
int limit,
int colLim, int colLim,
int leftDiaLim, int leftDiaLim,
int rightDiaLim) { int rightDiaLim) {
if (colLim == limit) { // base case if (colLim == limit) { // base case
return 1; return 1;
} }
// 所有候选皇后的位置都在pos上 // 所有可以放皇后的位置都在pos上
// colLim | leftDiaLim | rightDiaLim -> 总限制
// ~ (colLim | leftDiaLim | rightDiaLim) -> 左侧的一坨0干扰右侧每个1可尝试
int pos = limit & ( ~(colLim | leftDiaLim | rightDiaLim) ); int pos = limit & ( ~(colLim | leftDiaLim | rightDiaLim) );
int mostRightOne = 0; int mostRightOne = 0;
int res = 0; int res = 0;
while (pos != 0) { while (pos != 0) {
// 其取出pos中最右侧的1来剩下位置都是0
mostRightOne = pos & (~pos + 1); mostRightOne = pos & (~pos + 1);
pos = pos - mostRightOne; pos = pos - mostRightOne;
res += process2(limit, res += process2(limit,
@ -79,7 +88,7 @@ public class Code09_NQueens {
} }
public static void main(String[] args) { public static void main(String[] args) {
int n = 14; int n = 15;
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
System.out.println(num2(n)); System.out.println(num2(n));

@ -40,6 +40,58 @@ public class Code01_RobotWalk {
return walk(N, cur + 1, rest - 1, P) + walk(N, cur - 1, rest - 1, P); return walk(N, cur + 1, rest - 1, P) + walk(N, cur - 1, rest - 1, P);
} }
public static int waysCache(int N, int M, int K, int P) {
// 参数无效直接返回0
if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) {
return 0;
}
int[][] dp = new int[N+1][K+1];
for(int row = 0; row <= N; row++) {
for(int col = 0; col <= K; col++) {
dp[row][col] = -1;
}
}
return walkCache(N, M, K, P,dp);
}
// HashMap<String, Integer> (19,100) "19_100"
// 我想把所有cur和rest的组合返回的结果加入到缓存里
public static int walkCache(int N, int cur, int rest, int P, int[][] dp) {
if(dp[cur][rest] != -1) {
return dp[cur][rest];
}
if (rest == 0) {
dp[cur][rest] = cur == P ? 1 : 0;
return dp[cur][rest];
}
if (cur == 1) {
dp[cur][rest] = walkCache(N, 2, rest - 1, P, dp);
return dp[cur][rest];
}
if (cur == N) {
dp[cur][rest] =walkCache(N, N - 1, rest - 1, P,dp);
return dp[cur][rest];
}
dp[cur][rest] = walkCache(N, cur + 1, rest - 1, P,dp)
+ walkCache(N, cur - 1, rest - 1, P, dp);
return dp[cur][rest];
}
public static int ways2(int N, int M, int K, int P) { public static int ways2(int N, int M, int K, int P) {
// 参数无效直接返回0 // 参数无效直接返回0
if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) { if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) {

@ -33,8 +33,8 @@ public class Code03_Knapsack {
// index...货物自由选择但是不要超过rest的空间 // index...货物自由选择但是不要超过rest的空间
// 返回能够获得的最大价值 // 返回能够获得的最大价值
public static int process(int[] w, int[] v, int index, int rest) { public static int process(int[] w, int[] v, int index, int rest) {
if (rest <= 0) { // base case 1 if (rest < 0) { // base case 1
return 0; return -1;
} }
// rest >=0 // rest >=0
if (index == w.length) { // base case 2 if (index == w.length) { // base case 2
@ -42,9 +42,10 @@ public class Code03_Knapsack {
} }
// 有货也有空间 // 有货也有空间
int p1 = process(w, v, index + 1, rest); int p1 = process(w, v, index + 1, rest);
int p2 = Integer.MIN_VALUE; int p2 = -1;
if (rest >= w[index]) { int p2Next = process(w, v, index + 1, rest - w[index]);
p2 = v[index] + process(w, v, index + 1, rest - w[index]); if(p2Next!=-1) {
p2 = v[index] + p2Next;
} }
return Math.max(p1, p2); return Math.max(p1, p2);
} }

Loading…
Cancel
Save