前几天听一个学长描述了一下他做的几道头条笔试题,自己空闲时间选了一道简单的尝试做了做,由于没有经过校验,答案能对多少,自己也没数,因此读者就当看个乐子,答案是当不得真的。

题目描述

两个人通过加密通信的方式进行通信,每条信息都被编译成二进制数B(明文),其长度为N。信息被写下K次,每次向右移动0,1,……,k-1位。

例如

B=1001010, K=4
1001010
  1001010
    1001010
      1001010

然后对每一列进行异或操作,结果称为S(密文)
上面的结果就为

1110100110

要求是写一个程序去实现这种编码的解密过程

输入

第一行两个整数N和K
第二行一个二进制字符串S, 长度为N+K-1

输出

输出明文B

解题思路

首先要明白异或运算是干嘛的

异或运算:两个数相等就置0,不等就置1。
所以可以看成参与运算的1的数量是单数还是偶数

再次可以知道B的长度为N

然后很明显B的第一位和最后一位就等于S的第一位和最后一位。

private static byte[] decrypt(int N, int K, byte[] S) {

        byte[] answer = new byte[N];      
        answer[0] = S[0];
        answer[N - 1] = S[S.length - 1]; 
}

clipboard.png

可以看出 计算部分要分为两种情况,计算第i 位答案时:

如果i < k 就需要和前面k - i个答案进行运算
如果i >= k 就需要和前面k个答案进行运算

解码的完整代码如下

    private static byte[] decrypt(int N, int K, byte[] S) {

        byte[] answer = new byte[N];
        answer[0] = S[0];
        answer[N - 1] = S[S.length - 1];

        for (int i = 1; i < N - 1; i++) {
            int count = 0;

            int temp;   // 用于存储循环次数

            if (i < K) {
                temp = K - i;
                // 前K个结束
            } else {
                temp = K;
            }

            for (int j = 0; j < temp; j++) {
                if (answer[j] == 1)
                    count++;
            }

            if (count % 2 == 1) {
                if (S[i] == 1) {
                    answer[i] = 1;
                } else {
                    answer[i] = 0;
                }
            } else {
                if (S[i] == 1) {
                    answer[i] = 0;
                } else {
                    answer[i] = 1;
                }
            }
        }

        return answer;
    }

笙歌会停
1k 声望45 粉丝

代码成就万世基积沙镇海 梦想永在凌云意意气风发


引用和评论

0 条评论