2. 两数相加
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
result = cur = ListNode(0)
carry = 0
while l1 or l2:
x = l1.val if l1 else 0
y = l2.val if l2 else 0
carry, mod = divmod(carry + x + y, 10)
cur.next = ListNode(mod)
cur = cur.next
if l1: l1 = l1.next
if l2: l2 = l2.next
if carry: cur.next = ListNode(1)
return result.next
3. 无重复字符的最长子串
暴力法:O(n^3)
滑动窗口: O(n), 通过使用 HashSet 作为滑动窗口,我们可以用O(1)的时间来完成对字符是否在当前的子字符串中的检查。滑动窗口是数组/字符串问题中常用的抽象概念。 窗口通常是在数组/字符串中由开始和结束索引定义的一系列元素的集合,即 [i,j)(左闭,右开)。而滑动窗口是可以将两个边界向某一方向“滑动”的窗口。例如,我们将 [i,j)向右滑动 11 个元素,则它将变为 [i+1,j+1)(左闭,右开)。
回到我们的问题,我们使用 HashSet 将字符存储在当前窗口 [i,j)最初 (j=i)中。 然后我们向右侧滑动索引 j,如果它不在 HashSet 中,我们会继续滑动 j。直到 s[j] 已经存在于 HashSet 中。此时,我们找到的没有重复字符的最长子字符串将会以索引 i 开头。如果我们对所有的 i 这样做,就可以得到答案。
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
st = {}
i, ans = 0, 0 # i 是开始位置
for j in range(len(s)):
if s[j] in st:
i = max(st[s[j]], i) # 原来开始的位置和s[j]重复的位置,取大的那个
ans = max(ans, j - i + 1)
st[s[j]] = j + 1 # 更新当前字符在 hashset 中存储的位置,hashset 存储了一个窗口中字符的位置
return ans;
5. 最长回文子串
可以用动态规划
但更优的是中心扩展算法,回文可以从它的中心展开,并且只有 2n−1 个这样的中心。
class Solution:
def longestPalindrome(self, s: str) -> str:
if not s: return ""
start = end = 0
for i in range(len(s)):
len1 = self.expand_around_center(s, i, i)
len2 = self.expand_around_center(s, i, i + 1)
m_len = max(len1, len2)
if m_len > end - start:
start = i - (m_len - 1) // 2
end = i + m_len // 2
return s[start:end + 1]
def expand_around_center(self, s, left, right):
L, R = left, right
while L >= 0 and R < len(s) and s[L] == s[R]:
L -= 1
R += 1
return R - L -1