1784. Check if Binary String Has at Most One Segment of Ones
Problem Description
You are given a binary string s
that contains only '0's and '1's and has no leading zeros (meaning it doesn't start with '0').
Your task is to determine if the string contains at most one contiguous segment of ones. A contiguous segment of ones means consecutive '1's that appear together without any '0's in between.
Return true
if there is at most one such segment, and false
otherwise.
For example:
"1110000"
has exactly one segment of ones at the beginning → returntrue
"110111"
has two segments of ones (one at the beginning "11" and another "111" after the '0') → returnfalse
"1"
has exactly one segment → returntrue
"111"
has exactly one segment → returntrue
The key insight is that since the string has no leading zeros, it must start with '1'. If we ever encounter the pattern "01"
in the string, it means there's a '1' appearing after a '0', which indicates a second segment of ones has started. Therefore, checking whether "01"
exists in the string is sufficient to solve this problem.
Intuition
Since the string has no leading zeros, we know it must start with '1'. This is a crucial observation.
Let's think about what happens when we have multiple segments of ones. If we have more than one segment, the string would look something like: "111...000...111..."
. To go from the first segment of ones to the second segment, we must:
- First encounter a '0' (ending the first segment)
- Then encounter a '1' (starting the second segment)
This creates the pattern "01"
somewhere in the string.
On the other hand, if we have at most one segment of ones, the string can only be in one of these forms:
- Just ones:
"1111..."
- Ones followed by zeros:
"1111...0000..."
In both these valid cases, we never have a '1' coming after a '0', so the pattern "01"
never appears.
The beauty of this observation is that we don't need to count segments or track state as we traverse the string. We can simply check if the substring "01"
exists anywhere in the string. If it does, we have more than one segment (return false
). If it doesn't, we have at most one segment (return true
).
This reduces a seemingly complex problem of counting contiguous segments to a simple substring search, making the solution elegant and efficient with just one line: return '01' not in s
.
Solution Approach
The implementation is remarkably simple based on our observation that multiple segments of ones will always create the pattern "01"
in the string.
Algorithm Steps:
- Check if the substring
"01"
exists in the given strings
- If
"01"
is found, returnfalse
(more than one segment exists) - If
"01"
is not found, returntrue
(at most one segment exists)
Implementation Details:
The Python solution uses the in
operator for substring checking:
return '01' not in s
This one-liner works because:
- Python's
in
operator efficiently searches for the substring"01"
withins
- The expression
'01' not in s
evaluates toTrue
when"01"
is absent (valid case with at most one segment) - It evaluates to
False
when"01"
is present (invalid case with multiple segments)
Why This Works:
Since s
doesn't have leading zeros, it must start with '1'. The only way to have multiple segments of ones is to have the pattern:
"1...1"
(first segment)- followed by
"0...0"
(gap between segments) - followed by
"1...1"
(second segment)
This transition from zeros back to ones creates the "01"
pattern. Therefore:
- Strings like
"1110000"
are valid (no"01"
pattern) - Strings like
"1101"
or"110111"
are invalid (contain"01"
pattern)
Time Complexity: O(n) where n is the length of the string, as substring search requires scanning the string.
Space Complexity: O(1) as we only use constant extra space for the substring pattern check.
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 approach with a concrete example: s = "1100111"
Step 1: Identify what we're looking for We need to check if there's at most one contiguous segment of ones. Since the string has no leading zeros, it must start with '1'.
Step 2: Apply our key observation
We look for the pattern "01"
in the string. Let's scan through "1100111"
:
- Position 0-1:
"11"
- no match - Position 1-2:
"10"
- no match - Position 2-3:
"00"
- no match - Position 3-4:
"01"
- MATCH FOUND!
Step 3: Interpret the result
Since we found "01"
at position 3-4, this indicates a '1' appears after a '0'. This means:
- The first segment of ones:
"11"
(positions 0-1) - Then zeros:
"00"
(positions 2-3) - Then another segment of ones:
"111"
(positions 4-6)
We have two segments of ones, so the answer is false
.
Verification:
Let's verify with a valid example: s = "1110000"
- Scanning for
"01"
: No matter where we look, we only see patterns like"11"
,"10"
, or"00"
- Since
"01"
is not found, we have at most one segment - Indeed, there's only one segment of ones at the beginning:
"111"
- The answer is
true
Code execution:
# For s = "1100111" return '01' not in s # '01' is in "1100111", so returns False # For s = "1110000" return '01' not in s # '01' is not in "1110000", so returns True
Solution Implementation
1class Solution:
2 def checkOnesSegment(self, s: str) -> bool:
3 """
4 Check if all '1's in the binary string form exactly one contiguous segment.
5
6 The logic: If the pattern '01' exists in the string, it means there's a '0'
7 followed by a '1', indicating that '1's appear again after being interrupted
8 by '0's, which means multiple segments exist.
9
10 Args:
11 s: A binary string containing only '0's and '1's
12
13 Returns:
14 True if all '1's form a single contiguous segment, False otherwise
15 """
16 # Check if the substring '01' exists in the string
17 # If '01' is not found, all '1's are contiguous (return True)
18 # If '01' is found, there are multiple segments of '1's (return False)
19 return '01' not in s
20
1class Solution {
2 /**
3 * Checks if all '1's in the binary string form a single contiguous segment.
4 *
5 * The logic: If there are multiple segments of '1's, there must be at least
6 * one occurrence of "01" pattern (transitioning from '0' back to '1').
7 * A single segment means we never go from '0' to '1' after the initial segment.
8 *
9 * @param s - A binary string containing only '0's and '1's
10 * @return true if all '1's form a single contiguous segment, false otherwise
11 */
12 public boolean checkOnesSegment(String s) {
13 // Check if the string does NOT contain the pattern "01"
14 // If "01" is absent, all '1's must be in a single contiguous segment
15 return !s.contains("01");
16 }
17}
18
1class Solution {
2public:
3 /**
4 * Check if all '1's in the binary string form a single contiguous segment.
5 *
6 * The string contains a single segment of '1's if there are no '0's followed by '1's.
7 * If pattern "01" exists, it means '1's are split into multiple segments.
8 *
9 * @param s - Binary string containing only '0's and '1's
10 * @return true if all '1's form a single contiguous segment, false otherwise
11 */
12 bool checkOnesSegment(string s) {
13 // Check if pattern "01" exists in the string
14 // If "01" is not found (returns string::npos), all '1's are contiguous
15 return s.find("01") == string::npos;
16 }
17};
18
1/**
2 * Checks if all '1's in the binary string form a single contiguous segment.
3 * A contiguous segment means all '1's appear together without any '0's in between.
4 *
5 * @param s - A binary string containing only '0's and '1's
6 * @returns true if all '1's form a single contiguous segment, false otherwise
7 */
8function checkOnesSegment(s: string): boolean {
9 // Store the previous character for comparison
10 let previousChar: string = s[0];
11
12 // Iterate through each character in the string
13 for (const currentChar of s) {
14 // If we transition from '0' to '1', it means we found a second segment of '1's
15 // This violates the single segment requirement
16 if (previousChar !== currentChar && currentChar === '1') {
17 return false;
18 }
19
20 // Update the previous character for the next iteration
21 previousChar = currentChar;
22 }
23
24 // If we complete the loop without finding multiple segments, return true
25 return true;
26}
27
Time and Space Complexity
The time complexity is O(n)
, where n
is the length of the string s
. This is because the in
operator in Python needs to traverse through the string to check if the substring '01'
exists. In the worst case, it examines all characters in the string.
The space complexity is O(1)
. The algorithm only uses a constant amount of extra space regardless of the input size. The substring '01'
being searched for is a fixed constant, and no additional data structures that scale with input size are created.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
Pitfall 1: Misunderstanding Edge Cases
The Mistake: Developers might overthink edge cases and add unnecessary complexity, such as:
- Explicitly checking for empty strings
- Handling strings with only '0's or only '1's separately
- Adding special logic for single-character strings
# Overcomplicated approach - unnecessary!
def checkOnesSegment(self, s: str) -> bool:
if not s or len(s) == 1: # Unnecessary edge case handling
return True
if '1' not in s: # Unnecessary check
return True
return '01' not in s
Why It's Wrong:
The simple '01' not in s
check already handles all these cases correctly:
- Empty string:
'01' not in ''
returnsTrue
(valid) - Single character:
'01' not in '1'
or'01' not in '0'
both returnTrue
(valid) - All zeros:
'01' not in '0000'
returnsTrue
(valid - zero segments is "at most one")
The Fix: Trust the simplicity of the solution. The one-liner handles all edge cases naturally.
Pitfall 2: Incorrect Pattern Matching
The Mistake: Some might try to check for the wrong pattern or use complex regex:
# Wrong approach - checking for '10' instead
def checkOnesSegment(self, s: str) -> bool:
return '10' not in s # This doesn't catch all cases!
Why It's Wrong:
Checking for '10'
pattern misses cases like "111011"
. The '10'
pattern only indicates the end of a segment of ones, not the start of a new one. The string "1110000"
contains '10'
but is still valid.
The Fix:
Always check for '01'
pattern, which specifically indicates a '1' appearing after a '0', marking the start of a new segment.
Pitfall 3: Manual Iteration with State Tracking
The Mistake: Implementing complex state machines or flag-based solutions:
# Overly complex manual approach
def checkOnesSegment(self, s: str) -> bool:
seen_zero = False
for i in range(len(s)):
if s[i] == '0':
seen_zero = True
elif s[i] == '1' and seen_zero:
return False # Found a '1' after seeing a '0'
return True
Why It's Problematic: While this works, it's:
- More code to write and maintain
- Higher chance of bugs (off-by-one errors, incorrect flag handling)
- Less readable than the simple substring check
- Potentially slower due to Python loop overhead
The Fix: Use Python's built-in substring search which is optimized at the C level and more concise:
return '01' not in s
Which type of traversal does breadth first search do?
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!