2546. Apply Bitwise Operations to Make Strings Equal
Problem Description
You are given two binary strings s
and target
of the same length n
, both containing only '0's and '1's. Your goal is to transform string s
into string target
using a specific operation that can be applied any number of times.
The allowed operation works as follows:
- Select two different indices
i
andj
(where0 <= i, j < n
andi ≠ j
) - Simultaneously update both positions:
- Replace
s[i]
with the result ofs[i] OR s[j]
- Replace
s[j]
with the result ofs[i] XOR s[j]
- Replace
For example, starting with s = "0110"
:
- If you choose
i = 0
andj = 2
s[0]
becomes0 OR 1 = 1
s[2]
becomes0 XOR 1 = 1
- The resulting string is
s = "1110"
The operation behavior for all possible bit combinations:
(0, 0)
→(0, 0)
- no change when both bits are 0(0, 1)
→(1, 1)
- transforms to both 1s(1, 0)
→(1, 1)
- transforms to both 1s(1, 1)
→(1, 0)
- first stays 1, second becomes 0
The key insight is that having at least one '1' in the string acts as a "tool" that enables transformations. Once a string contains a '1', it will always contain at least one '1' after any operation. Conversely, if a string contains only '0's, no operation can introduce a '1'.
Therefore, transformation from s
to target
is possible if and only if both strings either contain at least one '1', or both contain only '0's.
Intuition
Let's carefully analyze what happens during each operation by examining all possible bit combinations:
- When we apply the operation on bits
(0, 0)
: They become(0 OR 0, 0 XOR 0) = (0, 0)
- no change - When we apply the operation on bits
(0, 1)
: They become(0 OR 1, 0 XOR 1) = (1, 1)
- When we apply the operation on bits
(1, 0)
: They become(1 OR 0, 1 XOR 0) = (1, 1)
- When we apply the operation on bits
(1, 1)
: They become(1 OR 1, 1 XOR 1) = (1, 0)
The crucial observation is that once you have at least one '1' in your string, you can never eliminate all '1's. Why? Because:
- Operating on
(0, 1)
or(1, 0)
produces two '1's - Operating on
(1, 1)
keeps one '1' and creates one '0' - Operating on
(0, 0)
doesn't create any '1's
This means '1' acts like a catalyst or tool - once present, it persists in the string (though it may move around or multiply).
Conversely, if your string contains only '0's, you can never create a '1' since operating on (0, 0)
yields (0, 0)
.
This leads to a fundamental invariant: the presence or absence of '1' in a string is preserved through all operations. A string with at least one '1' will always have at least one '1' after any sequence of operations, and a string with no '1's will never gain a '1'.
Therefore, we can only transform string s
into string target
if they belong to the same "class":
- Both contain at least one '1', OR
- Both contain only '0's
This explains why the solution is simply checking whether ("1" in s) == ("1" in target)
.
Solution Approach
Based on our understanding that the presence of '1' in a string is an invariant property, the solution becomes remarkably simple. We need to check if both strings belong to the same category - either both have at least one '1', or both have only '0's.
The implementation uses a direct comparison:
class Solution:
def makeStringsEqual(self, s: str, target: str) -> bool:
return ("1" in s) == ("1" in target)
Here's how this works:
-
Check for '1' in
s
: The expression"1" in s
returnsTrue
if strings
contains at least one '1', andFalse
if it contains only '0's. -
Check for '1' in
target
: Similarly,"1" in target
returnsTrue
if stringtarget
contains at least one '1', andFalse
otherwise. -
Compare the results: Using the equality operator
==
, we check if both expressions yield the same boolean value:- If both are
True
(both strings have '1's), the function returnsTrue
- If both are
False
(both strings have only '0's), the function returnsTrue
- If one is
True
and the other isFalse
, the function returnsFalse
- If both are
This elegant one-liner solution leverages Python's in
operator for substring checking, which internally performs a linear scan of the string. The time complexity is O(n)
where n
is the length of the strings, and the space complexity is O(1)
as we only use constant extra space for the boolean comparisons.
The beauty of this solution lies in recognizing that we don't need to simulate the actual transformations or find the specific sequence of operations. We only need to verify that both strings share the same fundamental property - the presence or absence of '1'.
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 a concrete example to illustrate why checking for the presence of '1' determines if transformation is possible.
Example 1: s = "0011", target = "1100"
First, let's check our condition:
"1" in s
=True
(s contains '1' at positions 2 and 3)"1" in target
=True
(target contains '1' at positions 0 and 1)- Since both are
True
, transformation is possible ✓
Let's verify by actually transforming s to target:
Starting with s = "0011"
-
Apply operation on indices i=2, j=0:
- s[2] = 1, s[0] = 0
- s[0] becomes 0 OR 1 = 1
- s[2] becomes 0 XOR 1 = 1
- Result: s = "1011"
-
Apply operation on indices i=3, j=1:
- s[3] = 1, s[1] = 0
- s[1] becomes 0 OR 1 = 1
- s[3] becomes 0 XOR 1 = 1
- Result: s = "1111"
-
Apply operation on indices i=2, j=3:
- s[2] = 1, s[3] = 1
- s[2] becomes 1 OR 1 = 1
- s[3] becomes 1 XOR 1 = 0
- Result: s = "1110"
-
Apply operation on indices i=2, j=3:
- s[2] = 1, s[3] = 0
- s[2] becomes 1 OR 0 = 1
- s[3] becomes 1 XOR 0 = 1
- Result: s = "1111"
-
Apply operation on indices i=3, j=2:
- s[3] = 1, s[2] = 1
- s[2] becomes 1 OR 1 = 1
- s[3] becomes 1 XOR 1 = 0
- Result: s = "1110"
-
Apply operation on indices i=2, j=3:
- s[2] = 1, s[3] = 0
- s[2] becomes 1 OR 0 = 1
- s[3] becomes 1 XOR 0 = 1
- Result: s = "1111"
-
Apply operation on indices i=3, j=2:
- s[3] = 1, s[2] = 1
- s[2] becomes 1 OR 1 = 1
- s[3] becomes 1 XOR 1 = 0
- Result: s = "1110"
-
Apply operation on indices i=1, j=2:
- s[1] = 1, s[2] = 1
- s[1] becomes 1 OR 1 = 1
- s[2] becomes 1 XOR 1 = 0
- Result: s = "1100" ✓
We successfully transformed s into target!
Example 2: s = "0000", target = "0101"
Check our condition:
"1" in s
=False
(s contains no '1's)"1" in target
=True
(target contains '1' at positions 1 and 3)- Since one is
False
and the other isTrue
, transformation is impossible ✗
Let's verify why it's impossible:
- Starting with s = "0000", any operation on indices i and j will be on bits (0,0)
- (0,0) transforms to (0 OR 0, 0 XOR 0) = (0,0)
- No matter how many operations we perform, we can never create a '1'
- Therefore, we can never reach target = "0101" which contains '1's
The key insight: once we know whether each string contains at least one '1', we immediately know if transformation is possible without needing to find the actual sequence of operations.
Solution Implementation
1class Solution:
2 def makeStringsEqual(self, s: str, target: str) -> bool:
3 """
4 Determines if string s can be transformed into target string.
5
6 The key insight: transformation is possible if and only if both strings
7 either contain at least one '1' or both contain no '1's.
8
9 Args:
10 s: The source string containing only '0' and '1'
11 target: The target string containing only '0' and '1'
12
13 Returns:
14 bool: True if s can be transformed into target, False otherwise
15 """
16 # Check if the presence of '1' is the same in both strings
17 # Both must have at least one '1', or both must have no '1's
18 has_one_in_s = "1" in s
19 has_one_in_target = "1" in target
20
21 return has_one_in_s == has_one_in_target
22
1class Solution {
2 /**
3 * Determines if string s can be transformed into target string through valid operations.
4 *
5 * The key insight: A string containing at least one '1' can be transformed into
6 * any other string that also contains at least one '1'. A string with all '0's
7 * can only match another string with all '0's.
8 *
9 * @param s The source binary string to transform
10 * @param target The target binary string to achieve
11 * @return true if s can be transformed into target, false otherwise
12 */
13 public boolean makeStringsEqual(String s, String target) {
14 // Check if both strings have the same "1" presence status
15 // If both have at least one '1', transformation is possible
16 // If both have no '1's (all zeros), they can match
17 // If one has '1' and other doesn't, transformation is impossible
18 boolean sourceHasOne = s.contains("1");
19 boolean targetHasOne = target.contains("1");
20
21 return sourceHasOne == targetHasOne;
22 }
23}
24
1class Solution {
2public:
3 bool makeStringsEqual(string s, string target) {
4 // Check if string s contains at least one '1'
5 bool sHasOne = count(s.begin(), s.end(), '1') > 0;
6
7 // Check if target string contains at least one '1'
8 bool targetHasOne = count(target.begin(), target.end(), '1') > 0;
9
10 // Two strings can be made equal if and only if:
11 // - Both have at least one '1', OR
12 // - Both have no '1's (all '0's)
13 // This is because operations require at least one '1' to transform bits
14 return sHasOne == targetHasOne;
15 }
16};
17
1/**
2 * Determines if string s can be transformed into target string through operations.
3 * The key insight is that any string containing '1' can be transformed into any other string containing '1',
4 * and a string with all '0's can only remain as all '0's.
5 *
6 * @param s - The source binary string
7 * @param target - The target binary string to transform into
8 * @returns true if transformation is possible, false otherwise
9 */
10function makeStringsEqual(s: string, target: string): boolean {
11 // Check if both strings either contain '1' or both don't contain '1'
12 // If both have at least one '1', transformation is possible
13 // If both have no '1's (all zeros), they must already be equal
14 return s.includes('1') === target.includes('1');
15}
16
Time and Space Complexity
The time complexity is O(n)
, where n
is the length of the string. This is because the in
operator needs to traverse through the string to check if the character "1" exists. In the worst case, it may need to scan the entire string (when "1" is at the end or doesn't exist at all). Since we perform this operation on both s
and target
, the total time complexity is O(n) + O(m)
, where n
and m
are the lengths of strings s
and target
respectively. However, if we assume both strings have the same or similar length n
, the overall time complexity simplifies to O(n)
.
The space complexity is O(1)
. The algorithm only uses a constant amount of extra space regardless of the input size. The in
operator performs the search without creating any additional data structures, and the comparison operation ==
also uses constant space. No auxiliary arrays, lists, or other data structures that scale with input size are created during execution.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Attempting to Simulate the Operations
A natural but inefficient approach is to try simulating the actual transformation operations to see if you can reach the target string. This leads to unnecessary complexity:
# WRONG APPROACH - Overly Complex
class Solution:
def makeStringsEqual(self, s: str, target: str) -> bool:
if s == target:
return True
s_list = list(s)
visited = {s}
queue = [s_list]
# BFS to try all possible operations
while queue:
current = queue.pop(0)
for i in range(len(current)):
for j in range(i + 1, len(current)):
new_state = current[:]
# Apply OR and XOR operations
or_result = str(int(current[i]) | int(current[j]))
xor_result = str(int(current[i]) ^ int(current[j]))
new_state[i] = or_result
new_state[j] = xor_result
new_string = ''.join(new_state)
if new_string == target:
return True
if new_string not in visited:
visited.add(new_string)
queue.append(new_state)
return False
Why it's wrong: This approach has exponential time complexity and will time out for larger inputs. It also misses the fundamental insight that makes the problem simple.
2. Misunderstanding the Operation's Effect on Bit Count
Some might think that the total number of '1's in the string is preserved or follows a specific pattern:
# WRONG APPROACH - Incorrect Assumption
class Solution:
def makeStringsEqual(self, s: str, target: str) -> bool:
# Incorrectly assuming the count of '1's matters
return s.count('1') == target.count('1')
Why it's wrong: The operation can change the count of '1's. For example:
"10"
can become"11"
(increasing '1' count)"11"
can become"10"
(decreasing '1' count)
3. Overthinking Edge Cases
Some might add unnecessary checks for edge cases that are already handled by the main logic:
# UNNECESSARILY COMPLEX
class Solution:
def makeStringsEqual(self, s: str, target: str) -> bool:
# These checks are redundant
if s == target:
return True
if len(s) != len(target):
return False
if s == "0" * len(s) and target != "0" * len(s):
return False
if s != "0" * len(s) and target == "0" * len(s):
return False
return ("1" in s) == ("1" in target)
Why it's wrong: The simple check ("1" in s) == ("1" in target)
already handles all these cases correctly. Adding extra conditions only makes the code harder to read and maintain.
Correct Solution
The key is recognizing the invariant: once a string has at least one '1', it will always have at least one '1' after any operation. The solution is elegantly simple:
class Solution:
def makeStringsEqual(self, s: str, target: str) -> bool:
return ("1" in s) == ("1" in target)
This solution is both correct and optimal with O(n) time complexity and O(1) space complexity.
Which data structure is used to implement priority queue?
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!