30 Days of LeetCode: Day 4 - Valid Parentheses String Locking Pattern


When I first encountered the "Check if a Parentheses String Can Be Valid" challenge, I fell into a common trap that many developers encounter: trying to solve for creation when the problem only asked for validation. This experience taught me a valuable lesson about problem interpretation and efficient solution design.
The Challenge
Given a string of parentheses and a corresponding "locked" pattern (where '1' means the character is locked and '0' means it can be changed), determine if it's possible to create a valid parentheses string.
Initial Approach
My first attempt focused on physically transforming the string into valid parentheses:
var canBeValid = function(s, locked) {
if (s.length % 2 !== 0) return false;
let arr = s.split('');
for (let i = 0; i < arr.length; i += 2) {
if (locked[i] === '0' && locked[i+1] === '0') {
arr[i] = '(';
arr[i+1] = ')';
}
}
// Check validity...
};
This approach had several flaws:
Only looked at adjacent pairs
Tried to physically create the valid string
Assumed pairs had to be adjacent
The Breakthrough
The "aha" moment came when I realized: We don't need to create a valid string - we just need to verify that one is possible.
This led to a fundamentally different approach:
var canBeValid = function(s, locked) {
if (s.length % 2 !== 0) return false;
// Check if we have enough potential opening parentheses
let opens = 0;
for (let i = 0; i < s.length; i++) {
if (s[i] === '(' || locked[i] === '0') opens++;
else opens--;
if (opens < 0) return false;
}
// Check if we have enough potential closing parentheses
let closes = 0;
for (let i = s.length - 1; i >= 0; i--) {
if (s[i] === ')' || locked[i] === '0') closes++;
else closes--;
if (closes < 0) return false;
}
return true;
};
Learning Impact
This challenge taught me several crucial lessons:
Question Interpretation: Always read what the problem is actually asking for. I was asked to check if a valid string was possible, not to create one.
Efficiency Through Simplification: The validation approach not only runs faster but uses less memory since it doesn't create any new strings or arrays.
Counter vs Creation: Sometimes counting potential outcomes is more powerful than trying to create actual solutions. This is a pattern I've now recognized in many other problems.
Problem Reduction: By reducing the problem to "do we have enough flexibility?" instead of "how do we make it valid?", the solution became much clearer.
This experience changed how I approach similar problems. Now, before diving into implementation, I ask myself: "Am I being asked to create a solution, or just verify if one exists?" The difference in approach can be dramatic.
The lesson extends beyond coding challenges. In real-world development, we often over complicate solutions by trying to solve more than what's actually needed. Sometimes, validation is enough - we don't always need to handle the transformation.
Subscribe to my newsletter
Read articles from Raphael Smith directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Raphael Smith
Raphael Smith
Just a developer who wants to talk web programming like I'm sitting in a barbershop in East Atlanta. "Tech is the new trap!"