• 2017滴滴出行笔试题:异或和为0的最大区间个数


    两个bit的异或(下文均用^代表异或运算):1^0=1 0^1=1 1^1=0 0^0=0,也就是左右元素不同时为1,相同时为0。

    对于两个int的异或,就是对它的二进制表示的每一位进行异或运算,比如2^5=binary(010^101)=binary(111)=7

    并且异或运算满足交换律、结合律,即a^b=b^a,a^b^c=(a^b)^c=a^(b^c)

    异或运算还有性质:x^0=x,x^x=0(这里可以得出推论:若x^y=0,则x=y;)

    OK,到此就可以分析题目了,题目给出数组a[N]找出所有不重叠区间,区间的数字xor和为0。

    这里定义f(i,j)=a[i]^a[i+1]^...^a[j],这里值得注意的是不重叠区间,那么假如有一对重叠区间的xor和为0,那我们应该选择哪一组呢?

    设重叠区间为[b,c],两个区间为[a,c]和[b,d],其中a<=b<c<=d。

    显然应该选择[a,c],因为这样相当于在[c,N]区间寻找xor和为0的子区间数量,而c<=d<N,[c,N]是在[d,N]的基础上多了0个以上数,那么子区间数量肯定不少于[d,N]。

    因此思路就是先找出最左边的子区间,然后在右边剩余区间重复以上操作。

    最左边也就是区间[a,b]满足b最小,也就是b从0到n,如果找到了一组异或和为0的区间[a0,b0],那么b就从b0+1开始,但是a不用从0开始,而是也从a0+1开始。

    因为若存在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;
    }
  • 相关阅读:
    shell脚本的常用参数
    Qt中使用Protobuf简单案例(Windows + msvc)
    使用PicGo和Typora写Markdown
    CentOS7安装protobuf(C++)和简单使用
    protobuf编译、安装和简单使用C++ (Windows+VS平台)
    protocol buffers 文档(一)-语法指导
    Base64编码和其在图片的传输的应用
    Qt程序打包发布
    Qt中的Label和PushButton背景图自动缩放设置
    TCP的粘包和拆包问题及解决
  • 原文地址:https://www.cnblogs.com/Harley-Quinn/p/7513052.html
Copyright © 2020-2023  润新知