网易2018校招内推编程题合集部分

今天分享一下网易2018校招内推编程题合集的部分编程题的思路和代码实现。
first:彩色砖块
小易有一些彩色的砖块。每种颜色由一个大写字母表示。各个颜色砖块看起来都完全一样。现在有一个给定的字符串s,s中每个字符代表小易的某个砖块的颜色。小易想把他所有的砖块排成一行。如果最多存在一对不同颜色的相邻砖块,那么这行砖块就很漂亮的。请你帮助小易计算有多少种方式将他所有砖块排成漂亮的一行。(如果两种方式所对应的砖块颜色序列是相同的,那么认为这两种方式是一样的。)
例如: s = "ABAB",那么小易有六种排列的结果:
"AABB","ABAB","ABBA","BAAB","BABA","BBAA"
其中只有"AABB"和"BBAA"满足最多只有一对不同颜色的相邻砖块。
思路解析
其实这道题只用计算,这些彩砖里有几种颜色而已。(不用下面代码这样麻烦,不过正确)
有0块彩砖,符合的方式为零;
只含1种颜色的彩砖,符合方式为1;
拥有2种颜色的彩砖,符合方式为2;
拥有2种以上颜色的彩砖,不(没办法)符合要求,所以符合的方式为零。
代码实现
#include<iostream>
using namespace std;
#include<string>
 
intHowNum(string & str){
    intsize=str.size();//彩砖的块数
    if(size<=1) returnsize;//有0块砖或1块砖
 
    chartmp[2]={'#','#'};//存放这一对砖的字符颜色
     
    for(inti=0; i<size; i++){
        intj=0;
        for( ; j<2; j++){
            if(tmp[j]=='#'){
                tmp[j]=str[i];
                break;
            }
            elseif(tmp[j] == str[i])
                break;
        }
        if(j==2) return0;//这size块砖中有超过两种颜色
    }
    if(tmp[1]=='#') return1;//这size块砖中只有一种颜色
    elsereturn2;//这size块砖中只有两种颜色
}
 
intmain(){
    string str;
    cin>>str;
    if(str.size()>=0&& str.size()<=50){
     cout<<HowNum(str)<<endl;
    }
     
    return0;
}
second:等差数组
如果一个数列S满足对于所有的合法的i,都有S[i + 1] = S[i] + d, 这里的d也可以是负数和零,我们就称数列S为等差数列。
小易现在有一个长度为n的数列x,小易想把x变为一个等差数列。小易允许在数列上做交换任意两个位置的数值的操作,并且交换操作允许交换多次。但是有些数列通过交换还是不能变成等差数列,小易需要判别一个数列是否能通过交换操作变成等差数列
思路解析
首先把数组S用STL库中的sort函数排序。
如果数组S是等差数列,则用数组最后一个数减去数组第一个数除以个数减一的值就是d值,且不存在余数,继续下一步;如果存在除数,即可判断数组S不是等差数组。
随后遍历数组,判断数组中当前值加d值是否等于后一个元素值?如果不等,则可判断数组S不是等差数组;反之,继续向后遍历判断,直到遍历判断完整个数组为止,才可判断数组S是等差数组。
代码实现
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>

bool IsPossible(vector<int> & str,int num){
if(num<=1) return true;
sort(str.begin(), str.end());//将数组排序

if((str[num -1]-str[0])%(num-1) != 0) return false;//数组最后一个数减去数组第一个数除以个数减一的值存在余数,不是等差数列
int d=(str[num-1]-str[0])/(num-1);//等差数列差值
int i=1;
int cur=str[0]+d;
while(i<num){
if(str[i++] != cur) return false;//后一个不等以前一个加d值,不是等差数组
cur += d;
}
return true;
}

