1. 程式人生 > >【筆試題】網易2018秋招內推筆試

【筆試題】網易2018秋招內推筆試

今天下午3點到五點做了網易秋招內推筆試題,晚上的時候牛妹就把程式設計題的答案發出來了,聽說有幾萬人參加了,嚇死。。。。。感覺自己太弱。

下面是我做的三道筆試題,一共有八道。。。。。

題目一

問題描述
小易有一個長度為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通不過

分析問題

我當初做的時候,通過率才80%。。。。。
例子有兩種,
個數為奇數: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

觀察上面的結果
奇數的時候,先寫1,然後把2放在1的後面,然後把3放在1的前面(先後面,再前面)
偶數的時候,先寫1,然後把2放在1的前面,3放在後面,4放在前面,(先前面,再後面)。

發現,自己的錯誤,只分析了一種情況,,,,還以為是邊界之類的問題

本人AC程式碼

#include <bits/stdc++.h>
using namespace std;

int main()
{

    int n;
    cin >> n;
    int *arr = new int[n];
    for (int i = 0; i < n; i++)
        cin >> arr[i];

    std::list<int> list;
    list.push_back(arr[0]);
    //奇數,先後面,再前面
if(n %2 == 1) { for (int i = 1; i < n; ++i) { if (i % 2 == 1) list.push_back(arr[i]); else list.push_front(arr[i]); } } //偶數 先前面,再後面 else { for (int i = 1; i < n; ++i) { if (i % 2 == 1) list.push_front(arr[i]); else list.push_back(arr[i]); } } //注意:輸出格式要與題目的輸出格式匹配。 int idx = 0; for (; idx < n - 1; ++idx) { cout << list.front() << " "; list.pop_front(); } cout << list.front() << endl; delete[] arr; return 0; }

大神的AC程式碼

對比,自己的程式碼,發現自己low啊,寫這麼多的程式碼,解決這個問題。自己的思路太複雜了

大神的思路是:
個數是奇數的時候:奇數放在左邊,偶數放在右邊
個數是偶數的時候:偶數放在左邊,奇數放在右邊


#include <bits/stdc++.h>

using namespace std;

const int maxn = 2e5 + 5; //邊界問題

int a[maxn];
int n;
int main() 
{
    scanf("%d", &n);
    //注意::從1開始,儲存的
    for(int i = 1; i <= n; i++) 
        scanf("%d", &a[i]);
    if(n % 2) // 4,2,1,3
    {   //先輸出 4 2
        for(int i = n; i >= 1; i -= 2)
            printf("%d ", a[i]);
        //控制輸出空格,最後一個沒有輸出空格
        for(int i = 2; i <= n; i += 2)
            i == n - 1 ? printf("%d", a[i]) : printf("%d ", a[i]);
    } 
    else //3,1,2
    {
        for(int i = n; i >= 1; i -= 2)
            printf("%d ", a[i]);
        for(int i = 1; i <= n; i += 2)
            i == n - 1 ? printf("%d", a[i]) : printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
}

問題二

問題描述
小易現在手裡有f個水果和d元,一天要消耗x元房租和1個水果,商店售賣一個水果p元,請問小易能堅持幾天。

問題分析
簡單的一批,,,呵呵,本菜雞通過率才70%。。。(一把辛酸)
(原來是,沒考慮一天也活不下去。。。。還是弱)
計算1天花多少錢:x+p
先計算能不能活f天,(看d元夠不夠f天的房租)

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int x, f, d, p;//房租,水果個數,錢,水果價錢
    while (cin >> x >> f >> d >> p)
    {
        if (x < 1)
            return -1;
        int onespend = x + p; //一天花費
        //先判斷能不能活f天
        int day = d / x;
        if (day <= f)
        {
            cout << day;
            return 0;
        }
        d -= f*x;
        day = f + d / onespend;
        cout << day;
    }
    return 0;
}

問題三

問題描述
瘋狂佇列,就是給一個數字,要求他們得兩兩的差值和最大,求這個瘋狂值,即:差值。

輸入描述
輸入包括兩行,第一行一個整數n(1 ≤ n ≤ 50),表示學生的人數
第二行為n個整數h[i](1 ≤ h[i] ≤ 1000),表示每個學生的身高

輸出描述
如樣例所示: 5 10 25 40 25
當佇列排列順序是: 25-10-40-5-25, 身高差絕對值的總和為15+30+35+20=100。
這是最大的瘋狂值了

分析問題
要想差值最大,先把最大值放上,然後把兩個最小值,放在左右兩邊,
再將兩個次大值,放在兩個最小值的兩邊。

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n;
    while(cin>>n)
    {
        vector<int> v(n,0);
        for(int i=0;i<n;i++)
        {
            cin>>v[i];
        }
        if(n==1)
        {
            cout<<0<<endl;
        }
        sort(v.begin(),v.end());
        deque<int> d;
        int l=0,r=n-1;
        d.push_front(v[r]);
        r--;
        while(l<=r)
        {
            if(l<=r)
            {
                d.push_front(v[l++]);
                if(l<=r)
                    d.push_back(v[l++]);
            }
            if(l<=r)
            {
                d.push_front(v[r--]);
                if(l<=r)
                    d.push_back(v[r--]);
            }
        }
        //最後一個元素可能會錯位,剩餘中間的三個數字
        //{ 10, 15, 30, 45, 50, 60, 70, 90 }; 
        //45-30-10-90-15-60-50 
        if(abs(d[n-1]-d[n-2])<abs(d[n-1]-d[0])){
            d.push_front(d.back());
            d.pop_back();
        }
        int res=0;
        for(int i=1;i<n;i++){
            res+=abs(d[i]-d[i-1]);
        }
        cout<<res<<endl;
    }
    return 0;
}

