【笔试题】网易2018秋招内推笔试

题目一

问题描述
小易有一个长度为n的整数序列,a_1,…,a_n。然后考虑在一个空序列b上进行n次以下操作:
1、将a_i放入b序列的末尾
2、逆置b序列
小易需要你计算输出操作n次之后的b序列。

输入描述

输入包括两行,第一行包括一个整数n(2 ≤ n ≤ 2*10^5),即序列的长度。
第二行包括n个整数a_i(1 ≤ a_i ≤ 10^9),即序列a中的每个整数,以空格分割。

输出描述
在一行中输出操作n次之后的b序列,以空格分割,行末无空格。

注意:要看一下输入输出描述,确定一下,不按要求的话,oj通不过

例子有两种:

个数为奇数:3 (1,2,3) 
1,翻转 1, 
1,2翻转 2,1 
2,1,3翻转 3,1,2 
最后的结果是 3,1,2

个数为偶数时,4(1,2,3,4) 
3,1,2,4翻转后 4,2,1,3

思路

这些有点像高中找规律的题目,先来看看个简短的实例就知道了:

输入:
5
1 2 3 4 5
输出的转变过程:
1--->1
1 2 --->2 1
2 1 3 ---> 3 1 2
3 1 2 4 ---> 4 2 1 3
4 2 1 3 5 ---> 5 3 1 2 4

可以发现,当输入奇数个的时候,把奇数放左边,偶数放右边。当输入个数时偶数个的时候,把偶数放左边,奇数放右边。其实就是先从尾部跳跃取数,到取到头部时在从第二个数开始跳跃取数至倒数第二个。当然需要考虑一些特殊情况,比如只有一个输入的时候。

我的代码如下,因为这是去年的题目,我也没有办法验证其准确率;只能说在本机上通过了我自定义的例子。

先输入n值,然后输入数组一个个push进vector中;

#include<iostream>
#include<vector>

using namespace std;
int main() {
    int n;
    int temp;
    vector<int> resV0, resV1;
    cin >> n;
    for (int i = 0; i < n;i++) {
        cin >> temp;
        resV0.push_back(temp);
    }
    int j = n-1;
    while (j>=0) {
        vector<int> ::iterator temp1;
        temp1 = resV0.begin() + j;
        resV1.push_back(*temp1);
        j -= 2;
    }
    if (n > 1) {
        int j2 = 1;
        while (j2<n) {
            vector<int> ::iterator temp2;
            temp2 = resV0.begin() + j2;
            resV1.push_back(*temp2);
            j2 += 2;
        }
    }
    for (int k = 0; k < n;k++) {
        cout << resV1[k] << ' ';
    }
    cin.get();
    cin.get();
}

题目二

问题描述
小易现在手里有f个水果和d元,一天要消耗x元房租和1个水果,商店售卖一个水果p元,请问小易能坚持几天。

思路

先看f个苹果和d元付房租x能成多少天day_max,如果day_max<=f;这就说明最多只能活day_max天了。如果day_max>f,这就说明可能还有余钱来买苹果来增加天数,那试着买一个苹果,如果买了一个苹果后,天数day还是大于等于原来的苹果数的话,那么我们更新最大天数day_max和苹果数ori_f,之后继续返回前面的逻辑;但如果时天价苹果,或者买了个苹果后发现天数day反而比原来的ori_f小(就是说原来可以活ori_f天的,现在买了个天价苹果,反而加速死亡了),那我们还是选择不买了,就是最后一个else处,直接输出ori_f作为最大天数。

#include<iostream>
using namespace std;

int main() {
    int f, d, x, p, day,day_max,ori_f;
    cin >> f >> d >> x >> p;
    day_max = d / x;
    ori_f = f;
    while (1) {

        if (day_max <= f) {
            cout << day_max << endl;
            break;

        }
        else {
            f += 1;
            day = (d - p) / x;
        }

        if (day >= ori_f) {
            day_max = day;
            ori_f = f;
        }
        else {
            cout << ori_f << endl;
            break;
        }

    }
    cin.get();
    cin.get();

}

问题三

问题描述
疯狂队列,就是给一个数字,要求他们得两两的差值和最大,求这个疯狂值,即:差值。

输入描述

输入包括两行,第一行一个整数n(1 ≤ n ≤ 50),表示学生的人数 
第二行为n个整数h[i](1 ≤ h[i] ≤ 1000),表示每个学生的身高

输出描述

如样例所示: 
5
5 10 25 40 35 
当队列排列顺序是: 35-10-40-5-25, 身高差绝对值的总和为25+30+35+20=110。 
其实25-10-40-5-35这样的排序与上面结果一样,因为都是两边内部两个数的和与外部和的差绝对值。

这是最大的疯狂值了

大神AC代码

