Skip to content

feat: 每日一题2019-09-23 #211

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Oct 22, 2019
Merged
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
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