int main(){
int num=0;
cin>>num;
if(num>=0 && num<=50)//数组个数要满足题意
{
vector<int> tmp(num);//数组S
for(int i=0; i<num; i++){
cin>>tmp[i];
if(tmp[i]>1000 || tmp[i]<0) return 0;//数组中元素值要满足题意
}
if(IsPossible(tmp, num))
cout<<"Possible"<<endl;
else
cout<<"Impossible"<<endl;
}
return 0;
}
third:最长01串
如果一个01串任意两个相邻位置的字符都是不一样的,我们就叫这个01串为交错01串。例如: "1","10101","0101010"都是交错01串。
小易现在有一个01串s,小易想找出一个最长的连续子串,并且这个子串是一个交错01串。小易需要你帮帮忙求出最长的这样的子串的长度是多少。
思路解析
其实就是通过遍历字符串找出最长01串,利用标志位记录前一个位置的元素,再判断标志位为1,则当前元素为0或者标志位为0,则当前元素为1的条件是否存在?不存在,则01串到此止,把当前01字符串长度与之前记录的01字符串最长的长度比较,找到新的01字符串最长的长度,继续遍历判断;如果存在,继续遍历判断。知道字符串到头,得到01字符串最长的长度即可。
代码实现
#include<iostream>
using namespace std;
#include<string>
 
intMaxLen(string & str){
    intflag=0;//默认标志位为0,标志前一个位置的元素
    if(str[0]=='1'){//第一个是1,则标志位为1
        flag=1;
    }
    intcount=0;//记录01字符串最长的长度
    intcur=1;//记录当前01字符串长度
    inti=1;
    while(str[i]){
       if(flag==1&& str[i]=='0'){//前一个元素为1,则当前元素为0
           cur++;
           flag=0;
       }
        elseif(flag==0&& str[i]=='1'){//前一个元素为0,则当前元素为1
           cur++;
           flag=1;
        }
        else{//不满足要求
            if(cur>count)//当前01字符串长度大于之前记录的01字符串最长的长度
                count=cur;//替换
            cur=1;//当前01字符串长度归1
            flag=str[i]-'0';//记录当前字符为标志位
        }
        i++;
    }
    if(cur>count)
    count=cur;
     
    returncount;
}
 
intmain(){
    string str;
    cin>>str;
    while(str.size()<0|| str.size()>50){
        cin>>str;
    }
     
    cout<<MaxLen(str)<<endl;
    return0;
}
fourth:移动逆序序列
小易有一个长度为n的整数序列,a_1,...,a_n。然后考虑在一个空序列b上进行n次以下操作:
1、将a_i放入b序列的末尾
2、逆置b序列
小易需要你计算输出操作n次之后的b序列。
思路解析
虽然这道题看上去很复杂,其实是一个与奇偶相关的问题,逆序的次数与数组的就有关。相当于把一个数组依次遍历从另一个等长的数组中间开始放数据,如果数组个数是奇数,第一个数放在中间位置,接下来的数字,按照左下标和右下标,依次一右一左的放;如果数组个数是偶数,所有数字按照左下标和右下标,依次一右一左的放。
图解如下(数组的最后一个数会放在最左边,即开头位置):

代码实现
#include<iostream>
using namespace std;
#include<string>
#include<vector>
 
 
vector<long>  AfterTurn(vector<long> & aim, intn)//逆置
{
    vector<long> tmp;//存放B序列的数组
    tmp.resize(n);
    intmid=n/2;//下标值
    inti=0;
 
    if(n%2!=0){
        tmp[mid]=aim[0];
        i=1;
    }
 
    intl=mid-1;
    intr=mid+i;//i=0,从mid开始;i=1;从mid+1开始
    while(i<n){
        tmp[r]=aim[i];
        r++;
        if(i+1<n){
            tmp[l]=aim[i+1];
            l--;
        }
        i+=2;
    }
     
    returntmp;
}
 
 
intmain(){
    intn;
    cin>>n;
    if(n>=2&& n<=200000){
        vector<long> aim;
    string ch;
 
    while(aim.size() < n){
        cin>>ch;
        longtmp=0;
        inti=0;
        while(ch[i]!='\0'&& ch[i]!='/n'){
            tmp=tmp*10+ch[i++]-'0';
        }
        aim.push_back(tmp);
    }
 
    vector<long> tmp=AfterTurn(aim, n );
 
    for(inti=0; i<n; i++){//打印b序列
        cout<<tmp[i];
        if(i<n-1)
        cout<<" ";
    }
    cout<<endl;
    }
     
    return0;
 
}
fifth:吃水果独立生活
小易为了向他的父母表现他已经长大独立了,他决定搬出去自己居住一段时间。一个人生活增加了许多花费: 小易每天必须吃一个水果并且需要每天支付x元的房屋租金。当前小易手中已经有f个水果和d元钱,小易也能去商店购买一些水果,商店每个水果售卖p元。小易为了表现他独立生活的能力,希望能独立生活的时间越长越好,小易希望你来帮他计算一下他最多能独立生活多少天。
思路解析
这是一道数学应用题,两个方程即可解。
生活天数:
如果d-f*x>=0,则小易能靠f个水果只花f*x元生活f天,之后在生活(d-f*x)/(p+x)天,小易一共生活了f+(d-f*x)/(p+x)天.
如果d-f*x<0,则小易能生活d/x天,虽然还有水果,但付不起房租了。
代码实现
#include<iostream>
using namespace std;
 
