Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Binary Prefix Divisible By 5 in Python
Given an array A of 0s and 1s, we need to determine which binary prefixes are divisible by 5. For each index i, we interpret the subarray from A[0] to A[i] as a binary number and check if it's divisible by 5.
For example, if the input is [0,1,1,1,1,1], the binary prefixes are:
- 0 (binary) = 0 (decimal) ? divisible by 5
- 01 (binary) = 1 (decimal) ? not divisible by 5
- 011 (binary) = 3 (decimal) ? not divisible by 5
- 0111 (binary) = 7 (decimal) ? not divisible by 5
- 01111 (binary) = 15 (decimal) ? divisible by 5
- 011111 (binary) = 31 (decimal) ? not divisible by 5
Approach 1: Efficient Modular Arithmetic
Instead of converting entire binary strings to decimal, we can use modular arithmetic. For each new bit, we update the running remainder when divided by 5 ?
def prefixesDivBy5(A):
result = []
remainder = 0
for bit in A:
# Update remainder: (remainder * 2 + bit) % 5
remainder = (remainder * 2 + bit) % 5
result.append(remainder == 0)
return result
# Test with example
A = [0, 1, 1, 1, 1, 1]
print(prefixesDivBy5(A))
[True, False, False, False, True, False]
How It Works
The key insight is that when we append a new bit to a binary number, the decimal value becomes (previous_value * 2 + new_bit). Using modular arithmetic:
# Example walkthrough
A = [0, 1, 1, 1, 1, 1]
remainder = 0
for i, bit in enumerate(A):
remainder = (remainder * 2 + bit) % 5
binary_prefix = ''.join(map(str, A[:i+1]))
decimal_value = int(binary_prefix, 2)
print(f"Prefix: {binary_prefix}, Decimal: {decimal_value}, Remainder: {remainder}, Divisible by 5: {remainder == 0}")
Prefix: 0, Decimal: 0, Remainder: 0, Divisible by 5: True Prefix: 01, Decimal: 1, Remainder: 1, Divisible by 5: False Prefix: 011, Decimal: 3, Remainder: 3, Divisible by 5: False Prefix: 0111, Decimal: 7, Remainder: 2, Divisible by 5: False Prefix: 01111, Decimal: 15, Remainder: 0, Divisible by 5: True Prefix: 011111, Decimal: 31, Remainder: 1, Divisible by 5: False
Approach 2: Direct Binary to Decimal Conversion
This approach converts each prefix to decimal and checks divisibility directly ?
def prefixesDivBy5_direct(A):
result = []
for i in range(len(A)):
# Get prefix from 0 to i
prefix = A[:i+1]
# Convert binary list to decimal
binary_str = ''.join(map(str, prefix))
decimal_value = int(binary_str, 2)
# Check if divisible by 5
result.append(decimal_value % 5 == 0)
return result
# Test with example
A = [0, 1, 1, 1, 1, 1]
print(prefixesDivBy5_direct(A))
[True, False, False, False, True, False]
Comparison
| Approach | Time Complexity | Space Complexity | Best For |
|---|---|---|---|
| Modular Arithmetic | O(n) | O(1) | Large arrays, efficient |
| Direct Conversion | O(n²) | O(n) | Understanding the problem |
Complete Solution with Class
class Solution:
def prefixesDivBy5(self, A):
result = []
remainder = 0
for bit in A:
remainder = (remainder * 2 + bit) % 5
result.append(remainder == 0)
return result
# Test the solution
solution = Solution()
test_cases = [
[0, 1, 1, 1, 1, 1],
[1, 1, 1],
[0, 1, 1, 0, 1]
]
for i, test in enumerate(test_cases):
result = solution.prefixesDivBy5(test)
print(f"Test {i+1}: {test} ? {result}")
Test 1: [0, 1, 1, 1, 1, 1] ? [True, False, False, False, True, False] Test 2: [1, 1, 1] ? [False, False, False] Test 3: [0, 1, 1, 0, 1] ? [True, False, False, True, False]
Conclusion
The modular arithmetic approach is optimal with O(n) time complexity and constant space. It efficiently tracks remainders without converting entire binary strings, making it suitable for large input arrays.
