给出一个字符串 s(仅含有小写英文字母和括号)。
请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。
注意,您的结果中 不应  包含任何括号。
示例 1: 
**输入:** s = "(abcd)"
**输出:** "dcba"
示例 2: 
**输入:** s = "(u(love)i)"
**输出:** "iloveu"
**解释:** 先反转子字符串 "love" ,然后反转整个字符串。
示例 3: 
**输入:** s = "(ed(et(oc))el)"
**输出:** "leetcode"
**解释:** 先反转子字符串 "oc" ,接着反转 "etco" ,然后反转整个字符串。
示例 4: 
**输入:** s = "a(bcdefghijkl(mno)p)q"
**输出:** "apmnolkjihgfedcbq"
提示: 
1 <= s.length <= 2000s 中只有小写英文字母和括号题目测试用例确保所有括号都是成对出现的 
 
方法一:栈 思路及算法 
本题要求按照从括号内到外的顺序进行处理。如字符串 (u(love)i),首先处理内层括号,变为 (uevoli),然后处理外层括号,变为 iloveu。
对于括号序列相关的题目,通用的解法是使用递归或栈。本题中我们将使用栈解决。
我们从左到右遍历该字符串,使用字符串 str 记录当前层所遍历到的小写英文字母。对于当前遍历的字符:
注意到我们仅在遇到右括号时才进行字符串处理,这样可以保证我们是按照从括号内到外的顺序处理字符串。
代码 
[sol1-C++] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class  Solution  {public :    string reverseParentheses (string s)   {         stack<string> stk;         string str;         for  (auto  &ch : s) {             if  (ch == '(' ) {                 stk.push (str);                 str = "" ;             } else  if  (ch == ')' ) {                 reverse (str.begin (), str.end ());                 str = stk.top () + str;                 stk.pop ();             } else  {                 str.push_back (ch);             }         }         return  str;     } }; 
[sol1-Java] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class  Solution  {    public  String reverseParentheses (String s)  {         Deque<String> stack = new  LinkedList <String>();         StringBuffer  sb  =  new  StringBuffer ();         for  (int  i  =  0 ; i < s.length(); i++) {             char  ch  =  s.charAt(i);             if  (ch == '(' ) {                 stack.push(sb.toString());                 sb.setLength(0 );             } else  if  (ch == ')' ) {                 sb.reverse();                 sb.insert(0 , stack.pop());             } else  {                 sb.append(ch);             }         }         return  sb.toString();     } } 
[sol1-C#] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public  class  Solution  {    public  string  ReverseParentheses (string  s         Stack<string > stack = new  Stack<string >();         StringBuilder sb = new  StringBuilder();         foreach  (char  ch in  s) {             if  (ch == '(' ) {                 stack.Push(sb.ToString());                 sb.Length = 0 ;             } else  if  (ch == ')' ) {                 char [] arr = sb.ToString().ToCharArray();                 sb.Length = 0 ;                 for  (int  i = arr.Length - 1 ; i >= 0 ; i--) {                     sb.Append(arr[i]);                 }                 sb.Insert(0 , stack.Pop());             } else  {                 sb.Append(ch);             }         }         return  sb.ToString();     } } 
[sol1-JavaScript] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 var  reverseParentheses = function (s ) {    const  stk = [];     let  str = '' ;     for  (const  ch of  s) {         if  (ch === '(' ) {             stk.push (str);             str = '' ;         } else  if  (ch === ')' ) {             str = str.split ("" ).reverse ().join ("" );             str = stk[stk.length  - 1 ] + str;             stk.pop ();         } else  {             str += ch;         }     }     return  str; }; 
[sol1-Golang] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 func  reverseParentheses (s string ) string  {    stack := [][]byte {}     str := []byte {}     for  i := range  s {         if  s[i] == '('  {             stack = append (stack, str)             str = []byte {}         } else  if  s[i] == ')'  {             for  j, n := 0 , len (str); j < n/2 ; j++ {                 str[j], str[n-1 -j] = str[n-1 -j], str[j]             }             str = append (stack[len (stack)-1 ], str...)             stack = stack[:len (stack)-1 ]         } else  {             str = append (str, s[i])         }     }     return  string (str) } 
[sol1-C] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 void  reverse (char * str, int  strSize)  {    for  (int  j = 0 ; j < strSize / 2 ; j++) {         char  tmp = str[j];         str[j] = str[strSize - j - 1 ], str[strSize - j - 1 ] = tmp;     } } char * reverseParentheses (char * s)  {    int  n = strlen (s);     char * stk[n];     int  top = 0 ;     char * str = malloc (sizeof (char ) * (n + 1 ));     str[0 ] = '\0' ;     int  strSize = 0 ;     for  (int  i = 0 ; i < n; i++) {         if  (s[i] == '(' ) {             stk[top] = malloc (sizeof (char ) * (strSize + 1 ));             memcpy (stk[top], str, sizeof (char ) * (strSize + 1 ));             top++;             str[0 ] = '\0' ;             strSize = 0 ;         } else  if  (s[i] == ')' ) {             reverse(str, strSize);             int  len = strlen (stk[top - 1 ]);             for  (int  j = strSize; j >= 0 ; j--) {                 str[j + len] = str[j];             }             memcpy (str, stk[top - 1 ], sizeof (char ) * len);             strSize += len;             top--;         } else  {             str[strSize++] = s[i];             str[strSize] = '\0' ;         }     }     return  str; } 
复杂度分析 
方法二:预处理括号 思路及算法 
我们可以将括号的反转理解为逆序地遍历括号,如下图:
第一步我们向右移动到左括号,此时我们跳跃到该左括号对应的右括号(进入了更深一层); 
第二到第三步我们在括号内部向左移动(完成了更深层的遍历); 
第四步我们向左移动到左括号,此时我们跳跃到该左括号对应的右括号(返回到上一层); 
第五步我们在括号外向右移动(继续遍历)。 
 
读者们可以自行尝试模拟两层乃至多层括号嵌套的移动方案,规律可以从当前的单层括号中总结出来。
假设我们沿着某个方向移动,此时遇到了括号,那么我们只需要首先跳跃到该括号对应的另一个括号所在处,然后改变我们的移动方向即可。这个方案同时适用于遍历时进入更深一层,以及完成当前层的遍历后返回到上一层的方案。
在实际代码中,我们需要预处理出每一个括号对应的另一个括号所在的位置,这一部分我们可以使用栈解决。当我们预处理完成后,即可在线性时间内完成遍历,遍历的字符串顺序即为反转后的字符串。
代码 
[sol2-C++] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class  Solution  {public :    string reverseParentheses (string s)   {         int  n = s.length ();         vector<int > pair (n)  ;         stack<int > stk;         for  (int  i = 0 ; i < n; i++) {             if  (s[i] == '(' ) {                 stk.push (i);             } else  if  (s[i] == ')' ) {                 int  j = stk.top ();                 stk.pop ();                 pair[i] = j, pair[j] = i;             }         }         string ret;         int  index = 0 , step = 1 ;         while  (index < n) {             if  (s[index] == '('  || s[index] == ')' ) {                 index = pair[index];                 step = -step;             } else  {                 ret.push_back (s[index]);             }             index += step;         }         return  ret;     } }; 
[sol2-Java] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class  Solution  {    public  String reverseParentheses (String s)  {         int  n  =  s.length();         int [] pair = new  int [n];         Deque<Integer> stack = new  LinkedList <Integer>();         for  (int  i  =  0 ; i < n; i++) {             if  (s.charAt(i) == '(' ) {                 stack.push(i);             } else  if  (s.charAt(i) == ')' ) {                 int  j  =  stack.pop();                 pair[i] = j;                 pair[j] = i;             }         }         StringBuffer  sb  =  new  StringBuffer ();         int  index  =  0 , step = 1 ;         while  (index < n) {             if  (s.charAt(index) == '('  || s.charAt(index) == ')' ) {                 index = pair[index];                 step = -step;             } else  {                 sb.append(s.charAt(index));             }             index += step;         }         return  sb.toString();     } } 
[sol2-C#] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public  class  Solution  {    public  string  ReverseParentheses (string  s         int  n = s.Length;         int [] pair = new  int [n];         Stack<int > stack = new  Stack<int >();         for  (int  i = 0 ; i < n; i++) {             if  (s[i] == '(' ) {                 stack.Push(i);             } else  if  (s[i] == ')' ) {                 int  j = stack.Pop();                 pair[i] = j;                 pair[j] = i;             }         }         StringBuilder sb = new  StringBuilder();         int  index = 0 , step = 1 ;         while  (index < n) {             if  (s[index] == '('  || s[index] == ')' ) {                 index = pair[index];                 step = -step;             } else  {                 sb.Append(s[index]);             }             index += step;         }         return  sb.ToString();     } } 
[sol2-JavaScript] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 var  reverseParentheses = function (s ) {    const  n = s.length ;     const  pair = new  Array (n).fill (0 );     const  stack = [];     for  (let  i = 0 ; i < n; i++) {         if  (s[i] === '(' ) {             stack.push (i);         } else  if  (s[i] == ')' ) {             const  j = stack.pop ();             pair[i] = j;             pair[j] = i;         }     }     const  sb = [];     let  index = 0 , step = 1 ;     while  (index < n) {         if  (s[index] === '('  || s[index] === ')' ) {             index = pair[index];             step = -step;         } else  {             sb.push (s[index]);         }         index += step;     }     return  sb.join ('' ); }; 
[sol2-Golang] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 func  reverseParentheses (s string ) string  {    n := len (s)     pair := make ([]int , n)     stack := []int {}     for  i, b := range  s {         if  b == '('  {             stack = append (stack, i)         } else  if  b == ')'  {             j := stack[len (stack)-1 ]             stack = stack[:len (stack)-1 ]             pair[i], pair[j] = j, i         }     }     ans := []byte {}     for  i, step := 0 , 1 ; i < n; i += step {         if  s[i] == '('  || s[i] == ')'  {             i = pair[i]             step = -step         } else  {             ans = append (ans, s[i])         }     }     return  string (ans) } 
[sol2-C] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 char * reverseParentheses (char * s)  {    int  n = strlen (s);     int  pair [n];     memset (pair , 0 , sizeof (pair ));     int  stk[n], top = 0 ;     for  (int  i = 0 ; i < n; i++) {         if  (s[i] == '(' ) {             stk[top++] = i;         } else  if  (s[i] == ')' ) {             int  j = stk[--top];             pair [i] = j, pair [j] = i;         }     }     char * ret = malloc (sizeof (char ) * (n + 1 ));     int  retSize = 0 ;     int  index = 0 , step = 1 ;     while  (index < n) {         if  (s[index] == '('  || s[index] == ')' ) {             index = pair [index];             step = -step;         } else  {             ret[retSize++] = s[index];         }         index += step;     }     ret[retSize] = '\0' ;     return  ret; } 
复杂度分析