1437. Check If All 1's Are at Least Length K Places Away
Problem Description
You are given a binary array nums
(containing only 0s and 1s) and an integer k
. Your task is to determine whether all the 1s in the array are separated by at least k
distance from each other.
In other words, between any two consecutive 1s in the array, there must be at least k
zeros. If this condition is satisfied for all pairs of consecutive 1s, return true
. Otherwise, return false
.
For example:
-
If
nums = [1,0,0,0,1,0,0,1]
andk = 2
, the function should returntrue
because:- Between the first 1 (index 0) and second 1 (index 4), there are 3 zeros
- Between the second 1 (index 4) and third 1 (index 7), there are 2 zeros
- Both gaps have at least
k = 2
zeros
-
If
nums = [1,0,0,1,0,1]
andk = 2
, the function should returnfalse
because:- Between the second 1 (index 3) and third 1 (index 5), there is only 1 zero
- This is less than the required
k = 2
zeros
The solution tracks the position of the previous 1 and checks if the distance between consecutive 1s meets the requirement.
Intuition
The key insight is that we only need to track consecutive 1s in the array and check the distance between them. We don't need to store all positions of 1s or look ahead - we can solve this in a single pass.
Think of it this way: as we traverse the array from left to right, whenever we encounter a 1, we need to know where the previous 1 was located. The distance between these two 1s tells us how many elements are between them. Since we want at least k
zeros between any two 1s, the actual distance should be at least k + 1
(accounting for the positions of the 1s themselves).
For example, if we have [1, 0, 0, 1]
, the indices of 1s are 0 and 3. The distance is 3 - 0 = 3
, but the number of zeros between them is 3 - 0 - 1 = 2
.
This leads to a simple approach:
- Keep track of the index of the last seen 1
- When we find a new 1, calculate how many positions are between it and the previous 1
- If the number of zeros (distance - 1) is less than
k
, we immediately know the condition is violated - Update our "last seen 1" position and continue
We initialize the "last seen 1" position to negative infinity (-inf
) to handle the edge case where the first element is a 1. This ensures that the first 1 we encounter won't falsely trigger a violation since i - (-inf) - 1
will always be greater than any finite k
.
Solution Approach
The implementation uses a single-pass traversal with a tracking variable to monitor the position of the last encountered 1.
Variables used:
j
: Stores the index of the most recently seen 1, initialized to-inf
to handle the first 1 gracefullyi
: Current index while iterating through the arrayx
: Current element value at indexi
Algorithm steps:
-
Initialize the tracker: Set
j = -inf
to represent that no 1 has been seen yet. Using negative infinity ensures that when we find the first 1, the distance calculationi - j - 1
will always be large enough to pass the check. -
Iterate through the array: Use
enumerate(nums)
to get both the indexi
and valuex
of each element. -
Check each 1: When we encounter a 1 (when
x
is truthy):- Calculate the number of zeros between current position
i
and previous 1 at positionj
using the formula:i - j - 1
- If this distance is less than
k
, immediately returnFalse
as the constraint is violated - Update
j = i
to mark this as the new "last seen 1" position
- Calculate the number of zeros between current position
-
Return result: If we complete the iteration without finding any violation, return
True
.
Example walkthrough:
For nums = [1,0,0,0,1,0,0,1]
and k = 2
:
- Start with
j = -inf
- Index 0: Found 1, distance =
0 - (-inf) - 1
> 2 ✓, updatej = 0
- Index 4: Found 1, distance =
4 - 0 - 1 = 3
≥ 2 ✓, updatej = 4
- Index 7: Found 1, distance =
7 - 4 - 1 = 2
≥ 2 ✓, updatej = 7
- Return
True
The time complexity is O(n)
where n
is the length of the array, as we traverse it once. The space complexity is O(1)
as we only use a constant amount of extra space.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with nums = [1,0,0,1,0,1]
and k = 2
:
Initial State:
j = -inf
(no previous 1 seen yet)- We need at least 2 zeros between any two 1s
Step-by-step traversal:
Index 0: nums[0] = 1
- This is a 1, so we check the distance from the previous 1
- Distance calculation:
0 - (-inf) - 1
= very large number - This is definitely ≥ 2, so we're good
- Update:
j = 0
(mark this 1's position)
Index 1: nums[1] = 0
- This is a 0, so we skip it
Index 2: nums[2] = 0
- This is a 0, so we skip it
Index 3: nums[3] = 1
- This is a 1, so we check the distance from the previous 1 at index 0
- Number of zeros between them:
3 - 0 - 1 = 2
- This equals our requirement
k = 2
, so we're good - Update:
j = 3
(mark this new 1's position)
Index 4: nums[4] = 0
- This is a 0, so we skip it
Index 5: nums[5] = 1
- This is a 1, so we check the distance from the previous 1 at index 3
- Number of zeros between them:
5 - 3 - 1 = 1
- This is less than our requirement
k = 2
(we need at least 2 zeros but only have 1) - Return
False
immediately
The algorithm correctly identifies that the last two 1s (at indices 3 and 5) only have 1 zero between them, violating the requirement of having at least 2 zeros between consecutive 1s.
Solution Implementation
1class Solution:
2 def kLengthApart(self, nums: List[int], k: int) -> bool:
3 """
4 Check if all 1s in the array are at least k distance apart.
5
6 Args:
7 nums: Binary array containing only 0s and 1s
8 k: Minimum required distance between consecutive 1s
9
10 Returns:
11 True if all 1s are at least k distance apart, False otherwise
12 """
13 # Initialize the position of the last seen 1 to negative infinity
14 # This ensures the first 1 doesn't fail the distance check
15 last_one_position = float('-inf')
16
17 # Iterate through the array with indices
18 for current_index, value in enumerate(nums):
19 # Check if current element is 1
20 if value == 1:
21 # Calculate distance between current 1 and previous 1
22 # Subtract 1 because we count only the elements between them
23 distance_between_ones = current_index - last_one_position - 1
24
25 # If distance is less than k, the condition is violated
26 if distance_between_ones < k:
27 return False
28
29 # Update the position of the last seen 1
30 last_one_position = current_index
31
32 # All 1s satisfy the distance requirement
33 return True
34
1class Solution {
2 public boolean kLengthApart(int[] nums, int k) {
3 // Initialize the position of the previous 1
4 // Set to -(k+1) to handle the case when the first element is 1
5 // This ensures the distance check passes for the first 1
6 int previousOneIndex = -(k + 1);
7
8 // Iterate through the array to find all 1s
9 for (int currentIndex = 0; currentIndex < nums.length; currentIndex++) {
10 // Check if current element is 1
11 if (nums[currentIndex] == 1) {
12 // Calculate distance between current 1 and previous 1
13 // Distance = currentIndex - previousOneIndex - 1 (excluding both endpoints)
14 if (currentIndex - previousOneIndex - 1 < k) {
15 // Distance is less than k, so return false
16 return false;
17 }
18 // Update the position of the previous 1
19 previousOneIndex = currentIndex;
20 }
21 }
22
23 // All 1s are at least k distance apart
24 return true;
25 }
26}
27
1class Solution {
2public:
3 bool kLengthApart(vector<int>& nums, int k) {
4 // Initialize the index of the previous '1' to a value that ensures
5 // the first '1' encountered will always satisfy the distance requirement
6 // Setting it to -(k + 1) means the first '1' at index i will have
7 // distance i - (-(k + 1)) - 1 = i + k, which is always >= k for i >= 0
8 int prevOneIndex = -(k + 1);
9
10 // Iterate through each element in the array
11 for (int i = 0; i < nums.size(); ++i) {
12 // Check if current element is 1
13 if (nums[i] == 1) {
14 // Calculate the distance between current '1' and previous '1'
15 // The actual distance is (i - prevOneIndex - 1) which represents
16 // the number of elements between the two 1's (excluding the 1's themselves)
17 if (i - prevOneIndex - 1 < k) {
18 // If distance is less than k, the condition is violated
19 return false;
20 }
21 // Update the index of the most recent '1'
22 prevOneIndex = i;
23 }
24 }
25
26 // All pairs of 1's satisfy the distance requirement
27 return true;
28 }
29};
30
1/**
2 * Checks if all 1s in the binary array are at least k distance apart
3 * @param nums - Binary array containing only 0s and 1s
4 * @param k - Minimum required distance between consecutive 1s
5 * @returns true if all 1s are at least k distance apart, false otherwise
6 */
7function kLengthApart(nums: number[], k: number): boolean {
8 // Initialize the position of the previous 1 found
9 // Set to -(k+1) to handle the first 1 correctly (ensures first 1 always passes the check)
10 let previousOneIndex: number = -(k + 1);
11
12 // Iterate through each element in the array
13 for (let currentIndex: number = 0; currentIndex < nums.length; currentIndex++) {
14 // Check if current element is 1
15 if (nums[currentIndex] === 1) {
16 // Calculate distance between current 1 and previous 1
17 // Distance is (currentIndex - previousOneIndex - 1) to exclude the positions of the 1s themselves
18 if (currentIndex - previousOneIndex - 1 < k) {
19 // Distance is less than required, return false
20 return false;
21 }
22 // Update the position of the most recent 1
23 previousOneIndex = currentIndex;
24 }
25 }
26
27 // All 1s are at least k distance apart
28 return true;
29}
30
Time and Space Complexity
Time Complexity: O(n)
, where n
is the length of the input array nums
. The algorithm iterates through the array exactly once using a single for loop with enumerate()
. Each operation inside the loop (checking if x
is 1, calculating the distance i - j - 1
, comparison with k
, and updating j
) takes constant time O(1)
. Therefore, the overall time complexity is linear.
Space Complexity: O(1)
. The algorithm uses only a constant amount of extra space regardless of the input size. The variables used are:
j
: stores the index of the previous 1 (initialized to negative infinity)i
: the current index from enumeratex
: the current value from enumerate
These variables don't grow with the input size, making the space complexity constant.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Distance Calculation
A common mistake is calculating the distance incorrectly by either including the positions of the 1s themselves or using the wrong formula.
Incorrect approaches:
- Using
current_index - last_one_position
instead ofcurrent_index - last_one_position - 1
- Counting the total elements between 1s including the 1s themselves
Why it's wrong: The problem asks for the number of zeros between consecutive 1s, not the total distance. If 1s are at indices 2 and 5, the positions between them are 3 and 4 (two zeros), not three elements.
Solution: Always use the formula current_index - last_one_position - 1
to get the exact count of elements between two positions.
2. Improper Initialization of the Last Position Tracker
Initializing last_one_position
to 0 or -1 instead of negative infinity can cause issues with the first 1 in the array.
Problem scenario:
# Wrong initialization last_one_position = -1 # If first 1 is at index 0 and k = 2 # Distance = 0 - (-1) - 1 = -1 < 2 (incorrectly fails!)
Solution: Initialize to float('-inf')
to ensure the first 1 always passes the distance check, as it has no preceding 1 to compare against.
3. Off-by-One Error in Distance Validation
Some might check distance_between_ones <= k
instead of distance_between_ones < k
.
Why it matters: The problem requires "at least k" zeros between 1s. If there are exactly k zeros, that satisfies the requirement.
Correct validation:
if distance_between_ones < k: # Correct: fails only if less than k return False
4. Forgetting to Update the Last Position
After checking the distance, failing to update last_one_position = current_index
will cause all subsequent distance calculations to be wrong.
Impact: The algorithm would always compare new 1s against the first 1 found, giving incorrect results for arrays with more than two 1s.
Solution: Always update the tracker after validating the distance:
if value == 1: if distance_between_ones < k: return False last_one_position = current_index # Don't forget this!
Given a sorted array of integers and an integer called target, find the element that
equals to the target and return its index. Select the correct code that fills the
___
in the given code snippet.
1def binary_search(arr, target):
2 left, right = 0, len(arr) - 1
3 while left ___ right:
4 mid = (left + right) // 2
5 if arr[mid] == target:
6 return mid
7 if arr[mid] < target:
8 ___ = mid + 1
9 else:
10 ___ = mid - 1
11 return -1
12
1public static int binarySearch(int[] arr, int target) {
2 int left = 0;
3 int right = arr.length - 1;
4
5 while (left ___ right) {
6 int mid = left + (right - left) / 2;
7 if (arr[mid] == target) return mid;
8 if (arr[mid] < target) {
9 ___ = mid + 1;
10 } else {
11 ___ = mid - 1;
12 }
13 }
14 return -1;
15}
16
1function binarySearch(arr, target) {
2 let left = 0;
3 let right = arr.length - 1;
4
5 while (left ___ right) {
6 let mid = left + Math.trunc((right - left) / 2);
7 if (arr[mid] == target) return mid;
8 if (arr[mid] < target) {
9 ___ = mid + 1;
10 } else {
11 ___ = mid - 1;
12 }
13 }
14 return -1;
15}
16
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!