网易数列还原

这里写图片描述

题目分析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.csdn.net/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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值