Binary Prefix Divisible By 5
EasyPrompt
You are given a binary array nums (0-indexed).
We define xi as the number whose binary representation is the subarray nums[0..i] (from most-significant-bit to least-significant-bit).
- For example, if
nums = [1,0,1], thenx0 = 1,x1 = 2, andx2 = 5.
Return an array of booleans answer where answer[i] is true if xi is divisible by 5.
Example 1:
Input: nums = [0,1,1]
Output: [true,false,false]
Explanation: The input numbers in binary are 0, 01, 011; which are 0, 1, and 3 in base-10.
Only the first number is divisible by 5, so answer[0] is true.Example 2:
Input: nums = [1,1,1]
Output: [false,false,false]
Constraints:
1 <= nums.length <= 105nums[i]is either0or1.
Approaches
2 approaches with complexity analysis and trade-offs.
A much more efficient approach avoids dealing with large numbers altogether by using modular arithmetic. The key insight is that to check for divisibility by 5, we only need the remainder of the number when divided by 5, not the number itself. We can maintain this remainder as we iterate through the binary array.
Algorithm
- Create an empty
List<Boolean>calledanswer. - Initialize an integer
remainderto 0. - Loop through each
bitin thenumsarray. - Update the
remainderusing the formula:remainder = (remainder * 2 + bit) % 5. - Check if the new
remainderis 0. - Add
truetoanswerifremainderis 0, otherwise addfalse. - After the loop, return
answer.
Walkthrough
The recurrence relation for the number x_i formed by the prefix nums[0...i] is x_i = x_{i-1} * 2 + nums[i]. We are interested in x_i % 5. Using properties of modular arithmetic, we can write: x_i % 5 = ( (x_{i-1} * 2) + nums[i] ) % 5. This can be further broken down: x_i % 5 = ( (x_{i-1} % 5) * 2 + nums[i] ) % 5. Let rem_i = x_i % 5. The formula becomes rem_i = (rem_{i-1} * 2 + nums[i]) % 5. This means we can calculate the remainder for the current prefix using only the remainder from the previous prefix. The remainder will always be a small integer (0, 1, 2, 3, or 4), so we can use a standard integer variable to keep track of it, completely avoiding large number arithmetic and potential overflows. The algorithm iterates through the nums array, updating the remainder at each step using this formula. If the remainder becomes 0, the number is divisible by 5.
import java.util.ArrayList;import java.util.List; class Solution { public List<Boolean> prefixesDivBy5(int[] nums) { List<Boolean> answer = new ArrayList<>(); int remainder = 0; for (int bit : nums) { // Update remainder: remainder = (remainder * 2 + bit) % 5 // This can be written as a left shift for multiplication by 2 remainder = ((remainder << 1) | bit) % 5; answer.add(remainder == 0); } return answer; }}Complexity
Time
O(n). We iterate through the input array of length `n` exactly once. Each step inside the loop involves a few constant-time arithmetic operations.
Space
O(n). The space is dominated by the output list `answer`, which stores `n` boolean values. The auxiliary space used by the algorithm (for the `remainder` variable) is `O(1)`.
Trade-offs
Pros
Extremely efficient with linear time complexity.
Constant auxiliary space complexity.
Avoids all issues with large numbers and overflows.
Cons
Requires knowledge of modular arithmetic to come up with the solution.
Solutions
Solution
class Solution {public List<Boolean> prefixesDivBy5(int[] nums) { List<Boolean> ans = new ArrayList<>(); int x = 0; for (int v : nums) { x = (x << 1 | v) % 5; ans.add(x == 0); } return ans; }}Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.