网易的内推的机试题
有一组n个数的数列(1~n),是乱序的。小明不小心水翻了弄湿了数列,导致几个数字看不清了,但是他记得顺序对的个数(对于i<j,有A[i]<A[j]),请你根据此找出符合顺序对个数的数列的个数。不符合情况则输出-1.
输入:n ,k
一组数列(0代表看不清的数字)
输出:m 种符合的情况
例子;
输入:5 5
4 0 0 2 0
输出:2
解答:
我的做法是:找出那些需要填入进行的数字组,以及需要填入的位置。对这组数字进行全排序,然后将他们填入空缺的位置上,再对组成的这个数列进行逆序对的判断。而顺序对的个数=C(n)(2) - 逆序列的个数。若顺序对个数符合,则count+1.最后输出结果
以下是我的代码:
//
// main.cpp
// pro1
//
// Created by zjl on 16/8/2.
// Copyright © 2016年 zjl. All rights reserved.
//
// 输入:5 5
// 4 0 0 2 0
//一共5个数(1~5),5对顺序对。0是缺失值,填补缺失值
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
int MergeArray(vector<int>&arry,int start,int mid,int end,vector<int>& temp)//数组的归并操作
{
//int leftLen=mid-start+1;//arry[start...mid]左半段长度
//int rightLlen=end-mid;//arry[mid+1...end]右半段长度
int i=mid;
int j=end;
int k=0;//临时数组末尾坐标
int count=0;
//设定两个指针ij分别指向两段有序数组的头元素,将小的那一个放入到临时数组中去。
while(i>=start&&j>mid)
{
if(arry[i]>arry[j])
{
temp[k++]=arry[i--];//从临时数组的最后一个位置开始排序
count+=j-mid;//因为arry[mid+1...j...end]是有序的,如果arry[i]>arry[j],那么也大于arry[j]之前的元素,从a[mid+1...j]一共有j-(mid+1)+1=j-mid
}
else
{
temp[k++]=arry[j--];
}
}
while(i>=start)//表示前半段数组中还有元素未放入临时数组
{
temp[k++]=arry[i--];
}
while(j>mid)
{
temp[k++]=arry[j--];
}
//将临时数组中的元素写回到原数组当中去。
for(i=0;i<k;i++)
arry[end-i]=temp[i];
return count;
}
int InversePairsCore(vector<int>&arry,int start,int end,vector<int>& temp)
{
int inversions = 0;
if(start<end)
{
int mid=(start+end)/2;
inversions+=InversePairsCore(arry,start,mid,temp);//找左半段的逆序对数目
inversions+=InversePairsCore(arry,mid+1,end,temp);//找右半段的逆序对数目
inversions+=MergeArray(arry,start,mid,end,temp);//在找完左右半段逆序对以后两段数组有序,然后找两段之间的逆序对。最小的逆序段只有一个元素。
}
return inversions;
}
int InversePairs(vector<int>&arry,int len)
{
vector<int>temp(len);
int count=InversePairsCore(arry,0,len-1,temp);
return count;
}
int judge(vector<int>&a) {
return InversePairs(a, a.size());
}
/*
void solve(vector<int>& number, vector<int>& loss, int& count, int l,int k, vector<vector<int>>& rr){
if(l == 0){
vector<int>v(number.begin()+1, number.end());
int len = number.size()-1;
judge(v);
int value = len*(len-1)/2 - ress;
if(value == k){
count++;
rr.push_back(number);
}
ress = 0;
return;
}
for(int i = 1; i < number.size(); i++){
if(number[i] == 0){
for(int j = 0; j < loss.size(); j++){
if(loss[j] != 0){
number[i] = loss[j];
loss[j] = 0;
solve(number, loss, count, l-1, k,rr);
loss[j] = number[i];
}
number[i] = 0;
}
}
}
}
*/
void permutation(vector<vector<int>>& res, vector<int>& num, int index){
if(index >= num.size()){
res.push_back(num);
return;
}
for(int i = index; i < num.size(); i++){
swap(num[i], num[index]);
permutation(res, num, index+1);
swap(num[index], num[i]);
}
}
int main()
{
int n,k;
while(cin>>n>>k){
vector<int>num(n+1,0);
vector<int>number(n+1,0);
vector<int>loss,pos;
vector<vector<int>>rr;
vector<vector<int>> results;
int count = 0, l = 0;
for(int i = 1; i < n+1; i++){
int t;
cin >> t;
number[i] = t;
if(t>0)
num[t] = 1;
}
for(int i = 1; i < n+1; i++){
if(num[i] == 0){
loss.push_back(i);
l++;
}
if(number[i] == 0)
pos.push_back(i);
}
//solve(number, loss, count, l, k,rr);
permutation(rr, loss, 0);
for(int kk = 0; kk < rr.size(); kk++){
for(int k = 0; k < l; k++)
number[pos[k]] = rr[kk][k];
vector<int>v(number.begin()+1, number.end());
int len = number.size()-1;
int res = judge(v);
int value = len*(len-1)/2 - res;
if(value == k){
count++;
results.push_back(number);
}
}
cout<<count<<endl;
if(count == 0){
cout<<-1<<endl;
break;
}
for(int i = 0; i < results.size(); i++){
for(int j = 1; j < results[1].size(); j++)
cout<<results[i][j];
cout<<endl;
}
}
return 0;
}
运行情况:
输入:
5 5
4 0 0 2 0
输出:
2
41523
43125