大神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 <bits/stdc++.h>
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 <bits/stdc++.h>
using namespace std;

int n;
int arr[55];

string solve(){
    sort(arr,arr+n);
    if(n < 2)
        return "Possible";
    else{
        int d = arr[1] - arr[0];      
        for(int i = 2; i < n; ++i){
            if(arr[i] - arr[i-1] != d)
                return "Impossible";
        }
    }
    return "Possible";
}
int main(){
    cin >> n;
    for(int i = 0; i < n; i++) 
        cin >> arr[i];
    cout << solve() << endl;
}

問題五

s = “ABAB”,那麼小易有六種排列的結果:
“AABB”,”ABAB”,”ABBA”,”BAAB”,”BABA”,”BBAA”
其中只有”AABB”和”BBAA”滿足最多隻有一對不同顏色的相鄰磚塊。

分析
思路就是看字串裡有幾種字元,超過兩種就不可能只有一對相鄰的不同字元,有兩種字元就是兩種正確的排列,有一種字元自然就是一種正確的排列。
就是先排序,然後過濾掉重複的,或者直接把字元放在set中,set預設不能插入相同的值。

int main()
{
    string str;
    cin >> str;
    sort(str.begin(), str.end());
    str.erase(unique(str.begin(), str.end()), str.end());
    size_t ans = str.size();
    if (ans > 2)
        ans = 0;
    cout << ans << endl;
    return 0;
}

問題六

問題描述

如果一個01串任意兩個相鄰位置的字元都是不一樣的,我們就叫這個01串為交錯01串。例如: “1”,”10101”,”0101010”都是交錯01串。

輸入包括字串s,s的長度length(1 ≤ length ≤ 50),字串中只包含’0’和’1’,求出最大字串是01串的長度。

思路:就是按個比較字串,維護最大值。

int main()
{
    string str;
    cin >> str;
    int len = 1, ans = 1;
    for (int i = 1; i < str.size(); ++i)
    {
        if (str[i] != str[i - 1])
            len++;
        else
            len = 1;
    }
    ans = max(ans, len);
    cout << ans << endl;
    return 0;
}

問題七

