First 15 minutes spent creating this Pseudocode:
Used the next 15 minutes to write this
Reflections
I finished with 2.5 minutes to go and got a function that worked first try, which I feel really good about! I think that spending 15 minutes to calmly work through edge cases worked really really well. Normally I just start coding as think, and maybe this is more efficient in some ways —
I guess to be fair, I DID code some things as I went, which I think is a good idea.
Something I didn’t do is have a section in my leetcode that was actionable notes, which might have helped with organization.
I also think I did a good job of going with an available working solution instead of an eloquent solution. 30 minutes really isn’t much time.
Claude
I asked Claude how I could have improved things, and he suggested using Sets instead of strings, and using Maps instead of normal js objects. Those make sense and would be a great way to flex my understanding of these data sets (dishonestly, as I don’t use these too often at the moment), but don’t really seem that important.
What I did like was checking for even or odd numbered inputs for early returns.
He also suggested checking for closing brackets first…dont’ totally understand this approach:
This switch statement suggestion is really interesting though:
Update
Paul Winkler, a colleague of mine, noticed that I failed to handle an edge case that I did notice in my pseudocode, which was:
Although the initial code passes leetcode’s submission tests, I don’t seem to be handling this. Leetcode is pretty stringent, so I wondered how this could be. I checked the submission criteria:
1. Open brackets must be closed by the same type of brackets.
2. Open brackets must be closed in the correct order.
3. Every close bracket has a corresponding open bracket of the same type.
And found that a case of }
would definitely fail criteria item #3, but maybe this is not a case that is run by leetcode. In fact, I think it must not be a case run by leetcode, since if it was I think this case might get an Out of bounds
error on the second line here:
But then I went and tested this case ]
as well as []]
just to be safe, and my function evaluated these as false
after all. So, edge case handled…just not intentionally. My ego is a little bruised, since it seems I got a bit lucky, but that tracks a bit better with how leetcode is supposed to go.
First off, it turns out that getting the length of an empty array doesn’t through an error in JavaScript.
But it does mean that if there are no openings left, lastOpen
is undefined
and we’ll return false
because there is no corresponding open tag to our closing tag! This applies even if we only have a single closing tag as our input string.
In summary, I lucked out, and that’s why this is the only leetcode that I have been able to approach blind and finish in 30 minutes. Luckily, because it was only the second one ever tried, the result was that I gained a huge amount of unearned confidence!
That confidence formed a sort of force field, protecting me from the grueling leetcode studying that followed, ultimately leaving me vulnerable, optimistic, and perfectly situated to fail my technical interview with Figma! So it goes.
Re-attempt 2: August 24
Remembered a little bit of this, mostly just that I had an object mapping closing to opening parens. And that I didn’t need an object doing the opposite.
Time: 9 minutes
My initial small mistake is that I thought I might need 2 for loops.
Above, I talk about handling edge cases by luck. This came back to bite me - by running my code, I got hit by a single edge case I didn’t see coming, and it took me two tries to handle it.
My first attempt was naive - I quickly created the anOpener
variable to check that there was at least one opener, a misguided attempt that did solve the case where I only got }
, thinking of that as somehow unique. But the problem here isn’t that there’s just one closer and no openers, it’s more broadly how the closer shows up with no corresponding opener, which should always result in failure.
So here’s a slightly simplified version:
var isValid = function(s) {
let thang = {
"}": "{",
")": "(",
"]": "["
}
let opens = "{[("
let openers = []
for (const p of s){
if (opens.includes(p)){
anOpener = true
openers.push(p)
} else {
// closer territory
let partner = thang[p]
// check the last opener to see if it is the same as the closer
if (openers[openers.length - 1] === partner){
openers.pop()
} else {
return false
}
}
}
if (!openers.length) return true
return false
};