一、题目原型:
给定一个字符串,找出不含有重复字符的最长子串的长度。
二、题目意思剖析:
1 | 给定 "abcabcbb" ,没有重复字符的最长子串是 "abc" ,那么长度就是3。 |
三、解题思路:
3.1暴力破解
1 | // 分析 |
1 | // 上代码 |
3.2滑动窗口
1 | func lengthOfLongestSubstring(_ s: String) -> Int { |
四、小结
暴力破解:时间复杂度o(n的平方)
滑动窗口:时间复杂度o(n*一个常数)
滑动窗口参考资料,这里边有详细图解
由于时间复杂度太高了,没有通过leetcode检测,超时了。😭1
2
3
4
5// leetcode测试用例
var s:String = ""
for _ in 0..<100 {
s .append("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ")
}
不同区间的耗时统计:
0..<10 - 284ms
0..<20 - 960ms
0..<50 - 5.7s
0..<100 - 20s
ps:当区间为[0,100],耗时简直恐怖。。。
—————————————分割线————————————-
经过多方查找,和自己验证,果断找到了一种办法。
用hash值。
因为每个字符只对应一个hash值。但是swift的这个值和c++或者java又有所不同。他们之间的差值不同。
验证:
1 | 将所有字符都列出来,比较找出最大最小的hash值和对应的字符。 |
结果:
max: I 4799450059485597695
min: _ 4799450059485595649
差值:2046
然后就简单了,之前一直卡在越界问题上1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26func lengthOfLongestSubstring(_ s: String) -> Int {
var last:[Int] = Array.init(repeating: -1, count: 2047)
var start: Int = 0 // 起始位置
var maxLength: Int = 0 // 最大长度
var characters:[String] = []
for char in s {
let string:String = String.init(char)
characters.append(string)
}
for i in 0..<characters.count {
let hash_i: Int = characters[i].hashValue
let hash_a: Int = "_".hashValue
if (last[hash_i - hash_a] >= start) {
maxLength = max(maxLength, i-start)
start = last[hash_i - hash_a] + 1
}
last[hash_i - hash_a] = i
}
maxLength = max(maxLength, s.count - start)
return maxLength
}
奇迹出现:耗时6ms!几千倍的差距。
然而leetcode还是没通过,说我越界了,我特么。。。自己运行没问题啊
然后我申诉了该题目。😏
—————————————分割线————————————-
在做387.字符串中的第一个唯一字符时,我发现了如果用hash值是会越界的,在leetcode上是会这样。那我们可以用ASCII码来搞,因为每一个字符只对应一个ASCII码。
可以参照ASCII码对照表
1 | abcdefghijklmnopqrstuvwxyz 97~122 |
接下来,只要把hashValue换一下就OK了。1
2
3
4
5
6// 所有字符的所对应的ASCII码,用CChar类型表示,实质为Int8类型。
// 该方法末尾会默认加上一个"0"元素,也就是空字符
var allCharacter: [Int8]? =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ".cString(using: String.Encoding.utf8)
print(allCharacter)
print(allCharacter?.count)
1 | func lengthOfLongestSubstring(_ s: String) -> Int { |
后记
这一题和387.字符串中的第一个唯一字符思路大致相同,不太清楚的可以先看一下那题。
1.耗时44
毫秒,超过99.35%
的提交记录,总提交数987
。
这一题总算告一段落了。
大家有疑惑的地方欢迎一起探讨啊。😄