這道題主要用到思路是:滑動窗口
什麼是滑動窗口?
其實就是一個隊列,比如例題中的 abcabcbb,進入這個隊列(窗口)爲 abc 滿足題目要求,當再進入 a,隊列變成了 abca,這時候不滿足要求。所以,我們要移動這個隊列!
如何移動?我們只要把隊列的左邊的元素移出就行了,直到滿足題目要求!一直維持這樣的隊列,找出隊列出現最長的長度時候,求出解!
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
left = 0
max_len = 0 #當取最大時,一定會設置兩個變量,當前值和當前最大值
cur_len = 0
lookup = set() #建立集合,如果集合內已有該元素,元素個數不變(並集)add添加,刪除用remove
s_len = len(s)
for i in range(s_len):
cur_len += 1
while s[i] in lookup:
lookup.remove(s[left])
left += 1
cur_len -= 1
if cur_len > max_len: max_len = cur_len
lookup.add(s[i])
return max_len
這位大佬寫的很棒,尤其是動態規劃法,但針對這題最好的方法還是中心擴散法。
我分別用暴力法,動態規劃和中心擴散法,代碼如下:
#暴力法 這篇文章是爲中級讀者而寫的。它介紹了迴文,動態規劃以及字符串處理。請確保你理解什麼是迴文。迴文是一個正讀和反讀都相同的字符串,例如,“aba” 是迴文
# class Solution:
# def longestPalindrome(self, s: str) -> str:
# if s==s[::-1]:
# return s
# max_len = 1
# res = s[0]
# for i in range(len(s) - 1):
# for j in range(i + 1, len(s)):
# if j - i + 1 > max_len and s[i:j+1] == s[i:j+1][::-1]:
# max_len = j - i + 1
# res = s[i:j + 1]
# return res
#時間複雜度:O(n^2),往往利用python的切片可以很好的縮減複雜度
#動態規劃方法
# class Solution:
# def longestPalindrome(self, s: str) -> str:
# #特例
# size = len(s)
# if len(s) < 2:
# return s
# start = 0
# max_len = 1
# #定義狀態
# dp = [[False for _ in range(size)] for _ in range(size)]
# #初始化
# for i in range(size):
# dp[i][i] = True
# #狀態轉移
# for j in range(1, size):
# for i in range(0, j):
# if s[i] == s[j]:
# if j - i < 3: #aba,cdc都是true
# dp[i][j] = True
# else:
# dp[i][j] = dp[i+1][j-1]
# else:
# dp[i][j] = False
# if dp[i][j] == True:
# cur_len = j - i + 1
# if cur_len > max_len:
# start = i
# max_len = cur_len
# # print(max_len)
# return s[start:start + max_len]
#中心擴散法 時間複雜度爲o(n2),空間複雜度爲o(n1)
class Solution:
def longestPalindrome(self, s: str) -> str:
def center_spread(s, size, left, right):
i = left
j = right
while i >= 0 and j < size and s[i] == s[j]:
i -= 1
j += 1
return s[i+1: j], j - i - 1
max_len = 1
size = len(s)
if size < 2:
return s
res = s[0] #注意這個位置要放在判斷之後,如果放在之前會報錯,eg當s=''時,不存在s[0]
for i in range(size):
odd_str, odd_len = center_spread(s, size, i, i)
even_str, even_len = center_spread(s, size, i, i+1)
cur_max_str = odd_str if odd_len > even_len else even_str
if len(cur_max_str) > max_len:
max_len = len(cur_max_str)
res = cur_max_str
return res
#參考鏈接https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zhong-xin-kuo-san-dong-tai-gui-hua-by-liweiwei1419/
掌握方法:https://leetcode-cn.com/problems/zigzag-conversion/solution/zzi-xing-bian-huan-by-jyd/
思路:
#按着z的方向,每次都是第一行到最後一行,然後從最後一行到第一行,再轉向,因此我們定義轉向flag,res存每行的字符,最後在用join連接起來。
class Solution:
def convert(self, s: str, numRows: int) -> str:
if numRows < 2:
return s
res = ['' for _ in range(numRows)]
i, flag = 0, -1
for c in s:
res[i] += c
if i == 0 or i == numRows - 1:flag = -flag
i += flag
return ''.join(res)