给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。
解:用滑动窗口法,i代表左界,j代表右界。先增加j直到[i,j]中包含t中所有元素,再让i缩小,去除不在T中的元素,此时i只想T中的某个元素ss,向右移动j找到ss,再向右移动i,找到新的在T中的元素,记录长度,一直循环,直到j到达右端。
class Solution:
def minWindow(self, s: str, t: str) -> str:
n=len(s)
m=len(t)
if n<m:
return ""
adict={
}
for ss in t:
if ss in adict.keys():
adict[ss]+=1
else:
adict[ss]=1
need=m
left=0
right=n-1
find=False
i=0
for j in range(n):
if s[j] in t:
if adict[s[j]]>0:
need=need-1
adict[s[j]]-=1
if need==0:
find=True
while True:
if s[i] not in t:
i=i+1
elif adict[s[i]]<0:
adict[s[i]]=adict[s[i]]+1
i=i+1
else:
if j-i<right-left:
left=i
right=j
break
need=need+1
adict[s[i]]+=1
i=i+1
if not find:
return ""
else:
return s[left:right+1]
执行用时:96 ms, 在所有 Python3 提交中击败了87.83%的用户
内存消耗:13.7 MB, 在所有 Python3 提交中击败了87.76%的用户
给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
解:这道题最先想到的方法就是动态规划,按第n个数是否在组合中区分,如果不在就是dp[n-1][k],如果是就是dp[n-1][k-1]中的元素再加上n
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
if k==0:
return []
if n<k:
return []
if n==k:
return [[i for i in range(1,n+1)]]
if k==1:
return [[i] for i in range(1,n+1)]
ans1=self.combine(n-1,k-1)
if ans1:
for i in range(len(ans1)):
ans1[i]=ans1[i]+[n]
ans2=self.combine(n-1,k)
ans=ans1 + ans2
ans.sort()
return ans
执行用时:56 ms, 在所有 Python3 提交中击败了88.27%的用户
内存消耗:15.1 MB在所有 Python3 提交中击败了29.79%的用户
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
解法一:用上一道题中的函数,遍历
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
ans=[[],nums]
n=len(nums)
if not nums:
return [[]]
if n<2:
return ans
for i in range(1,n):
curList=self.combine(n,i,nums)
ans=ans+curList
return ans
def combine(self, n: int, k: int,nums:List[int]) -> List[List[int]]:
if k==0:
return []
if n<k:
return []
if n==k:
return [[nums[i] for i in range(n)]]
if k==1:
return [[nums[i]] for i in range(n)]
ans1=self.combine(n-1,k-1,nums)
if ans1:
for i in range(len(ans1)):
ans1[i]=ans1[i]+[nums[n-1]]
ans2=self.combine(n-1,k,nums)
ans=ans1 + ans2
ans.sort()
return ans
执行用时:40 ms, 在所有 Python3 提交中击败了73.06%的用户
内存消耗:13.8 MB, 在所有 Python3 提交中击败了27.42%的用户
速度也不慢。
解法二:回溯法
还是一层一层的遍历,不论选还是不选这一层的元素,下一次都自动到下一层执行。
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
n=len(nums)
if not nums:
return [[]]
if n<2:
return [[],nums]
self.ans=[]
self.backtrack([],0,nums)
return self.ans
def backtrack(self,curList,depth,nums):
if depth==len(nums):
self.ans.append(curList[:])
return
self.backtrack(curList,depth+1,nums)#不选nums[depth]
self.backtrack(curList+[nums[depth]],depth+1,nums)#选nums[depth]
执行用时:36 ms, 在所有 Python3 提交中击败了89.94%的用户
内存消耗:13.9 MB, 在所有 Python3 提交中击败了16.16%的用户
不像动态规划一样浪费。
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
解:
用dfs搜索
class Solution:
def exist(self, board: List[List[str]], word: str) -> bool:
m=len(board)
n=len(board[0])
k=len(word)
def dfs(i,j,depth,board,k,word,lists,m,n):
if self.find:
return
if board[i][j]==word[depth]:
lists[i][j]=1
if depth+1==k:
self.find=True
return
if j+1<n and lists[i][j+1]==0:
dfs(i,j+1,depth+1,board,k,word,lists,m,n)
if i+1<m and lists[i+1][j]==0:
dfs(i+1,j,depth+1,board,k,word,lists,m,n)
if j>0 and lists[i][j-1]==0:
dfs(i,j-1,depth+1,board,k,word,lists,m,n)
if i>0 and lists[i-1][j]==0:
dfs(i-1,j,depth+1,board,k,word,lists,m,n)
lists[i][j]=0
else:
return
self.find=False
for i in range(m):
for j in range(n):
if board[i][j]==word[0]:
lists=[[0 for _ in range(n)] for _ in range(m)]
dfs(i,j,0,board,k,word,lists,m,n)
if self.find:
return True
if not self.find:
return False
执行用时:568 ms, 在所有 Python3 提交中击败了5.45%的用户
内存消耗:14.9 MB, 在所有 Python3 提交中击败了45.33%的用户
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成
解:双指针,一个指针定位在已经排好的数字位置加1,另一个指针遍历数组,记录上一个元素和上一个元素的重复次数count,如果大于2则j+1,否则换到i位置,i+1,j+1,如果与last不相等,则count=1,last=nums[j],再把j和i的位置互换。最后返回i
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
count=1
n=len(nums)
if n<3 or not nums:
return n
last=nums[0]
i=1
for j in range(1,n):
if nums[j]==last:
count=count+1
if count>2:
continue
else:
if i!=j:
nums[i],nums[j]=nums[j],nums[i]
i=i+1
else:
last=nums[j]
count=1
if i!=j:
nums[i],nums[j]=nums[j],nums[i]
i=i+1
return i
执行用时:40 ms, 在所有 Python3 提交中击败了85.70%的用户
内存消耗:13.6 MB, 在所有 Python3 提交中击败了84.72%的用户