题目1018:
1018. 题目如下
在这里插入代码片给定由若干 0 和 1 组成的数组 A。我们定义 N_i:从 A[0] 到 A[i] 的第 i个子数组被解释为一个二进制数(从最高有效位到最低有效位)。
返回布尔值列表 answer,只有当 N_i 可以被 5 整除时,答案 answer[i] 为 true,否则为 false。
示例 1:
输入:[0,1,1] 输出:[true,false,false] 解释: 输入数字为 0, 01, 011;也就是十进制中的 0, 1, 3
。只有第一个数可以被 5 整除,因此 answer[0] 为真。
示例 2:
输入:[1,1,1] 输出:[false,false,false]
示例 3: 输入:[0,1,1,1,1,1] 输出:[true,false,false,false,true,false]
在这里先做一个数学推导:
M
÷
a
=
N
.
.
.
.
.
.
b
M \div a = N ...... b
M÷a=N......b
那么
2
M
÷
a
=
2
N
.
.
.
.
.
.
.
.
2
b
2 M \div a = 2 N ........2 b
2M÷a=2N........2b
当然这是很不严谨的写法
如果我们只关心余数,则
c
M
÷
a
=
(
c
N
+
⌊
c
b
a
⌋
)
.
.
.
.
.
.
.
.
[
(
c
b
)
%
a
]
cM \div a = (cN + \left\lfloor\frac{cb}{a}\right\rfloor)........[ (cb)\%a ]
cM÷a=(cN+⌊acb⌋)........[(cb)%a]
(
d
+
M
)
÷
a
=
(
N
+
⌊
d
+
b
a
⌋
)
.
.
.
.
.
.
.
[
(
d
+
b
)
%
a
]
(d+M) \div a = (N + \left\lfloor\frac{d+b}{a}\right\rfloor).......[(d+b)\%a]
(d+M)÷a=(N+⌊ad+b⌋).......[(d+b)%a]
即若一个数除以a的余数为b,则c倍该数的余数为 cb % a,该数加上一个附加项d的余数为(d+b) % a。
与本题的联系
示例 3: 输入:[0,1,1,1,1,1] 输出:[true,false,false,false,true,false]
- 二进制数组为”0“,能被5整除,余数为0
- 原二进制数组<<1 (即乘2),后加一,则余数为 (2*0 + 1)% 5 = 1
- 同推导公式,余数为 (2*1+1)%5 = 3
- (2*3+1)%5 = 2
- (2*2+1)%5 = 0
- (2*0+1)%5 = 1
则我们可以定义状态机机状态转移:
class Solution(object):
def prefixesDivBy5(self, A):
"""
:type A: List[int]
:rtype: List[bool]
"""
ans = []
TransitionArr = [[0,2,4,1,3],[1,3,0,2,4]]
if A[0] == 0:
ans.append(True)
else:
ans.append(False)
prev = A[0]
for i in range(1,len(A)):
modulus = TransitionArr[A[i]][prev]
if modulus == 0:
ans.append(True)
else:
ans.append(False)
prev = modulus
return ans