给定一个正整数N代表火车数量,0<N<10,接下来输入火车入站的序列,一共N辆火车,每辆火车以数字1-9编号。要求以字典序排序输出火车出站的序列号。
输入描述:
有多组测试用例,每一组第一行输入一个正整数N(0<N<10),第二行包括N个正整数,范围为1到9。
输出描述:
输出以字典序从小到大排序的火车出站序列号,每个编号以空格隔开,每个输出序列换行,具体见sample。
输入例子:
3
1 2 3
输出例子:
1 2 3
1 3 2
2 1 3
2 3 1
3 2 1
解题
1.求出所有排列
2.判断合法出入栈
如何求排列
把一个字符串看成两部分组成:第一部分为它的第一个字符,第二部分是后面的所有字符。求整个字符串的排列,分为两步:
第一步:求所有可能出现在第一个位置的字符,即把第一个字符和后面的所有字符交换
第二步:固定第一个字符,求后面所有字符的排列,这个时候把后面的所有字符看成两个部分:后面字符的第一个字符,以及这个字符之后的所有字符,这是一个递归的过程。
代码如下
/** * 求出所有排列 * @param A * @param start * @param n * @param result */ private static void Permutation(int[] A,int start,int n,ArrayList<int[]> result){ if(start == n){ return; } if(start == n-1){ int[] B = A.clone(); result.add(B); return; } for(int i=start;i<n;i++){ swap(A,start,i); Permutation(A,start+1,n,result);// 后一个位置开始,进行递归 swap(A,start,i); } } private static void swap(int[] A,int i,int j){ int t = A[i]; A[i] = A[j]; A[j] = t; }
如何判断是合法出栈队列?
本质就是模拟可能出栈序列
private static boolean isLegal(int[] in,int[] out,int n){ LinkedList<Integer> stack = new LinkedList<Integer>(); int i=0; int j=0; while(i<n){ // in 还有元素的时候都需要判断 if(in[i] == out[j]){ // 相等时候就不用入栈,直接后移 i++; j++; }else{ if(stack.isEmpty()){ //空stack 就只有入栈了 stack.push(in[i]); i++; }else{ int top = stack.peek(); // 栈顶元素相等,进行出栈 if(top ==out[j]){ j++; stack.pop(); }else if(i<n){ // 不等时候入栈 stack.push(in[i]); i++; } } } } while(!stack.isEmpty() && j<n){ // in 的结束后,栈中元素进程出栈序列应该和out剩余的元素 相同 int top = stack.pop(); if(top == out[j]){ j++; }else{ return false; } } return true; }
这样就OK了
注意最后还有一个排序的过程
但是如果在华为OJ上做,就一个测试样例,不排序也可以,在牛客上就需要排序了
import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.Scanner; import java.util.Set; import java.util.TreeSet; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); while(in.hasNext()){ int n = in.nextInt(); int[] A = new int[n]; for(int i=0;i<n;i++){ A[i] = in.nextInt(); } int start = 0; ArrayList<int[]> result = new ArrayList<int[]>(); Permutation(A,start,n,result); Set<String> sortResult = new TreeSet<String>(); for(int[] out:result){ if(isLegal(A,out,n)){ StringBuilder sb = new StringBuilder(); for(int i=0;i<n-1;i++){ sb.append(out[i]+" "); } sb.append(out[n-1]); sortResult.add(sb.toString()); // System.out.println(sb.toString()); } } for(String list:sortResult){ System.out.println(list); } } in.close(); } private static boolean isLegal(int[] in,int[] out,int n){ LinkedList<Integer> stack = new LinkedList<Integer>(); int i=0; int j=0; while(i<n){ // in 还有元素的时候都需要判断 if(in[i] == out[j]){ // 相等时候就不用入栈,直接后移 i++; j++; }else{ if(stack.isEmpty()){ //空stack 就只有入栈了 stack.push(in[i]); i++; }else{ int top = stack.peek(); // 栈顶元素相等,进行出栈 if(top ==out[j]){ j++; stack.pop(); }else if(i<n){ // 不等时候入栈 stack.push(in[i]); i++; } } } } while(!stack.isEmpty() && j<n){ // in 的结束后,栈中元素进程出栈序列应该和out剩余的元素 相同 int top = stack.pop(); if(top == out[j]){ j++; }else{ return false; } } return true; } /** * 求出所有排列 * @param A * @param start * @param n * @param result */ private static void Permutation(int[] A,int start,int n,ArrayList<int[]> result){ if(start == n){ return; } if(start == n-1){ int[] B = A.clone(); result.add(B); return; } for(int i=start;i<n;i++){ swap(A,start,i); Permutation(A,start+1,n,result); swap(A,start,i); } } private static void swap(int[] A,int i,int j){ int t = A[i]; A[i] = A[j]; A[j] = t; } }