今天,练了一个题,题目不难,但是很多人写不出来,有大佬几行写完了,我也写不出来,所以我有必要写篇博客。
这是我第一次写 leetcode 我不太懂,就吧一些变量放到了类的外面,一直编译不过,难受。后来,我发现了这个问题,但是还是过不了,原因是超时了,ojs 给了一个很长很长长得突破天际得一串字符,然后我那可怜的O(n^2)算法就慢出银河系了。
times = {
'a': 1,
'e': 1,
'i': 1,
'o': 1,
'u': 1
};
yuanyin = "aeiou"
class Solution(object):
def findTheLongestSubstring(self, s):
lenth = len(s)
li = []
for i in range(lenth):
li.append([])
for j in range(lenth):
if s[j] in yuanyin:
times[s[j]] *= -1
for value in times.values():
li[j].append(value)
maxN = 0
N = 0
li.insert(0, [1, 1, 1, 1, 1])
le = len(li)
for k in range(le):
for l in range(le):
if li[k] == li[l]:
N = l - k
if N > maxN:
maxN = N
return maxN
s = input('S: ')
Word = Solution()
num = Word.findTheLongestSubstring(s)
print(num)
因为字符串的每个位置的元音奇偶可能只有32种,朋友告诉我可以用一个表来哈希一下要快的多。我就弄了就
(当然表还是用另一个程序生成的,手写太累了)
class Solution(object):
def findTheLongestSubstring(self, s):
yuanyin = "aeiou"
biao = {
(1, 1, 1, 1, 1) :[-1, -1],
(-1, 1, 1, 1, 1) :[-1, -1],
(1, -1, 1, 1, 1) :[-1, -1],
(-1, -1, 1, 1, 1) :[-1, -1],
(1, 1, -1, 1, 1) :[-1, -1],
(-1, 1, -1, 1, 1) :[-1, -1],
(1, -1, -1, 1, 1) :[-1, -1],
(-1, -1, -1, 1, 1) :[-1, -1],
(1, 1, 1, -1, 1) :[-1, -1],
(-1, 1, 1, -1, 1) :[-1, -1],
(1, -1, 1, -1, 1) :[-1, -1],
(-1, -1, 1, -1, 1) :[-1, -1],
(1, 1, -1, -1, 1) :[-1, -1],
(-1, 1, -1, -1, 1) :[-1, -1],
(1, -1, -1, -1, 1) :[-1, -1],
(-1, -1, -1, -1, 1) :[-1, -1],
(1, 1, 1, 1, -1) :[-1, -1],
(-1, 1, 1, 1, -1) :[-1, -1],
(1, -1, 1, 1, -1) :[-1, -1],
(-1, -1, 1, 1, -1) :[-1, -1],
(1, 1, -1, 1, -1) :[-1, -1],
(-1, 1, -1, 1, -1) :[-1, -1],
(1, -1, -1, 1, -1) :[-1, -1],
(-1, -1, -1, 1, -1) :[-1, -1],
(1, 1, 1, -1, -1) :[-1, -1],
(-1, 1, 1, -1, -1) :[-1, -1],
(1, -1, 1, -1, -1) :[-1, -1],
(-1, -1, 1, -1, -1) :[-1, -1],
(1, 1, -1, -1, -1) :[-1, -1],
(-1, 1, -1, -1, -1) :[-1, -1],
(1, -1, -1, -1, -1) :[-1, -1],
(-1, -1, -1, -1, -1) :[-1, -1]
}
times = {
'a': 1,
'e': 1,
'i': 1,
'o': 1,
'u': 1
}
lenth = len(s)
for j in range(lenth):
li = []
if s[j] in yuanyin:
times[s[j]] *= -1
for value in times.values():
li.append(value)
li = tuple(li)
if biao[li][0] == -1 and li != (1, 1, 1, 1, 1):
biao[li][0] = j
else:
biao[li][1] = j
maxN = 0
N = 0
for value in biao.values():
N = value[1] - value[0]
if N > maxN:
maxN = N
return maxN
s = input('S: ')
Word = Solution()
num = Word.findTheLongestSubstring(s)
print(num)
其中我觉得最大的问题,一个细节就是处理 key(1, 1, 1, 1, 1) 了,这个情况是当扫描带移动到该字符串时,包括该字符和该字符前的a, e, i, o, u的奇偶,1代表偶,-1代表奇。所以我们需要保持(1, 1, 1, 1, 1)的value[0] = -1,-1既是扫描带还未扫描到第0个字符时(不理解可以自己举例子想想)。
写完后提交了,过了。
看看官方的答案:
思路相似,但代码的简洁程度就大不一样了。
用了状态压缩,将11111->31……
class Solution {
public:
int findTheLongestSubstring(string s) {
int ans = 0, status = 0, n = s.length();
vector<int> pos(1 << 5, -1);
pos[0] = 0;
for (int i = 0; i < n; ++i) {
if (s[i] == 'a') {
status ^= 1<<0;
} else if (s[i] == 'e') {
status ^= 1<<1;
} else if (s[i] == 'i') {
status ^= 1<<2;
} else if (s[i] == 'o') {
status ^= 1<<3;
} else if (s[i] == 'u') {
status ^= 1<<4;
}
if (~pos[status]) {
ans = max(ans, i + 1 - pos[status]);
} else {
pos[status] = i + 1;
}
}
return ans;
}
};
开始看代码的时候看不懂,位运算没学好,很多细节不清楚&(且)、|(或)、^(异或)、~(取反),其中最迷惑的是~pos[status],最后推理得出是取第一位。是正数的化第一位是0,取反就为1了。
某大lao
class Solution:
def findTheLongestSubstring(self, s: str) -> int:
D = {"a": 1, "e": 2, "i": 4, "o": 8, "u": 16}
L = {0: 0}
m = t = 0
for i, c in enumerate(s, 1): # i从下标1开始
t ^= D.get(c, 0) #没有键返回0
m = max(m, i - L.setdefault(t, i))
return m
for 循环使用 enumerate
>>>seq = ['one', 'two', 'three']
>>> for i, element in enumerate(seq):
... print i, element
...
0 one
1 two
2 three
setdefault()方法提供了一种方式,在一行中完成这件事。传递给该方法的第一个参数,是要检查的键。第二个参数,是如果该键不存在时要设置的值。如果该键确实存在,方法就会返回键的值。