You are given a 0-indexed string s
of even length n
. The string consists of exactly n / 2
opening brackets '['
and n / 2
closing brackets ']'
.
A string is called balanced if and only if:
AB
, where both A
and B
are balanced strings, or[C]
, where C
is a balanced string.You may swap the brackets at any two indices any number of times.
Return the minimum number of swaps to make s
balanced.
Example 1:
Input: s = "][][" Output: 1 Explanation: You can make the string balanced by swapping index 0 with index 3. The resulting string is "[[]]".
Example 2:
Input: s = "]]][[[" Output: 2 Explanation: You can do the following to make the string balanced: - Swap index 0 with index 4. s = "[]][][". - Swap index 1 with index 5. s = "[[][]]". The resulting string is "[[][]]".
Example 3:
Input: s = "[]" Output: 0 Explanation: The string is already balanced.
Constraints:
n == s.length
2 <= n <= 106
n
is even.s[i]
is either '['
or ']'
.'['
equals n / 2
, and the number of closing brackets ']'
equals n / 2
.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force approach is like trying every possible arrangement of the string, swapping characters in all sorts of combinations. We'll check each of these arrangements to see if it's balanced and keep track of the best result.
Here's how the algorithm would work step-by-step:
def minimum_swaps_brute_force(unbalanced_string):
minimum_number_of_swaps = float('inf')
string_length = len(unbalanced_string)
def is_balanced(input_string):
balance = 0
for character in input_string:
if character == '[':
balance += 1
else:
balance -= 1
if balance < 0:
return False
return balance == 0
def solve(current_string, swap_count):
nonlocal minimum_number_of_swaps
if is_balanced(current_string):
minimum_number_of_swaps = min(
minimum_number_of_swaps, swap_count)
return
# Optimization:
# Stop searching when swaps exceeds best known
if swap_count >= minimum_number_of_swaps:
return
for first_index in range(string_length):
for second_index in range(
first_index + 1, string_length):
string_list = list(current_string)
# Create a new string arrangement by swapping
string_list[first_index], string_list[second_index] = \
string_list[second_index], string_list[first_index]
new_string = "".join(string_list)
# Recursively check this arrangement
solve(new_string, swap_count + 1)
# Begin searching with original string
solve(unbalanced_string, 0)
# If no solution, return -1
if minimum_number_of_swaps == float('inf'):
return -1
return minimum_number_of_swaps
The key insight is to count how many brackets are out of place. We then realize that we can fix two misplaced brackets with a single swap. Therefore we determine the answer by dividing the number of misplaced brackets by two.
Here's how the algorithm would work step-by-step:
def minimum_swaps(brackets_string):
mismatched_closing_brackets = 0
opening_bracket_count = 0
for bracket in brackets_string:
if bracket == '[':
opening_bracket_count += 1
else:
# Count misplaced closing brackets
if opening_bracket_count > 0:
opening_bracket_count -= 1
else:
mismatched_closing_brackets += 1
# Each swap corrects two misplaced brackets
minimum_number_of_swaps = (mismatched_closing_brackets + 1) // 2
return minimum_number_of_swaps
Case | How to Handle |
---|---|
Null or empty input string | Return 0 because an empty string is already balanced or throw an IllegalArgumentException depending on problem specifics. |
String with odd length | Return -1 because a balanced string requires equal number of '[' and ']' characters and an odd length cannot satisfy this condition. |
String with only '[' or only ']' characters | Calculate the number of swaps needed based on string length / 2, as that's how many characters must be swapped. |
String is already balanced | Return 0 because no swaps are needed. |
Maximum-sized input string to assess scalability. | The solution should use an efficient algorithm (e.g., O(n) time complexity) to avoid exceeding time limit for large inputs. |
String starts with all ']' characters followed by all '[' characters | This represents the worst-case scenario needing maximum swaps; verify correctness in this case. |
String contains a prefix where the number of ']' exceeds the number of '[' characters | The algorithm should identify and correct these imbalances, incrementing the swap count accordingly. |
String contains many localized imbalances (e.g., '][][][') | The solution must handle multiple local imbalances efficiently to determine the minimum swaps required. |