串联所有单词的子串
来源:力扣(LeetCode) 链接:leetcode.cn/problems/su…
给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。
s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。
- 例如,如果 words = ["ab","cd","ef"], 那么 "abcdef", "abefcd","cdabef", "cdefab","efabcd", 和 "efcdab" 都是串联子串。 "acdbef" 不是串联子串,因为他不是任何 words 排列的连接。
返回所有串联字串在 s 中的开始索引。你可以以 任意顺序 返回答案。
示例 1:
输入:s = "barfoothefoobarman", words = ["foo","bar"]
输出:[0,9]
解释:因为 words.length == 2 同时 words[i].length == 3,连接的子字符串的长度必须为 6。
子串 "barfoo" 开始位置是 0。它是 words 中以 ["bar","foo"] 顺序排列的连接。
子串 "foobar" 开始位置是 9。它是 words 中以 ["foo","bar"] 顺序排列的连接。
输出顺序无关紧要。返回 [9,0] 也是可以的。
示例 2:
输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
输出:[]
解释:因为 words.length == 4 并且 words[i].length == 4,所以串联子串的长度必须为 16。
s 中没有子串长度为 16 并且等于 words 的任何顺序排列的连接。
所以我们返回一个空数组。
示例 3:
输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
输出:[6,9,12]
解释:因为 words.length == 3 并且 words[i].length == 3,所以串联子串的长度必须为 9。
子串 "foobarthe" 开始位置是 6。它是 words 中以 ["foo","bar","the"] 顺序排列的连接。
子串 "barthefoo" 开始位置是 9。它是 words 中以 ["bar","the","foo"] 顺序排列的连接。
子串 "thefoobar" 开始位置是 12。它是 words 中以 ["the","foo","bar"] 顺序排列的连接。
提示:
- 1 <= s.length <= 104
- 1 <= words.length <= 5000
- 1 <= words[i].length <= 30
- words[i] 和 s 由小写英文字母组成
代码
class Solution {
public List<Integer> findSubstring(String s, String[] words) {
List<Integer> result = new ArrayList<>();
if (s.isEmpty() || words.length == 0) {
return result;
}
int wordLength = words[0].length();
int wordCount = words.length;
int totalLength = wordLength * wordCount;
Map<String, Integer> wordMap = new HashMap<>();
for (String word : words) {
wordMap.put(word, wordMap.getOrDefault(word, 0) + 1);
}
for (int i = 0; i <= s.length() - totalLength; i++) {
Map<String, Integer> seen = new HashMap<>();
int j = 0;
while (j < wordCount) {
String currentWord = s.substring(i + j * wordLength, i + (j + 1) * wordLength);
if (wordMap.containsKey(currentWord)) {
seen.put(currentWord, seen.getOrDefault(currentWord, 0) + 1);
if (seen.get(currentWord) > wordMap.get(currentWord)) {
break;
}
} else {
break;
}
j++;
}
if (j == wordCount) {
result.add(i);
}
}
return result;
}
}
思路分析
- 首先判断给定字符串
s和单词列表words是否为空。如果其中任意一个为空,则直接返回空结果列表。 - 获取单词列表中单词的长度
wordLength,以及单词的总个数wordCount和总长度totalLength。 - 创建一个哈希表
wordMap,用于存储单词列表中每个单词出现的次数。 - 遍历字符串
s的每个可能的起始位置i,从0到s.length() - totalLength。 - 在每个起始位置
i,使用滑动窗口和哈希表来检查子串是否包含指定的单词列表。使用变量j来表示滑动窗口的位置。 - 在滑动窗口中,从起始位置
i开始,以单词长度为步长,依次取出子串中的单词。 - 检查当前单词是否存在于
wordMap中。如果存在,更新seen哈希表中当前单词的出现次数,并检查是否超过了在wordMap中的出现次数。 - 如果当前单词不在
wordMap中,或者当前单词的出现次数超过了在wordMap中的出现次数,终止滑动窗口的移动。
最长有效括号
来源:力扣(LeetCode) 链接:leetcode.cn/problems/lo…
给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。
示例 1:
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"
示例 2:
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"
示例 3:
输入:s = ""
输出:0
提示:
- 0 <= s.length <= 3 * 104
- s[i] 为 '(' 或 ')'
代码
class Solution {
public int longestValidParentheses(String s) {
int maxLength = 0;
Stack<Integer> stack = new Stack<>();
stack.push(-1);
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
stack.push(i);
} else {
stack.pop();
if (stack.isEmpty()) {
stack.push(i);
} else {
maxLength = Math.max(maxLength, i - stack.peek());
}
}
}
return maxLength;
}
}
思路分析
- 初始化最大长度
maxLength为0,并创建一个栈stack,并将-1推入栈中。 - 遍历字符串
s中的每个字符。 - 如果当前字符是'(',将当前字符的下标推入栈中。
- 如果当前字符是')',表示遇到了一个可能的有效括号的结尾。我们通过弹出栈顶元素来匹配括号。
- 如果栈为空,表示当前')'没有匹配的'(',将当前字符的下标推入栈中作为新的起始点。
- 如果栈不为空,计算当前字符的下标与栈顶元素的差值,即为当前有效括号的长度。
- 将当前有效括号的长度与最大长度
maxLength比较,取较大值作为新的最大长度。 - 遍历完字符串后,返回最大长度
maxLength。