1、牛客网原题:
题目描述
牛牛的作业薄上有一个长度为 n 的排列 A,这个排列包含了从1到n的n个数,但是因为一些原因,其中有一些位置(不超过 10 个)看不清了,但是牛牛记得这个数列顺序对的数量是 k,顺序对是指满足 i < j 且 A[i] < A[j] 的对数,请帮助牛牛计算出,符合这个要求的合法排列的数目。
输入描述:
每个输入包含一个测试用例。每个测试用例的第一行包含两个整数 n 和 k(1 <= n <= 100, 0 <= k <= 1000000000),接下来的 1 行,包含 n 个数字表示排列 A,其中等于0的项表示看不清的位置(不超过 10 个)。
输出描述:
输出一行表示合法的排列数目。
示例1
输入
5 5 4 0 0 2 0
输出
2
2、思路:
(1)记录排列中没有的元素(X1,X2,X3...),并升序排序(记录字典排序需要用到的所有值)。
(2)将(X1,X2,X3...)序列,进行一次字典排序,然后按顺序插入到原序列A中为0的位置处。
(3)对插入(X1,X2,X3...)序列后的序列A,检验其顺序对个数是否等于k。
(4)对每一次的字典排序,重复执行(2)(3),即找出所有符合要求的合法排列。
3、code:已a
package schooloffer17;
import java.util.*;
/**
* Created by caoxiaohong on 17/11/1 16:55.
* 字典排序加强版
*/
public class DataRecovery {
public static void main(String[] args) {
int n,k;
Scanner scanner=new Scanner(System.in);
ArrayList<Integer> list=new ArrayList<Integer>();
ArrayList<Integer> notHas=new ArrayList<Integer>();
while (scanner.hasNextInt()){
n=scanner.nextInt();
k=scanner.nextInt();
for(int i=0;i<n;i++) {
list.add(scanner.nextInt());
}
//查找没有的元素
for(int i=1;i<=n;i++){
if(!list.contains(i))
notHas.add(i);
}
Collections.sort(notHas);//升序
int size=notHas.size();
int solutions=0;
//notHas当前状态是否符合 有k个顺序对
solutions+=getSolution(list,notHas,k);
while(true){
boolean isFind=false;
for(int i=size-2;i>=0;i--){
if(notHas.get(i)<notHas.get(i+1)){
isFind=true;
for(int j=size-1;j>i;j--){
if(notHas.get(j)>notHas.get(i)){
int tmp1=notHas.get(j);
notHas.set(j,notHas.get(i));
notHas.set(i,tmp1);
//从i+1~(size-1)进行升序排序
int low=i+1,high=size-1;
while (low<high){
int tmp2=notHas.get(low);
notHas.set(low,notHas.get(high));
notHas.set(high,tmp2);
low++;
high--;
}
solutions+=getSolution(list,notHas,k);
}
}
}else{
isFind=false;
}
}
if(!isFind)
break;
}
System.out.println(solutions);
//清空输入列表
list.clear();
notHas.clear();
}
}
/**对于ArrayList查找顺序对个数
* 顺序对定义: i < j 且 A[i] < A[j]
* @param list
* @return
*/
private static int getCount(ArrayList<Integer> list){
int len=list.size();
int res=0;
for(int i=0;i<len;i++){
for(int j=i+1;j<len;j++){
if(list.get(j)>list.get(i))
res++;
}
}
return res;
}
/**
* 本次字典排序 是否符合顺序对为k个
* @param list
* @param notHas
* @param k
* @return
*/
private static int getSolution(ArrayList<Integer> list,ArrayList<Integer> notHas,int k){
int size=notHas.size();
ArrayList<Integer> original=new ArrayList<Integer>();
original.addAll(list);
//将新生成的字典序数组插入list中元素为0的位置
int from=0;
for(int p=0;p<size;p++){
for(int q=from;q<list.size();q++){
if(list.get(q)==0){
list.set(q,notHas.get(p));
from=q+1;
break;
}
}
}
//查询顺序对个数
int kk=getCount(list);
//恢复list原值
Collections.copy(list,original);
if(kk==k)
return 1;
else
return 0;
}
}

本文介绍了一种解决牛客网排列恢复问题的算法。该问题要求根据已知的顺序对数量,恢复一个部分缺失的排列。算法通过字典排序未出现的元素,并将其插入到缺失位置来寻找所有可能的解决方案。

931

被折叠的 条评论
为什么被折叠?