問題描述
小易將n個棋子擺放在一張無限大的棋盤上。第i個棋子放在第x[i]行y[i]列。同一個格子允許放置多個棋子。每一次操作小易可以把一個棋子拿起並將其移動到原格子的上、下、左、右的任意一個格子中。小易想知道要讓棋盤上出現有一個格子中至少有i(1 ≤ i ≤ n)個棋子所需要的最少操作次數.
輸入描述
輸入包括三行,第一行一個整數n(1 ≤ n ≤ 50),表示棋子的個數
第二行為n個棋子的橫座標x[i](1 ≤ x[i] ≤ 10^9)
第三行為n個棋子的縱座標y[i](1 ≤ y[i] ≤ 10^9)
4
1 2 4 9
1 1 1 1
輸出描述
輸出n個整數,第i個表示棋盤上有一個格子至少有i個棋子所需要的運算元,以空格分割。行末無空格
0 1 3 10

如樣例所示:
對於1個棋子: 不需要操作
對於2個棋子: 將前兩個棋子放在(1, 1)中
對於3個棋子: 將前三個棋子放在(2, 1)中
對於4個棋子: 將所有棋子都放在(3, 1)中

暴力列舉,嘗試每個節點

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

const int INTMAX = 2147483647;

struct Point
{
    int x = 0;
    int y = 0;
}p[55];

int dis(int x,int y, const Point &b)
{
    return abs(x - b.x) + abs(y - b.y);
}

int main()
{
    int n, i, j;
    cin >> n;
    for (i = 1; i <= n; ++i)
    {
        cin >> p[i].x;
    }
    for (i = 1; i <= n; ++i)
    {
        cin >> p[i].y;
    }
    vector<vector<int>> min_step;
    for (int x = 1; x <= n; ++x)
    {
        for (int y = 1; y <= n; ++y)
        {
            vector<int> tmp;
            for (int k = 1; k <= n; ++k)
            {
                tmp.push_back(dis(p[x].x, p[y].y, p[k]));
            }
            sort(tmp.begin(), tmp.end());
            min_step.push_back(tmp);
        }
    }
    for (i = 1; i <= n; ++i)
    {
        int ans = INTMAX;
        for (j = 0; j < min_step.size(); ++j)
        {
            int temp = 0;
            for (int k = 0; k < i; ++k)
            {
                temp += min_step[j][k];
            }
            ans = min(ans, temp);
        }
        cout << ans;
        if (i != n) cout << " ";
        else cout << endl;
    }
    return 0;
}

問題八

小易非常喜歡擁有以下性質的數列:
1、數列的長度為n
2、數列中的每個數都在1到k之間(包括1和k)
3、對於位置相鄰的兩個數A和B(A在B前),都滿足(A <= B)或(A mod B != 0)(滿足其一即可)
例如,當n = 4, k = 7
那麼{1,7,7,2},它的長度是4,所有數字也在1到7範圍內,並且滿足第三條性質,所以小易是喜歡這個數列的
但是小易不喜歡{4,4,4,2}這個數列。小易給出n和k,希望你能幫他求出有多少個是他會喜歡的數列。

分析問題
可以發現長度為4時的數列是當n為3時數列減去不合法的序列。
定義一個全域性的陣列,記錄每個長度的合法數列的和。
dp[ j ][ i ] 表示長度為i,最後一個數是j的小易喜歡的數列的數量,
dp[j][i] += dp[m][i-1] (1<=m<=k),
判斷非法的情況,直接判斷是約數的情況下,就非法。

const int mod = 1e9 + 7;
const int maxn = 1e5 + 5;
int dp[maxn][15];
int n, k;
int main() 
{
    cin >> n >> k;//n長度
    dp[1][0] = 1;
    for (int i = 1; i <= n; i++) 
    {
        int sum = 0;
        for (int j = 1; j <= k; j++)
        {
            sum += dp[j][i - 1];
            sum %= mod;
        }
        for (int j = 1; j <= k; j++) 
        {
            int sum2 = 0;//非法的,約數的時候是非法的
            for (int z = j + j; z <= k; z += j) 
            {
                sum2 += dp[z][i - 1];
                sum2 %= mod;
            }
            dp[j][i] = (sum - sum2 + mod) % mod;
        }
    }
    int ans = 0;
    for (int j = 1; j <= k; j++) 
    {
        ans += dp[j][n];
        ans %= mod;
    }
    cout << ans << endl;
    return 0;
}