根据顺序对个数找符合条件的数列

网易的内推的机试题

有一组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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值