2020秋招笔试—复杂异或问题

复杂异或问题

题目

给定一个序列an,下标从1开始直到n,定义了以下式子:
在这里插入图片描述
现在要求下式的值:
在这里插入图片描述
小提示
在这里插入图片描述
样例解释
在这里插入图片描述
这里考察的是异或操作。

思路

  1. 首先注意到异或是支持交换律的,可将待求解的值分为两个部分:将ai全部交换到一起求出异或值,这是由输入序列确定的部分结果;还剩下一个n×n的余数矩阵,它们整体异或到一起构成输入序列个数确定的部分结果。
  2. 输入序列的异或结果十分简单,遍历一次输入序列,取出相异或即可,但剩下的余数矩阵如何处理?
  3. 再次注意到,余数矩阵在列方向上是有周期规律的:第列是0的循环序列,第列是1,0的循环序列,第列是1,2,0的循环序列,第列是1,2,3,0的循环序列,……第n列是1,2,3……n-1,0的循环序列。
  4. 那么先将列方向的余数相异或,第i列,偶数次循环序列相异或的结果都是0,可以抵消掉,剩余的就有单个1,2……i-1,0 序列、不完整的序列 以及单个多余的1,2……i-1,0 和一个不完整序列 1,2,……的组合这三种情况,恰好我们能够根据列序号 i总列数 n相对关系知道是何种剩余情况。
  5. 那么问题来了,序列1,2,3,……n-1,0的异或结果如何求解?事实上,连续整数的异或可以有O(1)复杂度的解法,详细的可以看以下两个链接,这里不进行证明:百度文库 CSDN

这里求余数矩阵单列异或结果的时间复杂度是 O(1) 的,求 n 列余数矩阵异或结果时间复杂度是O(n)的,而求解 ai 异或时间复杂度是 O(n) 的,因此整个解法是 O(n) 的。

代码

public class Solution {
    public int solute(int[] array){
        if(array==null || array.length==0)
            return 0;
        int bn = 0;
        int n = array.length;
        //遍历计算an
        for(int i=0;i<n;i++)
            bn^=array[i];
        //列数从2开始,到第n列结束
        for(int i=2;i<=n;i++){
            //判断剩余序列个数
            int remain = n - n/(2*i);
            //剩余一个序列+若干数
            if (remain >= i) {
                int last = remain - i;
                bn^=XorFrom0ToN(i-1);
                bn^=XorFrom0ToN(last);
            }
            //剩余不足一个序列
            else{
                bn^=XorFrom0ToN(remain);
            }
        }
        return bn;
    }

    private int XorFrom0ToN(int n){
        int mod = n%4;
        if(mod == 0)
            return n;
        else if(mod == 1)
            return 1;
        else if (mod == 2)
            return n+1;
        else
            return 0;
    }
 }

通过测试用例57%,报错运行超时,因此可能有特殊用例没有考虑到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值