2017滴滴出行筆試題:異或和爲0的最大區間個數

兩個bit的異或(下文均用^表明異或運算):1^0=1 0^1=1 1^1=0 0^0=0,也就是左右元素不一樣時爲1,相同時爲0。ios

對於兩個int的異或,就是對它的二進制表示的每一位進行異或運算,好比2^5=binary(010^101)=binary(111)=7數組

而且異或運算知足交換律、結合律,即a^b=b^a,a^b^c=(a^b)^c=a^(b^c)spa

異或運算還有性質:x^0=x,x^x=0(這裏能夠得出推論:若x^y=0,則x=y;)3d

OK,到此就能夠分析題目了,題目給出數組a[N]找出全部不重疊區間,區間的數字xor和爲0。code

這裏定義f(i,j)=a[i]^a[i+1]^...^a[j],這裏值得注意的是不重疊區間,那麼假若有一對重疊區間的xor和爲0,那咱們應該選擇哪一組呢?blog

設重疊區間爲[b,c],兩個區間爲[a,c]和[b,d],其中a<=b<c<=d。ci

顯然應該選擇[a,c],由於這樣至關於在[c,N]區間尋找xor和爲0的子區間數量,而c<=d<N,[c,N]是在[d,N]的基礎上多了0個以上數,那麼子區間數量確定很多於[d,N]。it

所以思路就是先找出最左邊的子區間,而後在右邊剩餘區間重複以上操做。io

最左邊也就是區間[a,b]知足b最小,也就是b從0到n,若是找到了一組異或和爲0的區間[a0,b0],那麼b就從b0+1開始,可是a不用從0開始,而是也從a0+1開始。class

由於若存在f(a0,b0+t)=0,那麼易證f(b0+1,b0+t)也爲0,能夠分紅2個異或和爲0的區間。

更詳細的證實就不用說了,有這樣的思路後直接上代碼吧。

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

void solution(int a[], int n)
{
    int cnt = 0;  // 閉區間個數
    vector<int> v;
    v.reserve(n);

    int low = 0;  // 閉區間左邊界的下限(即上一個找到異或和爲0的閉區間右邊界+1)
    for (int i = 0; i < n; i++)
    {    // 查找以i爲閉區間的右邊界的區間是否存在知足異或和爲0的
        v.clear();
        // 依次加入a[k]、a[k-1]^a[k]、...、a[low]^a[low+1]^...^a[k]
        v.push_back(a[i]);
        for (int j = i - 1; j >= low; j--)
        {
            v.push_back(v.back() ^ a[j]);
        }
        if (find(v.begin(), v.end(), 0) != v.end())
        {    // 存在異或和爲0的子區間
            cnt++;
            low = i + 1;  // 更新閉區間左邊界, 避免重複查找
        }
    }
    cout << cnt << endl;
}


int main()
{
    int n;
    cin >> n;
    vector<int> v(n);
    for (int i = 0; i < n; i++)
    {
        cin >> v[i];
    }
    solution(&v[0], n);
    return 0;
}
相關文章
相關標籤/搜索