intExitDay(intx,intf,intd,intp){
    intday=0;
 
    if(d-f*x>0){
        d-=f*x;
        day=f;
        day += d/(p+x);
    }
    else{//虽然还有水果,但付不起房租了
        day=d/x;
    }
 
    returnday;
}
 
intmain(){
    intx,f,d,p;
    scanf("%d %d %d %d",&x,&f,&d,&p);
 
    cout<<ExitDay(x,f,d,p)<<endl;
     
    return0;
}
sixth:疯狂的队列
小易老师是非常严厉的,它会要求所有学生在进入教室前都排成一列,并且他要求学生按照身高不递减的顺序排列。有一次,n个学生在列队的时候,小易老师正好去卫生间了。学生们终于有机会反击了,于是学生们决定来一次疯狂的队列,他们定义一个队列的疯狂值为每对相邻排列学生身高差的绝对值总和。由于按照身高顺序排列的队列的疯狂值是最小的,他们当然决定按照疯狂值最大的顺序来进行列队。现在给出n个学生的身高,请计算出这些学生列队的最大可能的疯狂值。小易老师回来一定会气得半死。
思路解析
本题要让排队使每对相邻排列学生身高差的绝对值总和最大。则最高的人左右分别是最低和次第的人即可,最低的人身边是最高和次高的人即可。
类似于第4题的解法,先是最后的元素放右边,再是最前的元素放左边,其次是次后的元素放左边,最后次前的元素放右边,依次进行,且每一步都要灵活改变左右下标和前后下标的位置,直到前后指针相遇并错开后停止。
最重要的是数组长度n是4的倍数时,mid(中间值的下标)的位置要加1,为了让最后一个次大值分布在次小值的左右,得到最大身高差总和(找出来的规律,我就不画图了);反之,mid(中间值的下标)为n除以2取整不变。
代码实现
#include<iostream>
using namespace std;
#include<vector>
#include<string>
#include<algorithm>
 
intSum(vector<int> seq, intn){
    sort(seq.begin(), seq.end());
 
    vector<int> tmp;//疯狂数组
    tmp.resize(n);
    intmid=n/2;
    if(n%2!=0&& mid%2!= 0)//****n%4 != 0//数组长度n是4的倍数时,mid(中间值的下标)的位置要加1
        mid++;

    intl=mid-1;//疯狂数组的左下标
    intr=mid;//疯狂数组的右下标
 
    intbegin=0;//原数组的前下标
    intend=n-1;//原数组的后下标
    while(begin<=end && (r<n || l>=0) ){
        if(begin<=end && r<n)//最后的元素放右边
            tmp[r++]=seq[end--];
        if(begin<=end && l>=0)//最前的元素放左边
            tmp[l--]=seq[begin++];
        if(begin<=end && r<n)//次后的元素放左边
            tmp[r++]=seq[begin++];
        if(begin<=end && l>=0)//次前的元素放右边
            tmp[l--]=seq[end--];
    }
 
    intsum=0;
    for(inti=1;i<n;i++){
        sum+=abs(tmp[i-1]-tmp[i]);
    }
 
    returnsum;
}
 
intmain(){
    intn;
    cin>>n;
    while(n<1|| n>50){
        cin>>n;
    }
 
    vector<int> seq;
    string ch;
 
    //aim.clear();
    while(seq.size() < n){
        cin>>ch;
        inttmp=0;
        inti=0;
        while(ch[i]!='\0'&& ch[i]!='/n'){
            tmp=tmp*10+ch[i++]-'0';
        }
        if(tmp<1000|| tmp>1)
        seq.push_back(tmp);
    }
     
    cout<<Sum(seq, n)<<endl;
 
    return0;
}
分享如上,望各位看的放心,学的开心!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值