输入只有一行,是一个由不同的小写字母组成的字符串,已知字符串的长度在1到6之间。
输出这个字符串的所有排列方式,每行一个排列。要求字母序比较小的排列在前面。字母序如下定义: 已知S = s1s2...sk , T = t1t2...tk,则S < T 等价于,存在p (1 <= p <= k),使得 s1 = t1, s2 = t2, ..., sp - 1 = tp - 1, sp < tp成立。 每组样例输出结束后要再输出一个回车。
abc
abc acb bac bca cab cba
// 可以将其想像成竖着排列的组 // 例如 // a a a // b b b // c c c // 第一组先取 a,标记数组标记为 true,代表已访问过 // 然后递归调用 // 第二组由于 a 标记为 true 跳过 取 b // 以此类推 // 第三组结束后输出 // 此时再依次将每一组用过的还原为 true // 访问到第几组由调用栈决定,每一组访问到第几个由 for 循环 i 决定,一次排列中是否访问过由 tag 数组决定 private static void get(char[] s, int index, boolean[] tag, char[] out) { // 访问结束 if (index == s.length) { System.out.println(out); return; } for (int i = 0; i < s.length; i++) { // 没有访问过 if (!tag[i]) { out[index] = s[i]; // 第一组内已访问过 tag[i] = true; get(s, index + 1, tag, out); // 将访问过的还原 tag[i] = false; } } }
import java.util.ArrayList; import java.util.Collections; import java.util.Scanner; public class Main { static boolean[] visited; static char[] array; static ArrayList<String> list = new ArrayList<>(); public static void main(String[] args) { Scanner scanner = new Scanner(System.in); array = scanner.next().toCharArray(); visited = new boolean[array.length]; gen(0,""); Collections.sort(list); for (String s1 : list) System.out.println(s1); //注意题目要求:每组样例输出结束后要再输出一个回车。 System.out.println(); } static void gen(int step,String cur){ // 递归终止 if (step==array.length){ list.add(cur); return; } for (int i = 0; i <array.length ; i++) { if (!visited[i]){ visited[i]=true; gen(step+1,cur+array[i]); // 回溯,清除现场 visited[i]=false; } } } }
import java.util.*; public class Main { public static void main(String[] args) { Scanner reader = new Scanner(System.in); char[] input = reader.next().toCharArray(); Arrays.sort(input); ArrayList<Character> path = new ArrayList<>(); boolean[] visited = new boolean[input.length]; helper(input, path, visited); System.out.println(); } public static void helper(char[] str, ArrayList<Character> path, boolean[] visited) { if (path.size() == str.length) { for (char c: path) { System.out.print(c); } System.out.println(); return; } for (int i = 0; i < str.length; ++i) { if (visited[i]) continue; path.add(str[i]); visited[i] = true; helper(str, path, visited); path.remove(path.size()-1); visited[i] = false; } } }
//用dfs写的,主要是排序和去重吧 import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Scanner; public class Main{ public static void main(String[] args){ testFullArrMent(); } static boolean[] flag; static List<String> list = new ArrayList<String>(); public static void testFullArrMent(){ Scanner sc = new Scanner(System.in); String s = sc.nextLine(); char[] ch = s.toCharArray(); char[] c = new char[ch.length]; flag = new boolean[ch.length]; dfs(ch,c,0); Collections.sort(list); for(String str:list){ System.out.println(str); } System.out.println(); } private static void dfs(char[] ch, char[] c, int k) { // TODO Auto-generated method stub if(k==ch.length){ String s = String.valueOf(c); if(!list.contains(s)){ list.add(s); } } for(int i=0;i<ch.length;i++){ if(!flag[i]){ flag[i]=true; c[k]=ch[i]; dfs(ch,c,k+1); flag[i]=false; } } } }
import java.util.Arrays; import java.util.Scanner; /* * 思路: * 当我试着分解问题时,发现,n个数(a1,...,an)的全排列可以分解为a1拼接(n-1)个数全排列.直到1个数的全排列.此时能够确定某一个排列. * 自然会去尝试一下递归处理 * # 那么思考递归变量是哪些呢? * 1. 参与全排列的元素在变,用char[]数组变量表示 * 2. 因为要打印完整的全排列,每次父问题分为前后两半之后,前半边字符串需要传递进来和后半边字符串进行拼接,然后打印. * * # 递归的边界条件是什么呢? * 1. 我们能直观感受到只有一个数时,问题不能再分解,并且可以拼接,打印字符串了. * 2. 但是,我们可能要用递归变量来具体化边界情况. recursive(前半边字符串=不怎么好描述...,char[] = 1个元素(这个1很好确定),); * * # 打印的顺序满足字典序吗? * 卧槽,是满足的. */ public class Main_Sure { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); while (scanner.hasNextLine()) { char[] input = scanner.nextLine().toCharArray(); Arrays.sort(input);//有坑,存在"dbc"这种顺序打乱的test case,所以排个序. fullPermutation("", input); System.out.println(); } } public static void fullPermutation(String pre, char[] inputs) { if (inputs.length == 1) { System.out.println(pre.toString() + inputs[0]); return; } //分类计数原理计算全排列的排列个数: 每个字符都要做一次开头. 这样分类完备,无重复. //inputs[i]:某全排列开头的字符. for (int i = 0; i < inputs.length; i++) { char[] rest = new char[inputs.length - 1]; int index = 0; for (int j = 0; j < inputs.length; j++) { if (i != j) { rest[index++] = inputs[j]; } } fullPermutation(pre +""+inputs[i], rest); } } }