Remove the Outermost Parentheses From Every Primitive Group
Solve this Problems is always a sequence of these primitive groups placed back to back. Given a valid parentheses string s, remove the outermost parentheses of every primitive group and return what's left.
Tracking depth as you scan and slicing out each group once its depth returns to 0 works, but building each slice separately means an extra pass through the substring boundaries. The faster approach skips slicing entirely: classify each character in a single pass by checking depth right before incrementing (for an opener) or right after decrementing (for a closer) — a depth of exactly 0 at that check means the character is an outermost paren to drop, anything else means it's an inner paren to keep.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ s.length ≤ 5 × 10⁴ - ◆
s consists only of '(' and ')' - ◆
s is a valid parentheses string
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
| 1 | class Solution { |
| 2 | public String removeOuterParentheses(String s) { |
| 3 | StringBuilder result = new StringBuilder(); |
| 4 | int depth = 0; |
| 5 | for (char c : s.toCharArray()) { |
| 6 | if (c == '(') { |
| 7 | if (depth > 0) result.append(c); |
| 8 | depth++; |
| 9 | } else { |
| 10 | depth--; |
| 11 | if (depth > 0) result.append(c); |
| 12 | } |
| 13 | } |
| 14 | return result.toString(); |
| 15 | } |
| 16 | } |
| 17 |
0Start depth at 0. Walk the string once, classifying each character by depth alone — no slicing needed.
Approach & Solutions
Brute Force — Track Depth, Slice Each Group
BruteA "primitive" group is a maximal balanced run of parentheses that never dips back to depth 0 in the middle — s is just a sequence of these groups placed back to back. Track depth as you scan: every '(' increases it, every ')' decreases it. Whenever depth returns to 0, you've just closed one whole primitive group — slice out everything between its outer pair (start+1 to i, exclusive of both ends) and append it to the result.
O(n)O(n)1class Solution {
2 public String removeOuterParentheses(String s) {
3 StringBuilder result = new StringBuilder();
4 int start = 0;
5 int depth = 0;
6 for (int i = 0; i < s.length(); i++) {
7 if (s.charAt(i) == '(') depth++;
8 else depth--;
9 if (depth == 0) {
10 result.append(s, start + 1, i);
11 start = i + 1;
12 }
13 }
14 return result.toString();
15 }
16}Optimal — Single Pass Depth Classification
OptimalNo slicing needed at all — classify each character as you scan. For an opening paren, check depth BEFORE incrementing: if depth was 0, this is a group's outermost opener, skip it; otherwise it's an inner paren, keep it. For a closing paren, decrement depth FIRST, then check: if depth is now 0, this was a group's outermost closer, skip it; otherwise it's an inner paren, keep it. One pass, no extra slicing pass required.
O(n)O(n)1class Solution {
2 public String removeOuterParentheses(String s) {
3 StringBuilder result = new StringBuilder();
4 int depth = 0;
5 for (char c : s.toCharArray()) {
6 if (c == '(') {
7 if (depth > 0) result.append(c);
8 depth++;
9 } else {
10 depth--;
11 if (depth > 0) result.append(c);
12 }
13 }
14 return result.toString();
15 }
16}