震惊!某985高校的人leetcode做不出来,男默女泪。

LEETCODE DAY1

今天,练了一个题,题目不难,但是很多人写不出来,有大佬几行写完了,我也写不出来,所以我有必要写篇博客。

题目:1371. 每个元音包含偶数次的最长子字符串

这是我第一次写 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()方法提供了一种方式,在一行中完成这件事。传递给该方法的第一个参数,是要检查的键。第二个参数,是如果该键不存在时要设置的值。如果该键确实存在,方法就会返回键的值。

你可能感兴趣的:(leetcode)