2017届网易内推笔试-机器学习(数据挖掘)编程第二题求解

昨晚这题没做出来,不甘心,不甘心,不甘心啊,难道只能枚举了吗?求大神攻破,以身相许了!!!!!!!
大致题意(如果有问题望指正,谢谢):
课桌上n个格子摆放成一行,里面放着1~n的正整数(乱序),有几个(不超过10个)格子看不清是什么数字,
但是牛牛记得整个序列中有k个有序对,即当 i<j 时,A[i]<A[j]。求满足所有条件的序列有多少种?
输入:第一行输入n k,第二行输入序列,看不清的数字用0代替,其中1<n<100,1<k<10000000000
例:
输入:
5 5
4 0 0 2 0
输出:
2
ps:满足条件的2种序列可以找到为:4 3 1 2 5、4 1 5 2 3(均满足有5个有序对)
/********************************************************************************************************/
//谢谢牛友的提示,以下纯手写,望批评指正!!!
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector<vector<int> > permutation(int n){
    //全排列
    vector<vector<int> > res;
    vector<int> num(n);
    for(int i=0;i<num.size();i++){
        num[i]=i+1;
    }
    do{
        res.push_back(num);
    }while(next_permutation(num.begin(),num.end()));  //如果知道这个next_permutation是库函数,是不是好做很多,不知道的是因为leetcode没刷好
    return res;
}

void finduse(vector<vector<int> > &res,vector<int> data){
    //找出满足看的清的数字的所有序列
    for(int i=0;i<res.size()-1;i++){
        for(int j=0;j<data.size();j++){
            if(data[j]!=res[i][j]&&data[j]!=0){
                res.erase(res.begin()+1);
                i--;
                break;
            }
        }
    }
}

int findsum(vector<vector<int> > res,int k){
    //找到满足k个有序对的所有序列,计算这样序列的个数
    int ll=res.size();
    int l=(*res.begin()).size();
    int count=0;
    for(int i=0;i<ll;i++){
        int sum=0;
        for(int j=0;j<l-1;j++){
            for(int s=j+1;s<l;s++){
                if(res[i][j]<res[i][s])
                    sum++;
            }
        }
        if(sum==k)
        count++;
    }
    return count;
}

