You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
4.8 KiB

2 years ago
package class19;
import java.util.LinkedList;
/*
* 33ABC
* "AAA"AAA
* "BCA"BCA
* cards[]
*
*
* "ABC""CBC""BBC"
* "A""C""B"
* "B""B""B"
* "C""C""C"
*
* cards[]
*
* */
public class Code05_CardsProblem {
public static int ways1(String[] cards) {
LinkedList<String> picks = new LinkedList<>();
return process1(cards, 0, picks);
}
public static int process1(String[] cards, int index, LinkedList<String> picks) {
if (picks.size() == 3) {
return getWays1(picks);
}
if (index == cards.length) {
return 0;
}
int ways = process1(cards, index + 1, picks);
picks.addLast(cards[index]);
ways += process1(cards, index + 1, picks);
picks.pollLast();
return ways;
}
public static int getWays1(LinkedList<String> picks) {
char[] s1 = picks.get(0).toCharArray();
char[] s2 = picks.get(1).toCharArray();
char[] s3 = picks.get(2).toCharArray();
for (int i = 0; i < 3; i++) {
if ((s1[i] != s2[i] && s1[i] != s3[i] && s2[i] != s3[i]) || (s1[i] == s2[i] && s1[i] == s3[i])) {
continue;
}
return 0;
}
return 1;
}
public static int ways2(String[] cards) {
int[] counts = new int[27];
for (String s : cards) {
char[] str = s.toCharArray();
counts[(str[0] - 'A') * 9 + (str[1] - 'A') * 3 + (str[2] - 'A') * 1]++;
}
int ways = 0;
for (int status = 0; status < 27; status++) {
int n = counts[status];
if (n > 2) {
ways += n == 3 ? 1 : (n * (n - 1) * (n - 2) / 6);
}
}
LinkedList<Integer> path = new LinkedList<>();
for (int i = 0; i < 27; i++) {
if (counts[i] != 0) {
path.addLast(i);
ways += process2(counts, i, path);
path.pollLast();
}
}
return ways;
}
// 之前的牌面,拿了一些 ABC BBB ...
// pre = BBB
// ABC ...
// pre = ABC
// ABC BBB CAB
// pre = CAB
// 牌面一定要依次变大,所有形成的有效牌面,把方法数返回
public static int process2(int[] counts, int pre, LinkedList<Integer> path) {
if (path.size() == 3) {
return getWays2(counts, path);
}
int ways = 0;
for (int next = pre + 1; next < 27; next++) {
if (counts[next] != 0) {
path.addLast(next);
ways += process2(counts, next, path);
path.pollLast();
}
}
return ways;
}
public static int getWays2(int[] counts, LinkedList<Integer> path) {
int v1 = path.get(0);
int v2 = path.get(1);
int v3 = path.get(2);
for (int i = 9; i > 0; i /= 3) {
int cur1 = v1 / i;
int cur2 = v2 / i;
int cur3 = v3 / i;
v1 %= i;
v2 %= i;
v3 %= i;
if ((cur1 != cur2 && cur1 != cur3 && cur2 != cur3) || (cur1 == cur2 && cur1 == cur3)) {
continue;
}
return 0;
}
v1 = path.get(0);
v2 = path.get(1);
v3 = path.get(2);
return counts[v1] * counts[v2] * counts[v3];
}
// for test
public static String[] generateCards(int size) {
int n = (int) (Math.random() * size) + 3;
String[] ans = new String[n];
for (int i = 0; i < n; i++) {
char cha0 = (char) ((int) (Math.random() * 3) + 'A');
char cha1 = (char) ((int) (Math.random() * 3) + 'A');
char cha2 = (char) ((int) (Math.random() * 3) + 'A');
ans[i] = String.valueOf(cha0) + String.valueOf(cha1) + String.valueOf(cha2);
}
return ans;
}
// for test
public static void main(String[] args) {
int size = 20;
int testTime = 100000;
System.out.println("test begin");
for (int i = 0; i < testTime; i++) {
String[] arr = generateCards(size);
int ans1 = ways1(arr);
int ans2 = ways2(arr);
if (ans1 != ans2) {
for (String str : arr) {
System.out.println(str);
}
System.out.println(ans1);
System.out.println(ans2);
break;
}
}
System.out.println("test finish");
long start = 0;
long end = 0;
String[] arr = generateCards(10000000);
System.out.println("arr size : " + arr.length + " runtime test begin");
start = System.currentTimeMillis();
ways2(arr);
end = System.currentTimeMillis();
System.out.println("run time : " + (end - start) + " ms");
System.out.println("runtime test end");
}
}