package month7.dp;
import java.util.Arrays;
public class 全排列 {
public static void main(String[] args) {
全排列 a = new 全排列();
int[] arr = { 1, 2, 2 };
a.perm(arr, 0, arr.length - 1);
System.out.println("==============");
a.perm_removeSame(arr, 0, arr.length-1);
}
/**
* 将数组中的元素,从下标 start 到 end 做全排列(未考虑重复的元素)
* @param arr 要排列的数组
* @param start 起始的位置
* @param end 终止的位置
*/
public void perm(int[] arr, int start, int end) {
if (start == end) {
System.out.println(Arrays.toString(arr));
}
for (int i = start; i <= end; i++) {
swap(arr, start, i); // 第一个数,从0开始,依次与后面的数相交换
perm(arr, start + 1, end);
swap(arr, i, start);
}
}
private void swap(int[] arr, int start, int i) {
int tmp = arr[start];
arr[start] = arr[i];
arr[i] = tmp;
}
// 那当字符串中出现重复的字符时,如何生成不重复的排列?
// ---去重的全排列就是从第一个数字起每个数分别与它后面非重复出现的数字交换
public void perm_removeSame(int[] arr, int start, int end) {
if (start == end) {
System.out.println(Arrays.toString(arr));
}
for (int i = start; i <= end; i++) {
// 只有当没有重叠的字符 才交换
if(!isSwap(arr, start, i)) {
swap(arr, start, i);
perm_removeSame(arr, start+1, end);
swap(arr, i, start);
}
}
}
//[start,end) 中是否有与 arr[end] 相同的字符
private boolean isSwap(int[] arr, int start, int end) {
for(int i=start;i<end;i++){
if(arr[i] == arr[end]){
return true;
}
}
return false;
}
}