1.全排列
有重复元素的全排列
- 需要对元素进行排序
然后再 全排列的时候加入
//重复元素 去重*************************
if(i>0&&a[i]==a[i-1]&&book[i-1]==0) continue;
例子: 对 一个数组{1,0,1,1} 进行全排列
import java.util.Arrays;
/**
*
* @author sjf666
*
* 2020年4月3日下午9:40:17
*/
public class Demo05_重复元素全排列 {
static int [] a= {1,0,1,1};
static int []ans = new int [a.length];
static int [] book = new int[a.length];
public static void main(String[] args) {
Arrays.sort(a);
dfs(0);
}
public static void dfs(int step){
if(step == ans.length)
System.out.println(Arrays.toString(ans));
for (int i = 0; i < a.length ; i++) {
if(i>0&&a[i]==a[i-1]&&book[i-1]==0) continue;
if(book[i] == 0){
book[i] = 1;
ans[step] = a[i];
dfs(step+1);
book[i] = 0;
}
}
}
}
好处: 此行if(i>0&&a[i]==a[i-1]&&book[i-1]==0) continue;
还可以筛掉很多次递归,可以优化程序, 在解决多个重复元素的全排列有很大的作用。
- 利用 HashSet集合去重(不考虑性能 可以使用 挺简单)
此方法只能对结果产生影响 ,不会对程序性能进行优化
例子:
组素数
素数就是不能再进行等分的数。比如:2 3 5 7 11 等。
9 = 3 * 3 说明它可以3等分,因而不是素数。
我们国家在1949年建国。如果只给你 1 9 4 9 这4个数字卡片,
可以随意摆放它们的先后顺序(但卡片不能倒着摆放啊,我们不是在脑筋急转弯!),那么,你能组成多少个4位的素数呢?
比如:1949,4919 都符合要求。
请你提交:能组成的4位素数的个数,不要罗列这些素数!!
import java.util.Arrays;
import java.util.HashSet;
import java.util.Scanner;
/**
*
* @author sjf666
*
* 2020年4月2日下午10:18:33
*/
// 全排列(有重复元素的) 检查素数
//重复元素 去重*************************
//if(i>0&&a[i]==a[i-1]&&book[i-1]==0) continue;
public class Demo04_组素数 {
static int[] ans = new int [4];
static int[] ku = new int [4];
static int[] book = new int [4];
static int count ;
private static HashSet<String> set;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
set = new HashSet<String>(); //初始化集合
for(int i = 0 ; i < 4 ; i++) {
ku[i] =sc.nextInt();
}
//Arrays.sort(ku);
dfs(0);
System.out.println(count);
System.out.println(set.size());
// for (Iterator iterator = set.iterator(); iterator.hasNext();) {
// String string = (String) iterator.next();
// System.out.println(string);
// }
}
public static void dfs(int step) {
if(step == 4) {
if(check()) {
set.add(Arrays.toString(ans));
count++;
}
return;
}
for (int i = 0; i < 4; i++) {
//if(i>0&&ku[i]==ku[i-1]&&book[i-1]==0) continue;
if(book[i] == 0) {
ans[step] = ku[i];
book[i] = 1;
dfs(step+1);
book[i] = 0;
}
}
}
public static boolean check() {
int num = ans[0]*1000+ans[1]*100+ans[2]*10+ans[3];
for(int i = 2 ; i <= Math.sqrt(num);i++) {
if(num % i ==0)
return false;
}
return true;
}
}
2.组合问题
组合问题
是对每种元素的个数进行全部列举 只看元素在组合中所占的个数,不看顺序
以下代码是一个经典组合问题的求解
参数 step :指向每种元素 也可以看成盒子 只不过盒子中固定放的是一种元素 只是个数不一样
参数 goal :距离目标组合还有多少个元素可以添加
/**
*
* @param step 当前的位置 相当于在 data数组的下标 每个元素的指向
* @param goal 距离目标的剩余个数
*
*/
public static void f(int step ,int goal) {
if(step == ans.length ) {
if(goal == 0)
print();
return;
}
//这里 i 的范围 应该是在 某种元素提供的个数 和 目标组合所需的个数中 去较小的那个
for(int i = 0 ; i <= Math.min(data[step], goal); i++) {
ans[step] = i;
f(step+1, goal-i);
}
}
-
X星球要派出一个5人组成的观察团前往W星。
其中:
A国最多可以派出4人。
B国最多可以派出2人。
C国最多可以派出2人。
D国最多可以派出1人。
E国最多可以派出1人。
F国最多可以派出3人。
那么最终派往W星的观察团会有多少种国别的不同组合呢?请输出所有不同的组合。
/**
*
* @author sjf666
*
* 2020年4月3日下午1:50:23
*/
public class Demo03_代表团出访 {
static int[] data = {4,2,2,1,1,3}; //元素个数
static int[] ans = new int[data.length];
public static void main(String[] args) {
f(0, 5);
}
/**
*
* @param step 当前的位置 相当于在 data数组的下标 每个元素的指向
* @param goal 距离目标的剩余个数
*
*/
public static void f(int step ,int goal) {
if(step == ans.length ) {
if(goal == 0)
print();
return;
}
for(int i = 0 ; i <= Math.min(data[step], goal); i++) {
ans[step] = i;
f(step+1, goal-i);
}
}
public static void print() {
for(int i = 0; i < ans.length; i++)
for(int j = 0; j<ans[i]; j++)
System.out.print((char)('A'+i));
System.out.println();
}
}
- 扑克序列
小明被劫持到X赌城,被迫与其他3人玩牌。
一副扑克牌(去掉大小王牌,共52张),均匀发给4个人,每个人13张。
这时,小明脑子里突然冒出一个问题:
如果不考虑花色,只考虑点数,也不考虑自己得到的牌的先后顺序,自己手里能拿到的初始牌型组合一共有多少种呢?
/**
*
* @author sjf666
*
* 2020年4月3日下午2:12:51
*/
public class Demo04_组合_扑克序列 {
static int[] data = {4,4,4,4,4,4,4,4,4,4,4,4,4};
static int count ;
static int[] ans = new int [data.length];
public static void main(String[] args) {
f(0, 13);
System.out.println(count);
}
/**
*
* @param step
* @param goal
*/
public static void f(int step ,int goal) {
if(step == ans.length) {
if(goal == 0)
count++;
return;
}
for(int i = 0; i <= Math.min(data[step], goal); i++ ) {
ans[step] = i;
f(step + 1 , goal - i);
}
}
}