问题描述
Longest Substring Without Repeating Characters
Topic: Hash Table, Two pointer, String, Sliding Windows
给定一个字符串,请找出其中不含有重复字符的 最长子串 的长度。
Given a string s, find the length of the longest substring without repeating characters.
Example 1:
Input: s = "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
Example 2:
Input: s = "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.
Example 3:
Input: s = "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.
Example 4:
Input: s = ""
Output: 0
Constraints:
0 <= s.length <= 5 * 104
s consists of English letters, digits, symbols and spaces.
问题分析
一般来说,当您需要跟踪连续的元素序列(例如,对子数组中的值求和、字符串序列等)时,滑动窗口技术很有用。
Generally speaking, the sliding window technique is useful when you need to keep track of a contiguous sequence of elements, such as summing up the values in a subarray.
滑动窗口算法思路
滑动窗口的应用场景有几个特点:
1. 需要输出或比较的结果在原数据结构中是连续排列的;
2. 每次窗口滑动时,只需观察窗口两端元素的变化,无论窗口多长,每次只操作两个头尾元素,当用到的窗口比较长时,可以显著减少操作次数;
3. 窗口内元素的整体性比较强,窗口滑动可以只通过操作头尾两个位置的变化实现,但对比结果时往往要用到窗口中所有元素。
问题答案
滑动窗口实现的源代码(Kotlin 语言):
class Solution {
fun lengthOfLongestSubstring(s: String): Int {
var ans = 0
var left = 0
var right = 0
val n = s.length
val window = mutableSetOf<Char>()
while (left < n && right < n) {
// slide window's right side
if (!window.contains(s[right])) {
window.add(s[right++])
ans = Math.max(ans, right - left)
} else {
// slide window's left side
window.remove(s[left++])
}
}
return ans
}
}
时间复杂度:O(N),其中N为字符串长度;
空间复杂度:O(N),其中N为字符串长度。
参考资料:
https:///subarray-with-a-given-sum-sliding-window-technique/
https://charon.me/posts/leetcode/day13/
https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
https://zhuanlan.zhihu.com/p/129018030