筆試 | 2020貝殼秋招筆試題講解&源碼

第一題

題目描述

給定一個長度爲n的字符串,問至少替換多少個字符變換成迴文串?node

分析

  • 咱們把字符串前一半和後一半拆成兩個字符串,而後比較有多少個字符不相等便可
  • 或者設置兩個指針left和right分別指向字符串的開始和結尾,讓他們同時向中間逼近,若是left和right位置的字符不等,那麼就須要作替換操做

解法

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

int main() {
    int n; cin >> n;
    string s; cin >> s;
    string s1, s2;
    int length = s.size();
    s1 = s.substr(0, (length + 1) / 2);
    s2 = s.substr(length / 2, (length + 1) / 2);
    reverse(s2.begin(), s2.end());
    int ans = 0;
    for (int i = 0; i < s1.size(); ++i) {
        if (s1[i] != s2[i])
            ans ++;
    }
    cout << ans << endl;
    return 0;
}
#include <bits/stdc++.h>

using namespace std;

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

第二題

題目描述

給你一個NxM的方格圖,如今要求你對其中每一個1x1的小方格進行染色,要求以下:c++

  • 每種顏色的格子數都是相同的
  • 相鄰格子染色不一樣
  • 全部格子必須染色如今最少要多少種顏色就能夠完成任務。

輸入描述

  • 第一行一個整數T,表示測試數據組數
  • 接下來T行每行兩個空格分割的正整數N, M,表明方格的行數和列數
  • 1 <= T <= 100>
  • 1 <= N, M <= 1e8

輸出描述

  • 共T行每行一個整數表示答案

分析

  • 若是沒有「每種顏色的格子數都是相同的」這個要求的話,用兩種顏色就能夠完成這個任務。
  • 加上「每種顏色的格子數都是相同的」,那麼最終用的顏色數 應該是 的一個因子,也就是說 應該是 的因子或者是 的因子。那麼咱們只要知道 或者 的最小因子是多少就能夠了。
  • 注意處理 或者 的狀況,這個時候2種顏色就能夠;若是兩個都等於1,那麼1種顏色就能夠。

解法

#include <bits/stdc++.h>

using namespace std;

#define ll long long
ll get_min(ll num) {
    if (num % 2 == 0return 2;
    for (ll i = 3; i * i <= num; i += 2) {
        if (num % i == 0return i;
    }
    return num;
}
int main() {
    ll a, b;
    int t; cin >> t;
    while(t--) {
        cin >> a >> b;
        if (a == 1 && b == 1cout << 1 << endl;
        else if (a == 1 || b == 1cout << 2 << endl;
        else cout << min(get_min(a), get_min(b)) << endl;
    }
    return 0;
}

第三題

題目描述

給出一個正整數序列A,求一個子區間使得這個區間內的數或起來儘量的大。求全部知足條件的子區間裏面,最短子區間長度。web

分析

  • 求最大或區間的最短長度,這種MaxMin的問題能夠優先考慮用二分解決。這裏能夠枚舉區間起點,二分區間長度。
  • 那麼剩下的問題就是,對於指定起點Ai和終點Aj,怎麼快速算出這個子區間的或運算結果。這裏能夠利用前綴和的思想,對第i個數計算前i個數裏面每一位的出現次數。求區間或運算結果的時候,只須要知道這個區間裏面哪些位出現過便可。
  • 對每個數Ai計算出以它爲起點的最大或區間最短長度,就能夠獲得題目的解。
  • 另外,當指定起點時,從這個起點開始最長的序列必定是值最大的,因此這裏能夠提早作一些剪枝,你們能夠本身嘗試一下。

解法

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000002;
int A[maxn];

class BitCount{
public:
    int bcount[32];
    BitCount(){};
    BitCount(int* _bcount) {
        for (int i = 0; i < 32; i ++)
            this->bcount[i] = _bcount[i];
    }
    BitCount operator-(const BitCount& x) {
        BitCount ret;
        for (int i = 0; i < 32; i ++) {
            ret.bcount[i] = this->bcount[i] - x.bcount[i];
        }
        return ret;
    }
    int to_int() {
        int ret = 0;
        for (int i = 31; i >= 0; i --) {
            ret = ret * 2;
            if (this->bcount[i])
                ret += 1;
        }
        return ret;
    }
};

BitCount bitCount[maxn];
int bitCountSum[32];

void update_bitsum(int x) {
    int bit = 0;
    while (x) {
        if (x % 2)
            bitCountSum[bit] ++;
        bit ++;
        x /= 2;
    }
}

int calc_or(int i, int j) {
    int x = (bitCount[j + 1] - bitCount[i]).to_int();
    //printf("calc: %d %d %d\n", i, j, x);
    return x;
}

int bin_search(int i, int right, int& len) {
    int left = 1;
    int value = calc_or(i, i + right - 1);
    len = right;
    while (left <= right) {
        int mid = (left + right) / 2;
        int tmpValue = calc_or(i, i + mid - 1);

        if (tmpValue >= value) {
            value = tmpValue;
            len = mid;
            right = mid - 1;
        }
        else {
            left = mid + 1;
        }
    }
    return value;
}


int main() {
    int n; cin >> n;

    for (int i = 0; i < n; i ++) {
        cin >> A[i];
        update_bitsum(A[i]);
        bitCount[i + 1] = BitCount(bitCountSum);
    }

    int maxValue = 0;
    int ans = 0;
    for (int i = 0; i < n; i ++) {
        int len = 0;
        int value = bin_search(i, n - i, len);
        if (value > maxValue) {
            maxValue = value;
            ans = len;
        } else if (value == maxValue && len < ans) {
            ans = len;
        }
    }
    cout << ans << endl;
    return 0;
}

關注公衆號可添加小編微信加入面試筆試交流&刷題羣,與更多的小夥伴一塊兒上岸~祝你好運:)面試

聽說點在看的都拿到了offer?


本文分享自微信公衆號 - 超哥的雜貨鋪(gh_a624b94bfdab)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。微信

相關文章
相關標籤/搜索