0%

leetcode每日一题2020.1.14

1018. 可被 5 整除的二进制前缀

一、题目

给定由若干 01 组成的数组 A。我们定义 N_i:从 A[0]A[i] 的第 i 个子数组被解释为一个二进制数(从最高有效位到最低有效位)。

返回布尔值列表 answer,只有当 N_i 可以被 5 整除时,答案 answer[i]true,否则为 false

示例1:

1
2
3
4
输入:[0,1,1]
输出:[true,false,false]
解释:
输入数字为 0, 01, 011;也就是十进制中的 0, 1, 3 。只有第一个数可以被 5 整除,因此 answer[0] 为真。

示例2:

1
2
输入:[1,1,1]
输出:[false,false,false]

示例3:

1
2
输入:[0,1,1,1,1,1]
输出:[true,false,false,false,true,false]

示例4:

1
2
输入:[1,1,1,0,1]
输出:[false,false,false,false,false]

提示:

  1. 1 ≤ A.length ≤ 30000
  2. A[i]01

二、题解

模拟法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
题解:

对数组 [A[0], A[1], A[2]] 模拟一下这个过程:

第一个数N1:A[0],然后对 5 去余判断是否为0
第二个数N2:A[0] * 2 + A[1],然后对 5 去余判断是否为0
第三个数N3:A[0] * 4 + A[1] * 2 + A[2],然后对 5 去余判断是否为0

我们可以发现 N(i) = N(i-1) * 2 + A[i-1]

考虑到数组 A 可能很长,如果每次都保留 N(i) 的值,则可能导致溢出。

但是因为只需要知道 N(i) 是否可以被 5 整除,因而我们可以每一轮只更新 N(i) % 5,结果不会影响,即

N(i) = (N(i-1) * 2 + A[i-1]) % 5
  • 时间复杂度:O($n$),其中 n 是数组 A 的长度。
  • 空间复杂度:O(1)
1
2
3
4
5
6
7
8
9
10
var prefixesDivBy5 = function(A) {
const ret = [];
let len = A.length;
let prefix = 0;
for (let i=0; i<len; i++) {
prefix = (prefix * 2 + A[i]) % 5;
ret.push(prefix === 0)
}
return ret
};
万一真有土豪呢