Skip to content
Merged

1212 #39

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
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
# @Author: LiLing
# @Date: 2018-10-02 19:20:50
# @Last Modified by: Liling
# @Last Modified time: 2018-12-12 20:39:03
"""
给定一个字符串,找出不含有重复字符的最长子串的长度。

示例 1:

输入: "abcabcbb"
输出: 3
解释: 无重复字符的最长子串是 "abc",其长度为 3。
示例 2:

输入: "bbbbb"
输出: 1
解释: 无重复字符的最长子串是 "b",其长度为 1。
示例 3:

输入: "pwwkew"
输出: 3
解释: 无重复字符的最长子串是 "wke",其长度为 3。
请注意,答案必须是一个子串,"pwke" 是一个子序列 而不是子串
"""
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
if s == None or len(s) <= 0:
return 0
# charDict存储每个字符以及字符出现的最后的位置, res为当前最长的子串长度, st当前无重复子串的最左边字符的位置
charDict, res, st = {}, 0, 0
for i, ch in enumerate(s):
if ch not in charDict or charDict[ch] < st:
res = max(res, i - st + 1)
else:
st = charDict[ch] + 1
charDict[ch] = i
return res

s = Solution()
print(s.lengthOfLongestSubstring('pwwkew'))
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
## 03.Longest Substring Without Repeating Characters无重复字符的最长子串

### 题目描述

给定一个字符串,找出不含有重复字符的最长子串的长度。

示例 1:

输入: "abcabcbb"
输出: 3
解释: 无重复字符的最长子串是 "abc",其长度为 3。
示例 2:

输入: "bbbbb"
输出: 1
解释: 无重复字符的最长子串是 "b",其长度为 1。
示例 3:

输入: "pwwkew"
输出: 3
解释: 无重复字符的最长子串是 "wke",其长度为 3。
​ 请注意,答案必须是一个子串,"pwke" 是一个子序列 而不是子串

### 思路

第一种方法是暴力解法,检查所有的子串是不是有重复的字符,需要写一个检查字符串是否有重复字符的函数。这种方法的时间复杂度是$O(n^3)$,空间复杂度是O(min(n,m))。n是字符串长度,m是charset/alphabet长度。



第二种方法。

在第一种方法中,我们需要重复检查一个子串是不是有重复的字符,但这个步骤是不必要的。如果一个子串$s_{ij}$ 的i到j-1是不重复的子串,我们只需要检查s[j]是不是已经在前面的子串中就可以了。

怎么检查呢?可以用哈希表作为滑动窗口来检查。用哈希表存储当前窗口[i,j)(初始时i=j)的字符,然后将索引j依次向右滑动,检查新的字符是否在哈希表中。如果不在,继续滑动。直到s[j]已经在哈希表中为止。这样就能找到以索引i开始的最长的无重复子串了。对于每个i重复上述操作就能得到结果。

这种方法的时间复杂度是O(2n)=O(n),最坏情况下每个字符会被访问两次(i和j),空间复杂度不变,O(min(m,n))。



上述方法还可以改进。

如果s[j]在[i,j)有一个重复的字符,其索引是j',我们不需要一点一点地增大i,而是可以直接跳过[i, j']这个范围,直接让i=j'+1。

我们可以不用哈希表来判断字符是否存在,我们可以定义一个字符到索引的映射字典。这样的话当我们遇到同样的字符时可以马上跳过这个字符。

代码如下。当前窗口是[st, i)。如果当前字符不在字典中,或它的上一个索引不在当前扫描窗口内,说明还没有遇到重复的字符,更新当前最长的子串长度res;否则(当前字符是重复字符),更新扫描窗口(注意在上一个字符的时候已经更新了res,所以这里不用再更新)。记住不管什么情况都要更新字符的最新索引。

```python
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
if s == None or len(s) <= 0:
return 0
# charDict存储每个字符以及字符出现的最后的位置, res为当前最长的子串长度, st当前无重复子串的最左边字符的位置
charDict, res, st = {}, 0, 0
for i, ch in enumerate(s):
if ch not in charDict or charDict[ch] < st:
res = max(res, i - st + 1)
else:
st = charDict[ch] + 1
charDict[ch] = i
return res
```



1 change: 1 addition & 0 deletions codingling/LeetCode-04/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test