题目分析1:首先数列长度为n,且为1~n中不重复的数字,也就意味着每个数字必须出现且只出现一次。首先,记录下输入中已经出现过的数字,再找出还未出现的数字,通过对未出现的数字进行全排列,再插入到原数组中,将原数组中的0替代掉,然后对替代后的数组进行判断,暴力计算合格排列为K的数列个数。代码如下
#include <iostream>
#include <algorithm>
#include <vector>
const int N = 100;
int vis[N];
using namespace std;
int isOk(int *num,int *queshi, int n,int k)
{
int tmp[N], acc = 0;
for (int i = 1, j = 1; i <= n; i++) //构建新数组,将原数组中的0替代
{
if (num[i] == 0)
{
tmp[i] = queshi[j++];
}
else{
tmp[i] = num[i];
}
//printf("%d ",tmp[i]);
}
for (int i = 1; i<=n - 1; i++) //对新数组进行暴力判断合法排列数目
{
for (int j = i + 1; j<=n; j++)
{
if (tmp[i]<tmp[j])
acc++;
}
}
if (acc == k)
return 1;
else
return 0;
}
void permutation(int *queshi, int *num, int n, int len, int index, int k, int &count )
{
//对数组queshi全排列
if (index > len){//全排列结束
for (int i = 1; i <= len; i++)
{
cout << queshi[i];
}
cout << endl;
if (isOk(num, queshi,n,k) == 1)
{
count++;
}
}
else
for (int i = index; i<=len; ++i){
//将第i个元素交换至当前index下标处
swap(queshi[index], queshi[i]);
//以递归的方式对剩下元素进行全排列
permutation(queshi, num, n, len, index + 1, k,count);
//将第i个元素交换回原处
swap(queshi[index], queshi[i]);
}
}
int main()
{
int n, k;
cin >> n >> k;
int temp;
int count = 0;
int num[N];
int zero = 0;
for (int i = 0; i <= n; i++){
vis[i] = 0;
}
for (int i = 1; i <= n; i++)
{
cin >> temp;
num[i] = temp;
vis[temp] = 1; //记录已经出现的数字
if (temp == 0)
zero++; //记录0的个数,同时也是数组queshi的范围1~zero
}
int queshi[N];
int v = 1;
for (int i = 1; i <= n; i++)
{
if (vis[i] == 0)
{
queshi[v++] = i; //记录没有出现的数字
}
}
///cout << zero;
permutation(queshi,num, n, zero,1, k,count);
cout << count << endl;
//cout << count << endl;
system("pause");
}
题目分析2:
首先找出数组A中的缺失值,将缺失值全排列。
对每一个缺失值序列,将其插入原数组A中,暴力求出顺序对的数量并判断是否合法(即顺序对是否为k)。
数组全排列:求数组[1,2,3,4,5]的全排列。
https://blog.youkuaiyun.com/u010005161/article/details/51811134
1、首先看最后两个数4, 5。 它们的全排列为4 5和5 4, 即以4开头的5的全排列和以5开头的4的全排列。
由于一个数的全排列就是其本身,从而得到以上结果。
2、再看后三个数3, 4, 5。它们的全排列为3 4 5、3 5 4、 4 3 5、 4 5 3、 5 3 4、 5 4 3 六组数。
即以3开头的和4,5的全排列的组合、以4开头的和3,5的全排列的组合和以5开头的和3,4的全排列的组合.
从而可以推断,设一组数p = {r1, r2, r3, … ,rn}, 全排列为perm(p),pn = p - {rn}。
因此perm(p) = r1perm(p1), r2perm(p2), r3perm(p3), … , rnperm(pn)。当n = 1时perm(p} = r1。
为了更容易理解,将整组数中的所有的数分别与第一个数交换,这样就总是在处理后n-1个数的全排列。
//数组全排列
#include <iostream>
#include <vector>
using namespace std;
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 argc, const char * argv[]) {
vector<vector<int>>res;
vector<int> vec={1,2,3};
permutation(res, vec, 0);
for(int i = 0; i < res.size(); i++){
for(int j = 0; j < res[0].size(); j++)
cout<<res[i][j]<<" ";
cout<<endl;
}
return 0;
}
本题代码如下:
//网易数列还原
#include<stdlib.h>
#include<stdio.h>
#include<iostream>
#include<vector>
using namespace std;
bool islegal(vector<int> &A,vector<int> is0_index,vector<int> queshi,int count0,int n,int k) //将缺失值插入数组中,并求数组中顺序对的数量
{
int res=0;
for(int i=0;i<count0;i++)
A[is0_index[i]]=queshi[i]; //将缺失值依次插入数组A中的0的位置
for(int i=0;i<n-1;i++) //计算数组A中顺序对的数目
{
for(int j=i+1;j<n;j++)
{
if(A[i]<A[j])
res++;
}
}
if(res==k) //判断序列是否合法
return true;
else
return false;
}
void quanpailie(vector<int> &queshi,vector<int> &A,vector<int> is0_index,int index,int count0,int n,int k,int &res) //缺失值的全排列
{ //queshi为缺失值,A为输入数组,is0_index为数组中为0的位置下标
if(index>=count0) //全排列结束
{
if(islegal(A,is0_index,queshi,count0,n,k)==true)
res++;
}
else
{
for(int j=index;j<count0;j++)
{
swap(queshi[index],queshi[j]); //将数组中index处的元素和index之后的每一个元素分别交换
quanpailie(queshi,A,is0_index,index+1,count0,n,k,res); //对index之后的元素进行全排列
swap(queshi[index],queshi[j]); //交换回来
}
}
}
int main()
{
int n,k;
cin>>n>>k;
vector<int> A(n); //输入数组
vector<int> queshi; //缺失值
vector<int> is0_index; //数组中为0的位置下标
vector<int> indexA(n+1,0);
int count0=0; //数组中为0的个数
for(int i=0;i<n;i++)
{
cin>>A[i];
if(A[i]==0)
{
is0_index.push_back(i); //缺失值的位置下标
count0++; //缺失值的个数
}
else
{
indexA[A[i]]=1;
}
}
for(int i=1;i<=n;i++)
{
if(indexA[i]==0)
queshi.push_back(i); //缺失值
}
int result=0;
quanpailie(queshi,A,is0_index,0,count0,n,k,result);
cout<<result<<endl;
system("pause");
return 0;
}