Skip to content

Commit

Permalink
feat: 每日一题2019-09-23 (azl397985856#211)
Browse files Browse the repository at this point in the history
* 每日一题 2019-10-11

* 去掉分析步骤中的推敲错误

* 修改格式问题,代码高亮,39588数学公式区域去掉了

* 对原 $$ 数学公式区域部分 添加了文字解释

* 每日一题20190923

* 补充添加标签,在README中添加链接
  • Loading branch information
zhangjinyang authored and azl397985856 committed Oct 22, 2019
1 parent 188f0db commit 6a3dc7e
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 0 deletions.
166 changes: 166 additions & 0 deletions daily/2019-09-23.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# 毎日一题 - 反转每对括号间的子串

## 信息卡片

* 时间:2019-09-23
* 题目链接:https://leetcode-cn.com/problems/reverse-substrings-between-each-pair-of-parentheses
* tag:`String` `Backtracking`
## 题目描述
```
给出一个字符串 s(仅含有小写英文字母和括号)。
请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。
注意,您的结果中 不应 包含任何括号。
示例 1:
输入:s = "(abcd)"
输出:"dcba"
示例 2:
输入:s = "(u(love)i)"
输出:"iloveu"
示例 3:
输入:s = "(ed(et(oc))el)"
输出:"leetcode"
示例 4:
输入:s = "a(bcdefghijkl(mno)p)q"
输出:"apmnolkjihgfedcbq"
提示:
0 <= s.length <= 2000
s 中只有小写英文字母和括号
我们确保所有括号都是成对出现的
```

## 参考答案

#### 思路

1. 对字符串中的字符遍历


2. 括号是有层次性的,所以这里用递归的方式处理内层的字符串,内层处理完成后回溯。返回内层有括号索引的下一个位置,以及括号内反转完成后的字符串。


3. 在2的递归过程中,原字符串也需要作为递归方法的参数传递进来


4. 递归方法的负责处理从当前位置开始到遇到对应的有括号之间的字符串,将其反转;若遇到新的左括号,创建临时的StringBuilder用于记录递归方法内反转的字符串,进入新的一层递归;递归完成后临时StringBuilder被填充并且是反转后的结果,append到上一层递归的StringBuilder中。


5. 递归回溯到最上层时,StringBuilder即为最终结果。


6. 更多代码细节可以关注下代码注释

#### 代码如下

```java
package com.jinyang.algorithms.string;

/**
* Created by Zhang.Jinyang&Hardy on 2019/10/17.
*/
public class ReverseParentheses {

public static void main(String[] args) {

/**
* 用例的类型
* (ab(cd)ef)
* ab(cd)
* ab(cd)ef
* ((ab)c)def
* abc(d(ef))
* */
String s = "ab((cd)ef)";

StringBuilder builder = new StringBuilder();
reverseParentheses(s, 0, builder, 0);
System.out.println(builder.toString());
}

/**
* leetcode 1190
* 耗时 1ms
* 内存消耗 34.6M
* */
static int reverseParentheses(String s, int index, StringBuilder stringBuilder, int leftCount) {


//遍历字符串
while (index < s.length()) {
/**
* case 当前字符为'('
* leftCount++; 记录已遍历 但未 找到相对应的右括号 的左括号数目;这里每当当前字符为'(',leftCount+1
* case: index 为 0,第一个字符为'('
* index ++, 继续遍历
* case:index 不为0, 不是第一个字符
* 递归,index++,new stringBuilder(临时存放从当前'('到其相对应的')'里的字符,不包含'('和')'), leftCount
* 递归后,new stringBuilder已被填充好 从当前'('到其相对应的')'里的字符 反转后的字符串;且返回参数为下一次要访问的字符下标index
* leftCount --;因为进入递归后返回时已经将 当前'(' 与其响应的 ')' 内的字符反转,所以左括号数减1
* 递归前的 stringBuilder append 递归后,已反转的 new stringBuilder
* 继续遍历.
* */
if (s.charAt(index) == '(') {
leftCount++;
if (index != 0) {
StringBuilder sTemp = new StringBuilder();
index = reverseParentheses(s, index + 1, sTemp, leftCount);
leftCount--;
stringBuilder.append(sTemp);
continue;
}

index++;
continue;
}

/**
* case 当前字符为')'
* 反转stringBuilder里的字符位置;
* index++;
* case:当前leftCount >1 那么当前是在递归过程中
* return index;//回溯
* case: 当前leftCount <=1 当前不是递归
* 继续遍历;
* */
if (s.charAt(index) == ')') {
stringBuilder.reverse();
index++;
if (leftCount > 1) {
return index;
} else {
continue;
}
}

/**当前字符不是'(' 或 ')'
* 当前stringBuilder append 当前下标对应的字符
* index++
* 继续遍历
* */
stringBuilder.append(s.charAt(index));
index++;
}
return index;
}


}


```


## 优秀解答

>暂缺
5 changes: 5 additions & 0 deletions daily/2019-10-11.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@

1. 由集合中元素的特点可以联想到 **二进制**。如果将集合中的所有元素都用二进制来表示的话:

1 等于 2的0次方 等于 二进制的 1
2 等于 2的1次方 等于 二进制的 10
4 等于 2的2次方 等于 二进制的 100
...
即:
1=2^0=(1)2; 2=2^1=(10)2; 4 = 2^2 = (100)2;..... .**(等号最后的数都是二进制表示法)**

集合中的每一个元素都可以表示为 首位为 1 其他位为 0 的二进制数。
Expand Down
4 changes: 4 additions & 0 deletions daily/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,4 +276,8 @@ tag: `DP` `Bit`

时间: 2019-10-11

### [1190.反转每对括号间的子串](./2019-09-23.md)

tag: `String` `Backtracking`

时间: 2019-09-23

0 comments on commit 6a3dc7e

Please sign in to comment.