题目来源于力扣(LeetCode)
一、题目
题目相关标签:数组
提示:
1 <= A.length <= 30000
A[i]
为0
或1
二、解题思路
-
遍历数组,对数组上的元素进行二进制数字的计算操作
-
定义变量 j,j 初始值为 0,用于存储当前遍历元素及其索引之前的全部元素组成的二进制数字
使初始值为 0,可以防止元素首位元素为 0 的情况
-
计算方式:j 左移一位加上当前遍历的元素
元素只为 0 或 1
-
考虑到数组 A 的长度取值范围是 1 到 30000,则需要处理数值溢出的情况
long 类型也不够用
-
处理数值溢出:每次都对 j 进行取余 5 的操作,使 j 的值控制在较小的数值内
三、代码实现
public static List<Boolean> prefixesDivBy5(int[] A) {
List<Boolean> list = new ArrayList<>(A.length);
// 变量 j 记录数组前 i 项组成的二进制数字的十进制形式
int j = 0; // 初始和声明为 0
for (int i = 0; i < A.length; i++) {
// 当前遍历元素与之前元素所能组成的二进制数字,用十进制表示
// 每次遍历都左移 1 位,即乘 2,加上当前遍历元素的值,为 0 或为 1
j = (j << 1) + A[i];
// 对 5 取余并赋值取余的结果,因数组长度过大,有溢出风险
// 对 j 赋值 j 取余 5 的结果,该操作并不会影响判断的结果
j %= 5;
// j == 0 时,说明当前遍历元素与前面全部的元素组成的二进制数字能够被 5 整除
list.add(j == 0 ? Boolean.TRUE : Boolean.FALSE);
}
return list;
}
四、执行用时
五、部分测试用例
public static void main(String[] args) {
int[] arr = {0, 1, 1}; // output:{true, false, false}
// int[] arr = {1, 1, 1}; // output:{false, false, false}
// int[] arr = {0, 1, 1, 1, 1, 1}; // output:{true, false, false, false, true, false}
// int[] arr = {1, 1, 1, 0, 1}; // output:{fasle, false, false, false, false}
List<Boolean> result = prefixesDivBy5(arr);
System.out.println(result);
}