Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# 1190. Reverse Substrings Between Each Pair of Parentheses

[LeetCode Link](https://leetcode.com/problems/reverse-substrings-between-each-pair-of-parentheses/)

Difficulty: Medium
Topics: String, Stack, Bracket Sequences
Acceptance Rate: 72.9%

## Hints

### Hint 1

Whenever you see nested, balanced brackets that must be processed "innermost first", think about a **stack**. Matching each `(` with its `)` is the classic stack job.

### Hint 2

A straightforward approach: keep a stack of partially built strings (or indices). When you hit `)`, reverse the segment since the most recent `(`. This is O(n²) in the worst case but passes easily for n ≤ 2000. Can you avoid doing the reversals physically at all?

### Hint 3

Precompute `pair[i]` — the index of the matching parenthesis for every bracket (one stack pass). Now walk the string with a pointer `i` and a direction `d = +1`. When you land on a parenthesis, **jump to its partner and flip the direction** (`i = pair[i]; d = -d`), then keep stepping. Letters are appended as you visit them. Each character is visited exactly once, so the walk is O(n).

## Approach

**Why the "wormhole" trick works:** Reversing a segment means reading it from right to left. When we reach an opening `(` while moving forward, the segment inside needs to be read backwards — so we teleport to the matching `)` and start moving left. Nested pairs inside are handled the same way: hitting a bracket while moving left teleports us to its partner and flips direction again (two reversals cancel out). When we finally reach the original `(` again from the inside, we teleport back to the `)` and continue forward past it.

**Algorithm:**

1. **Pair brackets.** Scan `s` with a stack of indices. Push on `(`; on `)`, pop `j` and set `pair[i] = j`, `pair[j] = i`.
2. **Walk.** Start at `i = 0`, `d = 1`. While `0 <= i < n`:
- If `s[i]` is a bracket: `i = pair[i]`, `d = -d`.
- Otherwise append `s[i]` to the result.
- Then `i += d`.
3. Return the result.

**Example:** `s = "(u(love)i)"` (indices 0..9, pairs: 0↔9, 2↔7)

- i=0 `(` → jump to 9, d=-1 → i=8 `i` → append "i"
- i=7 `)` → jump to 2, d=+1 → i=3..6 → append "love"
- i=7 `)` → jump to 2, d=-1 → i=1 `u` → append "u"
- i=0 `(` → jump to 9, d=+1 → i=10, stop.

Result: `"iloveu"` ✓

A simpler stack-of-builders solution (reverse on each `)`) is also perfectly acceptable in an interview; mention the O(n) wormhole idea as the optimization.

## Complexity Analysis

Time Complexity: O(n) — one pass to pair brackets, one walk visiting each character a bounded number of times.
Space Complexity: O(n) — the `pair` array, the index stack, and the output buffer.

## Edge Cases

- **No parentheses** (`"abc"`): the string is returned unchanged.
- **Empty parentheses** (`"()"` or `"a()b"`): contribute nothing; the walk jumps in and straight back out.
- **Deep nesting** (`"((ab))"`): even number of reversals cancels out → `"ab"`.
- **Adjacent groups** (`"(ab)(cd)"`): each group is reversed independently → `"badc"`.
- **Letters outside brackets** (`"a(bc)d"`): only the inner segment is reversed → `"acbd"`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
number: "1190"
frontend_id: "1190"
title: "Reverse Substrings Between Each Pair of Parentheses"
slug: "reverse-substrings-between-each-pair-of-parentheses"
difficulty: "Medium"
topics:
- "String"
- "Stack"
- "Bracket Sequences"
acceptance_rate: 7290.8
is_premium: false
created_at: "2026-09-27T05:31:01.909324+00:00"
fetched_at: "2026-09-27T05:31:01.909324+00:00"
link: "https://leetcode.com/problems/reverse-substrings-between-each-pair-of-parentheses/"
date: "2026-09-27"
---

# 1190. Reverse Substrings Between Each Pair of Parentheses

You are given a string `s` that consists of lower case English letters and brackets.

Reverse the strings in each pair of matching parentheses, starting from the innermost one.

Your result should **not** contain any brackets.



**Example 1:**


**Input:** s = "(abcd)"
**Output:** "dcba"


**Example 2:**


**Input:** s = "(u(love)i)"
**Output:** "iloveu"
**Explanation:** The substring "love" is reversed first, then the whole string is reversed.


**Example 3:**


**Input:** s = "(ed(et(oc))el)"
**Output:** "leetcode"
**Explanation:** First, we reverse the substring "oc", then "etco", and finally, the whole string.




**Constraints:**

* `1 <= s.length <= 2000`
* `s` only contains lower case English characters and parentheses.
* It is guaranteed that all parentheses are balanced.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package main

// Approach: "wormhole" traversal.
// First pair every '(' with its matching ')' using a stack of indices.
// Then walk the string: on a bracket, jump to its partner and flip the
// walking direction; on a letter, append it. Each segment inside a pair is
// thus read in reverse, and nested reversals cancel naturally. O(n) time.
func reverseParentheses(s string) string {
n := len(s)
pair := make([]int, n)
stack := make([]int, 0, n)
for i := 0; i < n; i++ {
switch s[i] {
case '(':
stack = append(stack, i)
case ')':
j := stack[len(stack)-1]
stack = stack[:len(stack)-1]
pair[i], pair[j] = j, i
}
}

res := make([]byte, 0, n)
for i, d := 0, 1; i >= 0 && i < n; i += d {
if s[i] == '(' || s[i] == ')' {
i = pair[i]
d = -d
} else {
res = append(res, s[i])
}
}
return string(res)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import "testing"

func TestReverseParentheses(t *testing.T) {
tests := []struct {
name string
s string
expected string
}{
{"example 1: single pair", "(abcd)", "dcba"},
{"example 2: two nested levels", "(u(love)i)", "iloveu"},
{"example 3: three nested levels", "(ed(et(oc))el)", "leetcode"},
{"edge case: no parentheses", "abc", "abc"},
{"edge case: empty parentheses", "a()b", "ab"},
{"edge case: only empty parentheses", "()", ""},
{"edge case: double nesting cancels", "((ab))", "ab"},
{"edge case: adjacent groups", "(ab)(cd)", "badc"},
{"edge case: letters outside brackets", "a(bc)d", "acbd"},
{"edge case: single character", "a", "a"},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := reverseParentheses(tt.s)
if result != tt.expected {
t.Errorf("got %q, want %q", result, tt.expected)
}
})
}
}