目录
5. Longest Palindromic Substring
10. Regular Expression Matching
5. Longest Palindromic Substring
题目链接:https://leetcode.com/problems/longest-palindromic-substring/
题目思路:
有两种方法。
1.dp的思路,if s[i]=s[j], dp[i][j]=dp[i+1][j-1],max_len=max(max_len,j-i+1).
2.对0-len(s)-1的每个位置,分别按照奇偶的方式遍历,如果左右两端的字符相同,则继续向外扩张。
class Solution(object):
def longestPalindrome1(self, s):
res = ""
for i in xrange(len(s)):
# odd case, like "aba"
tmp = self.helper(s, i, i)
if len(tmp) > len(res):
res = tmp
# even case, like "abba"
tmp = self.helper(s, i, i+1)
if len(tmp) > len(res):
res = tmp
return res
def longestPalindrome(self, s):
n=len(s)
dp=[[0]*n for _ in range(n)]
max_len=0
ans=''
for i in range(n):
dp[i][i]=1
max_len=1
ans=s[i]
res=0
for i in range(n-1):
if s[i]==s[i+1]:
dp[i][i+1]=1
res=2
ans=s[i:i+2]
max_len+2
for j in range(n):
for i in range(j-1):
if dp[i+1][j-1] and s[i]==s[j]:
dp[i][j]=True
if j-i+1>max_len:
max_len=j-i+1
ans=s[i:j+1]
return ans
def helper(self, s, l, r):
while l >= 0 and r < len(s) and s[l] == s[r]:
l -= 1; r += 1
return s[l+1:r]
10. Regular Expression Matching
题目链接:https://leetcode.com/problems/regular-expression-matching/
这个问题主要是正则规则的理解,多submit几次就懂了【滑稽】。
需要关注的判断条件是s[i],p[j]是否相等,p[j+1]是否为‘*’,p[j]是否为'.'。
只有两个字符串都遍历完了的情况,这时可以返回true。
class Solution(object):
def isMatch(self, s, p):
"""
:type s: str
:type p: str
:rtype: bool
"""
l1,l2=len(s),len(p)
def match(i,j):
if i==l1 and j==l2:
return True
elif i<l1 and j==l2:
return False
elif i==l1 and j<l2:
if j+1==l2:
return False
elif p[j+1]=='*':
return match(i,j+2)
else:
return False
if j+1==l2:
if p[j]=='.' or s[i]==p[j]:
return match(i+1,j+1)
else:
return False
if s[i]!=p[j]:
if p[j+1]=='*':
if p[j]=='.':
return match(i,j+2) or match(i+1,j)
else:
return match(i,j+2)
else:
if p[j]=='.':
return match(i+1,1+j)
else:
return False
else:
if p[j+1]=='*':
return match(i+1,j) or match(i,j+2)
else:
return match(i+1,1+j)
return match(0,0)
53. Maximum Subarray
https://leetcode.com/problems/maximum-subarray/
class Solution(object):
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
res=nums[0]
dp=[0]*len(nums)
dp[0]=nums[0]
for i in range(1,len(nums)):
dp[i]=max(dp[i-1]+nums[i],nums[i])
res=max(res,dp[i])
print(dp)
return res
62. Unique Paths
题目链接:https://leetcode.com/problems/unique-paths/
class Solution(object):
def uniquePaths(self, m, n):
"""
:type m: int
:type n: int
:rtype: int
"""
res=[[0]*(1+n) for _ in range(1+m)]
res[1][1]=1
# for i in range(1,m):
# res[i][0]=res[i-1][0]+1
# for i in range(1,n):
# res[0][i]=res[0][i-1]+1
for i in range(1,m+1):
for j in range(1,n+1):
res[i][j]+=res[i][j-1]
res[i][j]+=res[i-1][j]
print(res)
return res[m][n]
63. Unique Paths II
题目链接:https://leetcode.com/problems/unique-paths-ii/
class Solution(object):
def uniquePathsWithObstacles(self, o):
"""
:type obstacleGrid: List[List[int]]
:rtype: int
"""
if o==[[1]]:
return 0
m,n=len(o),len(o[0])
res=[[0]*(n+1) for _ in range(m+1)]
res[1][1]=1
for i in range(1,1+m):
for j in range(1,1+n):
if o[i-1][j-1]:
pass
else:
if o[i-1][j-2] != 1:
res[i][j]+=res[i][j-1]
if o[i-2][j-1] != 1:
res[i][j]+=res[i-1][j]
# print(res)
return res[m][n]
70. Climbing Stairs
题目链接:
设d(x)为金额为x时爬楼梯的方式数目
- 初始条件:d(0)=1,x<0时,d(x)=0。或者是d(1)=1,d(2)=2,x<1时,d(x)=0
- 递归方程:d(x)=d(x-1)+d(x-2)
- 优化方式:将已经计算好的d(x)存起来,防止多次计算同一个值
class Solution(object):
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
a={}
def d(x):
if a.__contains__(x):
return a[x]
res=0
if x==0:
res= 1
elif x<0:
return 0
else:
res= d(x-1)+d(x-2)
a[x]=res
return res
return d(n)
72. Edit Distance
题目链接:https://leetcode.com/problems/edit-distance/
关键是递归关系,因为置换、删除和插入都需要一次,所以递归方程如下:
if word1[i-1]==word2[j-1]:
dp[i][j]=dp[i-1][j-1]
else:
dp[i][j]=1+min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])
class Solution(object):
def minDistance(self, word1, word2):
"""
:type word1: str
:type word2: str
:rtype: int
"""
l1,l2=len(word1),len(word2)
dp=[[0]*(l2+1) for _ in range(l1+1)]
print(dp)
for j in range(1,l2+1):
dp[0][j]=dp[0][j-1]+1
for i in range(1,l1+1):
dp[i][0]=dp[i-1][0]+1
print(dp)
for i in range(1,l1+1):
for j in range(1,l2+1):
if word1[i-1]==word2[j-1]:
dp[i][j]=dp[i-1][j-1]
else:
dp[i][j]=1+min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])
# print(i,j,dp[i][j])
return dp[l1][l2]
78. Subsets
题目链接:https://leetcode.com/problems/subsets/
思路,每次遍历所有元素,对res内里的所有子集都加一下。递归方程是dp[i+1]=[[nums[i]]+j for j in dp[i]]
def subsets(nums):
res = [[]]
for n in nums:
for i in range(len(res)):
res.append(res[i] + [n])
# print(res)
print(res)
115. Distinct Subsequences
题目链接:https://leetcode.com/problems/distinct-subsequences/
题目思路:相当于0/1背包问题,dp(a,b)表示在a里找到b的次数。对a里的元素遍历,如果和b[0]相同,则去除第一个元素,求次数之和。
class Solution(object):
def numDistinct(self, s, t):
"""
:type s: str
:type t: str
:rtype: int
"""
d={}
res=0
def dp(a,b):
if len(a)<len(b):
return 0
elif len(b)==1:
return a.count(b)
elif d.__contains__((a,b)):
return d[(a,b)]
else:
res=0
for i in range(len(a)):
if a[i]!=b[0]:
pass
else:
res+=dp(a[i+1:],b[1:])#+dp(a[i+1:],b)
d[(a,b)]=res
return res
return dp(s,t)
# bbit,bit
120. Triangle
题目链接:https://leetcode.com/problems/triangle/
class Solution(object):
def minimumTotal(self, t):
"""
:type triangle: List[List[int]]
:rtype: int
"""
l=len(t)
res=[[0]*len(t[-1]) for _ in range(l)]
res[-1]=t[-1]
for i in range(l-2,-1,-1):
x=len(t[i])
for j in range(x):
res[i][j]=min(res[i+1][j],res[i+1][j+1])+t[i][j]
# print(res)
return res[0][0]
139. Word Break
题目链接:https://leetcode.com/problems/word-break/
class Solution(object):
def wordBreak(self, s, w):
"""
:type s: str
:type wordDict: List[str]
:rtype: bool
"""
res=False
d={}
if not s:
return False
def dp(t):
if not t:
return True
elif d.__contains__(t):
return d[t]
else:
res=False
for word in w:
if t.startswith(word):
res = res or dp(t[len(word):])
d[t]=res
return res
return dp(s)
140. Word Break II
题目链接:https://leetcode.com/problems/word-break-ii/
题目思路:每次对于当前字符串,搜索元素集合,对于开头是i的字符串,搜索i后面的字符串的组合结果,再拼接在一起。
class Solution(object):
def wordBreak(self, s, w):
"""
:type s: str
:type wordDict: List[str]
:rtype: bool
"""
res=False
d={}
if not s:
return []
def dp(t):
if d.__contains__(t):
return d[t]
else:
res=[]
for word in w:
if t.startswith(word):
if t==word:
res+=[word]
else:
x=dp(t[len(word):])
if x:
for i in x:
res.append(word+' '+i)
d[t]=res
return res
x=dp(s)
# print(d)
return x
198. House Robber
题目链接:https://leetcode.com/problems/house-robber/
class Solution(object):
def rob(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
n=len(nums)
if n==0:
return 0
# elif n==1:
# return 1
d={}
def dp(i):
if i>=n:
return 0
elif d.__contains__(i):
return d[i]
else:
res=max(nums[i]+dp(i+2), dp(i+1))
d[i]=res
return max(nums[i]+dp(i+2), dp(i+1))
return dp(0)
213. House Robber II
题目链接:https://leetcode.com/problems/house-robber-ii/
这里的思路是,从0开始偷,最后一个不能偷,倒数第二个肯定可以偷;如果从1开始偷,那就随意了。所以应该求0-n-2和1-n-1这两段之间偷的最大值。
class Solution(object):
def rob(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
n=len(nums)
if n==0:
return 0
elif n==1:
return nums[0]
elif n==2:
return max(nums)
d={}
def dp(i,l):
if i>=l:
return 0
elif d.__contains__(i):
return d[i]
else:
res=max(nums[i]+dp(i+2,l), dp(i+1,l))
d[i]=res
return res
x=dp(1,n)
d={}
y=dp(0,n-1)
return max(x,y)
221. Maximal Square
题目链接:https://leetcode.com/problems/maximal-square/
这里采用了最直观的方法,类似于求直方图的最大面积。
class Solution(object):
def maximalSquare(self, matrix):
"""
:type matrix: List[List[str]]
:rtype: int
"""
max_len=0
if not matrix:
return 0
m,n=len(matrix),len(matrix[0])
if not n:
return 0
his=[int(i) for i in matrix[-1]]
if 1 in his:
max_len=1
for i in range(m-2,-1,-1):
for j in range(n):
if '1' in matrix[i]:
max_len=max(max_len,1)
his[j]+=int(matrix[i][j])
his[j]*=int(matrix[i][j])
# print(his)
for j in range(n):
if his[j]<=1:
continue
min_len=1
for k in range(j+1,n):
if his[k]<=1:
break
else:
min_len=min(his[j:k+1])
# print(min_len)
if k-j+1>min_len:
min_len=k-j
break
min_len=min(min_len,k-j+1)
max_len=max(max_len,min_len)
return max_len*max_len
279. Perfect Squares
题目链接:https://leetcode.com/problems/perfect-squares/
题目思路:如果i本身就是平方数,则返回1;否则,从最大int(sqrt(i))开始遍历,寻找最短的步数。
import math
class Solution(object):
def numSquares(self, n):
"""
:type n: int
:rtype: int
"""
d={8:2,4:1,9:1,1:1,2:2,3:3,16:1}
def dfs(i):
if d.__contains__(i):
return d[i]
a=math.sqrt(i)
if int(a)==a:
d[i]=1
return 1
res=i
for j in range(int(a),1,-1):
t=dfs(i-j*j)
res=min(res,t+1)
d[i]=res
return res
return dfs(n)
322. Coin Change
题目链接:https://leetcode.com/problems/coin-change/
和第70题思路一样。
class Solution(object):
def coinChange(self, coins, amount):
"""
:type coins: List[int]
:type amount: int
:rtype: int
"""
t={}
def g(a):
if t.__contains__(a):
return t[a]
elif a==0:
return 0
elif a<0:
return -1
else:
c=[g(a-i) for i in coins if g(a-i)>=0]
if c==[]:
res = -1
else:
res=min(c)+1
t[a]=res
return res
return g(amount)
337. House Robber III
思路,dfs遍历所有节点,每个节点返回两个值(a,b):a是经过当前节点往下的最大值,b是不经过当前节点往下的最大值路径。则每个节点的值a等于当前的节点值+左右子节点b之和,每个节点的值b等于左右子节点的max(a,b)之和。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def rob(self, root):
"""
:type root: TreeNode
:rtype: int
"""
d={}
def dfs(node):
if not node:
return 0, 0
x,y=dfs(node.left),dfs(node.right)
# print(node.val,node.val+x[1]+y[1],x[0]+y[0])
return node.val+x[1]+y[1],max(x)+max(y)
return max(dfs(root))
338. Counting Bits
题目链接:https://leetcode.com/problems/counting-bits/
思路是每个数是前一个数+1的结果,看看发生了几次进位。
递归关系如下:如果0次进位,那么说明最后一位是0,1的个数直接+1;如果1次进位,那么1的个数不变;如果是k次进位,那么减少了k个1,增加了一个1,总共减少了k-1个1。
class Solution(object):
def countBits(self, num):
"""
:type num: int
:rtype: List[int]
"""
def get_flag(a,b):
cnt=0
while b!=0:
sum=a^b
flag=(a&b)<<1
a=sum
b=flag
cnt+=1
return cnt-1
if num==0:
return [0]
res=[0,1]
for i in range(1,num):
flag = get_flag(i,1)
if flag==0:
res.append(res[-1]+1)
elif flag==1:
res.append(res[-1])
else:
res.append(res[-1]-flag+1)
return res
343. Integer Break
题目链接:https://leetcode.com/problems/integer-break/
class Solution(object):
def integerBreak(self, n):
"""
:type n: int
:rtype: int
"""
d={2:1,3:2}
def dfs(i):
if d.__contains__(i):
return d[i]
res=0
for j in range(1,i):
res=max(res,j*dfs(i-j),j*(i-j))
d[i]=res
return res
return dfs(n)
377. Combination Sum IV
题目链接:https://leetcode.com/problems/combination-sum-iv/
class Solution(object):
def combinationSum4(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
d={}
def dp(x):
if x==0:
return 1
elif d.__contains__(x):
return d[x]
else:
res=0
for i in nums:
if x>=i:
res+=dp(x-i)
d[x]=res
return res
return dp(target)
474. Ones and Zeroes
题目链接:https://leetcode.com/problems/ones-and-zeroes/
典型0-1背包问题,没啥好说的,注意迭代公式即可。
class Solution(object):
def findMaxForm(self, strs, m, n):
"""
:type strs: List[str]
:type m: int
:type n: int
:rtype: int
"""
# strs=list(set(strs))
d={i:[strs[i].count('0'),strs[i].count('1')] for i in range(len(strs))}
# print(d)
a=[[[0 for _ in range(len(strs)+1)] for _ in range(n+1)] for _ in range(m+1)]
for i in range(1,len(strs)+1):
for x in range(1+m):
for y in range(1+n):
if x-d[i-1][0]<0 or y-d[i-1][1]<0:
a[x][y][i]=a[x][y][i-1]
else:
a[x][y][i]=max(a[x-d[i-1][0]][y-d[i-1][1]][i-1]+1,a[x][y][i-1])
# print(x,y,i,a[x][y][i])
return a[m][n][-1]
494. Target Sum
题目链接:https://leetcode.com/problems/target-sum/
class Solution(object):
def findTargetSumWays(self, nums, S):
"""
:type nums: List[int]
:type S: int
:rtype: int
"""
n=len(nums)
d={}
def dfs(i,su):
if i==n:
if su==0:
return 1
else:
return 0
elif d.__contains__((i,su)):
return d[(i,su)]
else:
res=dfs(i+1,su-nums[i])+dfs(i+1,su+nums[i])
d[(i,su)]=res
return res
return dfs(0,S)
523. Continuous Subarray Sum
题目链接:https://leetcode.com/problems/continuous-subarray-sum/
如果sum(a[i:j])%k==0,sum(a[:i])%k==sum(a[:j])%k,在mod k情况下,sum值是相同的。
class Solution():
def checkSubarraySum(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: bool
"""
dic = {0:-1}
summ = 0
for i, n in enumerate(nums):
if k != 0:
summ = (summ + n) % k
else:
summ += n
if summ not in dic:
dic[summ] = i
else:
if i - dic[summ] >= 2:
return True
return False
576. Out of Boundary Paths
题目链接:https://leetcode.com/problems/out-of-boundary-paths/
class Solution(object):
def findPaths(self, m, n, N, i, j):
"""
:type m: int
:type n: int
:type N: int
:type i: int
:type j: int
:rtype: int
"""
Max=1e9+7
def out_of_box(x,y):
if 0<=x<m and 0<=y<n:
return False
return True
d={}
def dfs(i,j,times):
s=[(1,0),(-1,0),(0,1),(0,-1)]
if out_of_box(i,j):
if times==0:
return 1
return -1
elif times==0:
return -1
elif d.__contains__((i,j,times)):
return d[(i,j,times)]
res=0
for step in s:
x,y=i+step[0],j+step[1]
t=dfs(x,y,times-1)
if t!=-1:
res+=t
if res==0:
d[(i,j,times)]= -1
else:
d[(i,j,times)]=int(res%Max)
return d[(i,j,times)]
res=0
for t in range(1,N+1):
x=dfs(i,j,t)
if x>0:
res+=x
return int(res%Max)
647. Palindromic Substrings
题目链接:https://leetcode.com/problems/palindromic-substrings/
class Solution(object):
def countSubstrings(self, s):
res = 0
for i in xrange(len(s)):
# odd case, like "aba"
tmp = self.helper(s, i, i)
res+=tmp
# even case, like "abba"
tmp = self.helper(s, i, i+1)
res+=tmp
return res
def helper(self, s, l, r):
res=0
while l >= 0 and r < len(s) and s[l] == s[r]:
res+=1
l -= 1; r += 1
return res
最大和子矩阵
问题描述:求一个二维矩阵里所有元素之和最大的子矩阵。
例如,以下矩阵中最大和的子矩阵是红框内的。
思路:可以每次求出第i到j行的每列元素之和,这样就可以转化成最大连续子数组之和的问题。时间复杂度为O(n^2)
def max_sum_matrix():
a=[[1,0,-7,6],[1,-4,3,0],[-1,2,-7,9],[2,0,4,-3]]
n = len(a)
tmp=[[0]*n for _ in range(n)]
tmp[0] = a[0]
for i in range(1, n):
for j in range(n):
tmp[i][j] = tmp[i-1][j] + a[i][j]
s=[0]*n
res=-1e9
for i in range(n):
for j in range(i+1, n):
cur = -1e9
for k in range(n):
if i == 0:
s[k] = tmp[j][k]
else:
s[k] = tmp[j][k] - tmp[i-1][k]
for k in range(n):
cur = max(s[k]+cur, s[k])
res=max(res, cur)
print(s, cur, res)
print(res)