根据样例提示,猜想了一个结论:
我们要把这个队列安排为交错的形式(证明略)。
交错有两种形式,看第一个人是比他相邻的人高还是矮。
以矮的为例:
总共的疯狂值为(h2 - h1) + (h2 - h3) + (h4 - h3) + … = -h1 + 2h2 - 2h3 + 2h4 - …,
如果总共是偶数个人,疯狂值为-h1 + 2h2 - 2h3 + 2h4 - … - 2h{n-1} + h{n},所以我们需要从最大的开始依次安排h2,…h{n-2},然后安排h{n},然后继续安排剩下的。
如果总共是奇数个人,疯狂值为-h1 + 2h2 - 2h3 + 2h4 - … + 2h{n-1} - h{n},所以我们需要从最大的开始依次安排h2,…h{n-1},然后安排h1和h{n},然后继续安排剩下的。
然后另外一种形式类似,维护最大的疯狂值即可

#include <iostream>
#include<algorithm>

using namespace std;

int h[55];
int n;
int main()
{
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> h[i];
    sort(h, h + n);
    int tmp, ans = 0, ans1 = 0, ans2 = 0;
    if (n % 2 == 0)
    {
        tmp = n / 2;
        for (int i = 0; i < tmp; i++)
        {
            ans += 2 * (h[tmp + i] - h[i]);
        }
        ans += h[tmp - 1] - h[tmp];
        cout << ans << endl;
        return 0;
    }
    else
    {
        tmp = n / 2;
        for (int i = 0; i < tmp; i++)
        {
            ans1 += 2 * (h[tmp + 1 + i] - h[i]);
            ans2 += 2 * (h[tmp + 1 + i] - h[i]);
        }
        ans1 += -h[tmp] + h[tmp - 1];
        ans2 += h[n] - h[n + 1];
        cout << max(ans1, ans2) << endl;
        return 0;
    }
    return 0;
}

问题四

问题描述

判断数列能否是等差数列,
分析:先排序,然后再比较差值。

思路

先用快速排序将原始数组从小到大排序,再比较差值是否相等。
快速排序详情:点这里

#include <iostream>
#include<algorithm>
#include<vector>
void quicksort(int lo, int hi);
int pivotsort(int lo, int hi);
using namespace std;

vector<int> resV1;
int main(){
    int temp;
    int i = 0;
    while (cin >> temp) { //这样输入完成得按CTRL+Z  Enter来结束
        resV1.push_back(temp);
    }
    int n = resV1.size();
    if (n < 3) { 
        cout << "是" << endl;
        cin.get();
        cin.get();
        return 0; }
    quicksort(0, n - 1);
    for (int k = 1; k < n-1;k++) {
        if (2 * resV1[k] - resV1[k - 1] - resV1[k + 1] != 0) {
            cout << "否" << endl;
            cin.get();
            cin.get();
            return 0;
        }
    }
    cout << "是" << endl;
    cin.get();
    cin.get();
    return 0;
}

void quicksort(int lo,int hi) {
    if (hi - lo < 1) { return; }
    int mid = pivotsort(lo,hi);
    quicksort(lo, mid);
    quicksort(mid + 1, hi);
}

int pivotsort(int lo,int hi) {
    int pivot = resV1[lo];

    while (lo<hi) {
        while ((lo<hi) && (resV1[hi] >= pivot)) {
            hi--;
        }
        resV1[lo] = resV1[hi];
        while ((lo<hi)&&(resV1[lo]<=pivot)) {
            lo++;
        }
        resV1[hi] = resV1[lo];
    }
    return lo;
}

问题五

s = “ABAB”,那么小易有六种排列的结果:
“AABB”,”ABAB”,”ABBA”,”BAAB”,”BABA”,”BBAA”
其中只有”AABB”和”BBAA”满足最多只有一对不同颜色的相邻砖块。

思路

输出只有一对不同颜色的相邻砖块组合;若本身有大于2种砖块颜色,那么不可能存在。这题目我也是看别人转的,不清楚具体要输出什么,哈哈哈。

#include <iostream>
#include<cstring>
//#include<algorithm>
#include<vector>
#include<string>
#include<map>

using namespace std;

int main(){
    string str;
    getline(cin,str);
    map<char, int> mapstr;
    int n = str.size();
    if (n==0) {
        cout << "空的" << endl;
        cin.get();
        return 0;
    };
    for (int i = 0; i < n;i++) {
        mapstr.insert(pair<char, int>(str[i], 1)); //用字典去重
    }
    if (mapstr.size() > 2) { 
        cout << "不满足" << endl;
        cin.get();
        return 0; 
    }
    if (mapstr.size()==1) {
        cout << "一个" << endl;
        cin.get();
        return 0;
    };
    if (mapstr.size()==2) {
        cout << "一对" << endl;
        cin.get();
        return 0;
    };

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值