01 5. 最长回文子串:
https://leetcode-cn.com/problems/longest-palindromic-substring/
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
class Solution:
def longestPalindrome(self, s: str) -> str:
if s == '':
return ''
if len(s) == 1:
return s
if len(s) == 2:
return s if s[0] == s[1] else s[0]
res = s[0]
for i in range(len(s)):
pos = [i ,i ]
while pos[0] >= 0 and pos[1] < len(s) and s[pos[0]] == s[pos[1]]:
if len(res) < len(s[pos[0]:pos[1]+1]):
res = s[pos[0]:pos[1]+1]
pos[0] -= 1
pos[1] += 1
pos = [i ,i + 1]
while pos[0] >= 0 and pos[1] < len(s) and s[pos[0]] == s[pos[1]]:
if len(res) < len(s[pos[0]:pos[1]+1]):
res = s[pos[0]:pos[1]+1]
pos[0] -= 1
pos[1] += 1
return res
从前到后依次循环,每次循环以当前字符s[i]为中心,或以s[i],s[i+1]为中心向两边拓展,每次拓展比较首尾两字符是否相同。时间复杂度为O(n^2)
02 72. 编辑距离:
https://leetcode-cn.com/problems/edit-distance/
给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
插入一个字符
删除一个字符
替换一个字符
class Solution:
def minDistance(self, word1, word2):
"""
:type word1: str
:type word2: str
:rtype: int
"""
n = len(word1)
m = len(word2)
# 有一个字符串为空串
if n * m == 0:
return n + m
# DP 数组
D = [ [0] * (m + 1) for _ in range(n + 1)]
# 边界状态初始化
for i in range(n + 1):
D[i][0] = i
for j in range(m + 1):
D[0][j] = j
# 计算所有 DP 值
for i in range(1, n + 1):
for j in range(1, m + 1):
left = D[i - 1][j] + 1
down = D[i][j - 1] + 1
left_down = D[i - 1][j - 1]
if word1[i - 1] != word2[j - 1]:
left_down += 1
D[i][j] = min(left, down, left_down)
return D[n][m]
本质不同的操作实际上只有三种:
在单词 A 中插入一个字符;
在单词 B 中插入一个字符;
修改单词 A 的一个字符。
可以写出如下的状态转移方程:
若 A 和 B 的最后一个字母相同:
\begin{aligned} D[i][j] &= \min(D[i][j - 1] + 1, D[i - 1][j]+1, D[i - 1][j - 1])\ &= 1 + \min(D[i][j - 1], D[i - 1][j], D[i - 1][j - 1] - 1) \end{aligned}
\begin{aligned} D[i][j]
=min(D[i][j−1]+1,D[i−1][j]+1,D[i−1][j−1])
=1+min(D[i][j−1],D[i−1][j],D[i−1][j−1]−1)\end{aligned}
若 A 和 B 的最后一个字母不同:
\begin{aligned} D[i][j] = 1 + \min(D[i][j - 1], D[i - 1][j], D[i - 1][j - 1])
D[i][j]=1+min(D[i][j−1],D[i−1][j],D[i−1][j−1])\end{aligned}
03 198. 打家劫舍:
https://leetcode-cn.com/problems/house-robber/
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
class Solution:
def rob(self, nums: List[int]) -> int:
if not nums:
return 0
yes = nums[0]
no = 0
for i in range(1,len(nums)):
yes,no = no + nums[i],max([yes,no])
return max([yes,no])
时间复杂度O(N),从第一家开始,每一家都是抢或不抢两种选择,如果第n家选择抢,那么最大的金额就是第n家金额+第n-1家不抢的金额,如果不抢第n家,金额为第n-1家抢或不抢金额中最大的那个
04 213. 打家劫舍 II:
https://leetcode-cn.com/problems/house-robber-ii
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。
class Solution:
def rob(self, nums: List[int]) -> int:
if not nums:
return 0
if len(nums) == 1:
return nums[0]
yes1 = nums[0]
no1 = 0
yes = nums[1]
no = 0
for i in range(1,len(nums) - 1):
yes1,no1 = nums[i] + no1,max([yes1,no1])
yes,no = nums[i+1]+no,max(yes,no)
return max([yes1,no1,yes,no])
和上一题类似,需要分两种情况,第一种是不抢第一家的最大值,第二种是不抢最后一家的最大值,然后这两个结果再取最大值为最终结果,时间复杂度O(N)
05 516. 最长回文子序列:
https://leetcode-cn.com/problems/longest-palindromic-subsequence/
给定一个字符串 s ,找到其中最长的回文子序列,并返回该序列的长度。可以假设 s 的最大长度为 1000 。
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
if not s:
return 0
res =[ [0]*len(s) for _ in range(len(s))]
for i in range(len(s)):
res[i][i] = 1
for i in range(len(s)-1,-1,-1):
for j in range(i+1,len(s)):
if s[i] == s[j]:
res[i][j] = res[i+1][j-1] + 2
else:
res[i][j] = max([res[i][j-1],res[i+1][j]])
return res[0][len(s)-1]
用一个len(s)*len(s)的矩阵res存储最长回文子序列长度,res[i][j]表示字符串s[i:j+1]的最长回文子序列,若s[i]==s[j],则res[i][j] = res[i+1][j-1] + 2,否则res[i][j] = max([res[i][j-1],res[i+1][j]]),时间复杂度为O(n)
06 674. 最长连续递增序列:
https://leetcode-cn.com/problems/longest-continuous-increasing-subsequence/
给定一个未经排序的整数数组,找到最长且连续的的递增序列,并返回该序列的长度
class Solution:
def findLengthOfLCIS(self, nums: List[int]) -> int:
if not nums:
return 0
res = 1
curr = 1
for i in range(1,len(nums)):
if nums[i] > nums[i-1]:
curr += 1
else:
curr = 1
res = max([res,curr])
return res
从前往后依次判断相邻两个数大小,若递增,则计数加1,若不递增,计数置1,每次记录递增计数的最大值,时间复杂度为O(n)