int main(){
    int n;
    int k;
    while(cin>>n>>k){
        if(n<=0||n>100)
            break;
        vector<int> data(n);
        for(int t=0;t<n;t++){
            cin>>data[t];
        vector<vector<int> > res = permutation(n);
        finduse(res,data);
        int count = findsum(res,k);
        cout<<count<<endl;
    }
    return 0;  
}
#网易##C++工程师#
全部评论
再贴一种方法哈,昨天吃饭时候跟朋友讨论,换了一种思路,昨天晚上做了一下。 #include <iostream> #include <vector> #include <string> #include <queue> #include <unordered_map> #include <map> #include <algorithm> using namespace std; //输入参数 int n;//输入n个数 int k;//有序对k对 vector<int> a;//输入序列a,包含1~n的n个数,有若干个数(不超过10个)是0 //输出参数 int cnt=0;//合法排列的数目 //输出perm数组,用于测试 void printperm(const vector<vector<int> > &perm) { for(int i=0;i<perm.size();i++) { for(int j=0;j<perm[0].size();j++) cout<<perm[i][j]<<" "; cout<<endl; } } //第一步,选出用于全排列的数 void chooseperm(vector<int> &permuse) { vector<int> permtemp; int permnum=0;//需要全排列的数的个数 int temp=0; for(int i=1;i<=n;i++)//初始化为1~n permtemp.push_back(i); for(int i=0;i<a.size();i++)//移除输入中已有的数 { if(a[i]) { remove(permtemp.begin(),permtemp.end(),a[i]); temp++; } } permnum=n-temp;//n-移除的数,即需要全排列的数的个数 for(int i=0;i<permnum;i++)//得到用于全排列的vector permuse.push_back(permtemp[i]); } //第二步,对第一步选出的数全排列 void creatperm(vector<vector<int> > &perm,vector<int> &permuse) { do{ perm.push_back(permuse); }while(next_permutation(permuse.begin(), permuse.end())); } //第三步,拼接第二步得到的全排列的二维vector和已有的输入 void insertperm(vector<vector<int> > &perminsert,const vector<vector<int> > &perm) { for(int i=0;i<perm.size();i++) { vector<int> tempinsert; int q=0; for(int p=0;p<n;p++) { if(a[p]) tempinsert.push_back(a[p]); else tempinsert.push_back(perm[i][q++]); } perminsert.push_back(tempinsert); } } //第四步,逐行验证其有序对是否为k,统计符合的个数 void count( const vector<vector<int> > &choose) { for(int i=0;i<choose.size();i++) { int ktemp=0; vector<int> temp=choose[i]; for(int j=0;j<temp.size();j++) { for(int jj=j+1;jj<temp.size();jj++) { if(temp[j]<temp[jj]) ktemp++; } } if(ktemp==k) cnt++; } } int main(){ //输入 cin>>n>>k; for(int i=0;i<n;i++) { int temp; cin>>temp; a.push_back(temp); } //第一步,选出用于全排列的数 vector<int> permuse;//用于全排列的数 chooseperm(permuse); cout<<"用于全排列的数"<<endl; for(int i=0;i<permuse.size();i++) cout<<permuse[i]<<" "; cout<<endl; //第二步,对第一步选出的数全排列 vector<vector<int> > perm;//得到全排列的二维vector creatperm(perm,permuse); cout<<"全排列"<<endl; printperm(perm); //第三步,拼接第二步得到的全排列的二维vector和已有的输入 vector<vector<int> > perminsert; insertperm(perminsert,perm); cout<<"符合模板的排列"<<endl; printperm(perminsert); //第四步,逐行验证其有序对是否为k,统计符合的个数 count(perminsert); cout<<"符合的排列个数"<<endl; cout<<cnt<<endl; }
点赞 回复 分享
发布于 2016-08-07 09:49
小岛说是暴力 搜索,或者next permutation  
点赞 回复 分享
发布于 2016-08-03 19:32
以身相许什么鬼! 这题很简单啊。 说了不超过10个数没给,你生成一个全排列,一个一个判断就行了
点赞 回复 分享
发布于 2016-08-03 19:34
当时用的就是暴力求解: 1、先将1~n全排列(permutation),生成一个二维数组备用(每一行代表一种排序方式); 2、过滤该二维数组,选取满足特定位置上为输入序列中非0数的序列,生成新的二维数组; 3、最后一步就比较简单了,只要逐行验证其有序对是否为K,统计符合的个数即为满足条件的数量。
点赞 回复 分享
发布于 2016-08-03 19:39
第三题做出来了?
点赞 回复 分享
发布于 2016-08-04 15:21
回去想的,用全排列,逐个搜索 #include<stdio.h> int p[4000000][100];//保存剩余数的全排列   int num=0;//保存剩余数全排列个数  int count=0;//保存i<j,a[i]<a[j]的个数  void swap(int &a,int &b) { int t; t=a; a=b; b=t; } //求剩余数的个数  int less(int *a,int *b,int n)//扫描b[n],如果有b[j]=a[i],b中从j开始每项往前面移一位 ,s记录b中剩余个数;  { int i,j,k,s=n; for(i=0;i<n;i++) for(j=0;j<n;j++) { if(a[i]==0) break; if(b[j]==a[i]) { s--;  for(k=j;k<n-1;k++) { b[k]=b[k+1]; } break; } }  return s;  }  //剩余的数全排列  void perm(int a[],int start,int n)//a[n]数组从a[start]开始全排列,结果放在b[num][n]中 ,num计数  { int i; int *c; if(start==n-1) { for(i=0;i<n;i++) p[num][i]=a[i]; num++; return; } else { for(i=start;i<n;i++) { swap(a[i],a[start]); perm(a,start+1,n); swap(a[i],a[start]); } } } //剩余排列数p[x][m]加到a[n]=0中  void add(int a[],int n,int x) { int i=0,j=0; for(i=0;i<n;i++) { if(a[i]==0) { a[i]=p[x][j]; j++;    } } } //计算是否k个 ,若是count++  void cou(int a[],int n,int k) { int i,j,c=0; for(i=0;i<n-1;i++) for(j=i+1;j<n;j++) { if(a[i]<a[j]) c++; } if(c==k) count++; } int main() { int n,k,m,i,j; while(scanf("%d%d",&n,&k)!=EOF) { int a[n],b[n],c[n]; for(i=0;i<n;i++) { scanf("%d",&a[i]); b[i]=i+1; } m=less(a,b,n); perm(b,0,m); for(i=0;i<num;i++) { for(j=0;j<n;j++) c[j]=a[j]; add(c,n,i); cou(c,n,k); } printf("%d\n",count); count=0; num=0; }  } 
点赞 回复 分享
发布于 2016-08-04 15:25
这道题是我的第三题,我用python写的,通过了70%。我的第二题特别难,是算最大路径的,我当时没写出来。
点赞 回复 分享
发布于 2016-08-04 23:45
没明白题意
点赞 回复 分享
发布于 2016-08-05 12:07
#include <iostream> #include <vector> #include <algorithm> using namespace std; //输入参数 int n;//输入n个数 int k;//有序对k对 vector<int> a;//输入序列a,包含1~n的n个数,有若干个数(不超过10个)是0 //输出参数 int cnt=0;//合法排列的数目 //输出perm数组,用于测试 void printperm(const vector<vector<int> > &perm) { for(int i=0;i<perm.size();i++) { for(int j=0;j<perm[0].size();j++) cout<<perm[i][j]<<" "; cout<<endl; } } //将1~n全排列,放入二维数组perm void creatperm(vector<vector<int> > &perm) { vector<int> temp;//1~n的临时vector for(int i=1;i<=n;i++) temp.push_back(i); do{ perm.push_back(temp); }while(next_permutation(temp.begin(), temp.end())); } //过滤,刷掉返回false,如果没有刷掉返回true bool chooseperm(const vector<int> &permtemp) { for(int i=0;i<n;i++) { if(a[i]) { if(a[i]!=permtemp[i]) return false; } } return true; } //计算cnt void count( const vector<vector<int> > &choose) { for(int i=0;i<choose.size();i++) { int ktemp=0; vector<int> temp=choose[i]; for(int j=0;j<temp.size();j++) { for(int jj=j+1;jj<temp.size();jj++) { if(temp[j]<temp[jj]) ktemp++; } } if(ktemp==k) cnt++; } } int main(){ //输入 cin>>n>>k; for(int i=0;i<n;i++) { int temp; cin>>temp; a.push_back(temp); } //第一步 //先将1~n全排列(permutation),生成一个二维数组备用(每一行代表一种排序方式); vector<vector<int> > perm;//用于存放全排列的二维vector creatperm(perm); cout<<"全排列:"<<endl; printperm(perm);//测试生成是否正确 //第二步 //过滤该二维数组,选取满足特定位置上为输入序列中非0数的序列,生成新的二维数组; vector<vector<int> > choose;//过滤之后的二维数组 for(int i=0;i<perm.size();i++) { if(chooseperm(perm[i])) choose.push_back(perm[i]); } cout<<"过滤后:"<<endl; printperm(choose);//测试生成是否正确 //第三步 //逐行验证其有序对是否为k,统计符合的个数; count(choose); cout<<"符合的排列个数"<<endl; cout<<cnt<<endl; }
点赞 回复 分享
发布于 2016-08-06 17:29
DFS全排列  (这个当时好像过了70%) 优化方法,分支限界法剪枝。 不过。不好意思代码木有
点赞 回复 分享
发布于 2016-08-06 17:42

相关推荐

河和静子:如果大专也能好过的话,我寒窗苦读几年的书不是白读了?
点赞 评论 收藏
分享
点赞 14 评论
分享
牛客网
牛客企业服务