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


    题目描述

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

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

    示例

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

    提示:

    • 1 <= A.length <= 30000
    • A[i] 为 0 或 1

    解题思路

    暴力破解

    如已知A=[0,1,0],变换 B=['0', '1', '0'],变换C=['0', '01', '010'],之后将C中每个值进行判断即可。

    • 优点:简单直接,不存在思路上的困难;
    • 缺点:解法不论是在空间还是时间上不占优;
    class Solution:
        def prefixesDivBy5(self, A: List[int]) -> List[bool]:
            List = A	# 初始化List
            str_A = [str(i) for i in A]	# 将A转换成字符串数组
    
            if A[0] == 0:	# 判断第一个数字是否符合
                List[0] = True
            else: List[0] = False
            
            if len(str_A) == 1:
                return List
            else:
                str_res = str_A	# str_res初始化
                str_res[0] = str_A[0]
                for j in range(1, len(str_A)):
                    str_res[j] = str_res[j-1] + str_A[j]
                    int_res = int(str_res[j],2)
                    if int_res % 5 == 0:
                        List[j] = True
                    else: List[j] = False
                return List
    

    数学分析

    在进行代码优化前,我们先从数学角度进行分析,会得出如下结论:
    (N_i)为A中从下标0到下标i构成的二进制数,则有:

    • (N_0 = A[0])
    • (N_i = N_{i-1} *2 + A[i], i>0)(这是二进制的左移性质)

    所以,我们可以将上面“数字-字符串-数字”的过程变成上面递推公式的计算。但是这个思路存在的问题:考虑到数组A可能很长,如果每次都保留(N_i)的值,则可能导致溢出。

    解决方案:(M_i=N_i mod 5=(N_{i-1} *2 + A[i])mod5=(M_{i-1} *2 + A[i])mod5),即可以用余数代替N完成运算。

    在上面思路的基础上,代码如下:

    class Solution:
        def prefixesDivBy5(self, A: List[int]) -> List[bool]:
            ans = list()
            prefix = 0
            for num in A:
                prefix = ((prefix << 1) + num) % 5
                ans.append(prefix == 0)
            return ans
    

    prefix初始化为0,0<<1左移的结果仍然是0。

    思路总结

    本题侧重于数学分析,如果分析不到位,会出现两种情况:

    • 使用(N_{i-1}*2)去递推得到(N_i)的值,最后因为数值过大造成溢出;
    • 当作字符串处理(暴力破解法),尽管没有溢出问题,但是性能不佳。
  • 相关阅读:
    MySQL复制延时排查
    SQL优化之【类型转换】
    Twemproxy 介绍与使用
    Redis Cluster 3.0搭建与使用
    unauthenticated user reading from net
    XtraBackup之踩过的坑
    Redis学习之实现优先级消息队列
    如何保证接口的幂等性
    Redis缓存网页及数据行
    Rabbitmq 消费者的推模式与拉模式(go语言版本)
  • 原文地址:https://www.cnblogs.com/rongyupan/p/14277863.html
Copyright © 2020-2023  润新知