火车进站

[编程题]-火车进站

【解题思路】
 
思路为用三个变量分别存储:
待进站火车
站中火车(用 Stack 存储)
已出站火车
具体实现思路:
第一种:
采用递归的方法,递归函数的参数为当前待进站火车、站中火车、已出站火车的值所组成的三元组,递归结
束条件是, 未进站火车和站中火车均为空 ,此时输出已出站火车即为所有出站的一种可能,递推关系为对于
当前情况有让下一辆火车进站或让站中的一辆火车出站两种可能,对于两种可能分别调用递归函数,即可得
出问题的解。
第二种:
采用先对火车编号进行排列组合,计算出所有可能的出站情况。但是火车出站的情况需要满足栈的出栈顺
序,所以通过 火车编号的顺序 排列组合的顺序 进行出栈和入栈来比较排列组合中的一组顺序是否满足条
件,如果满足,则该排序就是有效的出栈顺序。
(下面的代码实现采用第二种思路)
 
【示例代码】
 
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;
      //计算n个火车的出站的编号的排列组合
      ArrayList<int[]> result = new ArrayList<int[]>();
      Permutation(A,start,n,result);
      //出栈的结果,一个元素一个记录,例如:1 2 3 ; 1 3 2
      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());
        }
      }
      //最后输出所有的符合出栈要求的组合
      for(String list:sortResult){
        System.out.println(list);
      }
    }
    in.close();
  }
/*
in : 火车编号数组
out : 火车出站顺序
n : 火车数量
*/
  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;
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值