这是我参与「掘金日新计划 · 2 月更文挑战」的第 20 天,点击查看活动详情
问题描述
给定一个二进制数组 nums ( 索引从 0 开始 )。
我们将 xi 定义为其二进制表示形式为子数组 nums[0..i] (从最高有效位到最低有效位)。
例如,如果 nums =[1,0,1] ,那么 x0 = 1, x1 = 2, 和 x2 = 5。 返回布尔值列表 answer,只有当 xi 可以被 5 整除时,答案 answer[i] 为 true,否则为 false。
示例 1:
输入:nums = [0,1,1]
输出:[true,false,false]
解释:
输入数字为 0, 01, 011;也就是十进制中的 0, 1, 3 。只有第一个数可以被 5 整除,因此 answer[0] 为 true 。
示例 2:
输入:nums = [1,1,1]
输出:[false,false,false]
提示:
- 1 <= nums.length <= 10^5
- nums[i] 仅为 0 或 1
思路分析
首先我们先要理解一下题目意思,题目会给我们一个二进制数组,我们需要判断每一个位置的二进制数字能否被 5 整除。如:[0,1,1],我们可以得到这样三个二进制数字:0、01、011,转换成十进制后为0、1、3,其中0可以被 5 整除,1和3都不可以被5整除,所以我们可以得到答案数组[true,false,false]。
这道题目的难度主要在于如何快速求出每一个下标对应的数字,我们可以知道 2 ^ n = 2 ^ (n - 1) + 2 ^ (n - 2) + ... + 2 ^ 1 + 2 ^ 0,我们可以分析一下每个位置的数字:
i = 0 -> num0 = nums[0]
i = 1 -> num1 = nums[0] * 2 + nums[1] = num0 * 2 + nums[1]
i = 2 -> num2 = (nums[0] * 2 + nums[1]) * 2 + nums[2] = num1 * 2 + nums[2]
i = n - 1 -> num(i - 1) = ...... = num(i - 2) * 2 + nums[i - 1]
i = n -> numi = ...... = num(i - 1) * 2 + nums[i]
看到这里大家其实就大概知道该怎么做了吧!知道了每一个位置的数值计算公式之后,我们便可以开始进行解题了,我们可以遍历这个数组,通过前一个位置的数字可以快速递推出当前位置的数字,因为判断是否可以被5整除我们可以通过数字的个位数来判断,所以我们只需要记录前一个位置的个位数即可,通过递推公式可以快速求出每一个位置的数值,在判断其是否可以被5整除即可。
完整 AC 代码如下:
AC 代码
/**
* @param {number[]} nums
* @return {boolean[]}
*/
var prefixesDivBy5 = function (nums) {
const res = [];
let num = 0;
for (let i = 0; i < nums.length; i++) {
if (i < nums.length) {
num = (num * 2) % 10;
}
num += nums[i];
res.push(num % 5 == 0);
}
return res;
};
说在后面
本人为算法业余爱好者,平时只是随着兴趣偶尔刷刷题,如果上面分享有错误的地方,欢迎指出,感激不尽。