Problem 30 字符查找题
一开始的想法是将words进行全排列,再找s里面的匹配,但是由于全排列n!运算,耗时过长。
于是改由在s里面找到words里面的词,接下来就继续配对,配对一个words的词就remove,知道words为空。耗时1400ms, 勉强通过,但是内存占用较大。
class Solution:
def findSubstring(self, s: 'str', words: 'List[str]') -> 'List[int]':
count=len(words)
if len(s)==0 or count==0:
return []
lens=len(words[0])
if len(s)<count*lens:
return []
index=[]
for i in range(len(s)-count*lens+1):
j=i
temp=words.copy()
while s[j:j+lens] in temp:
temp.remove(s[j:j+lens])
j+=lens
if temp==[]:
index.append(i)
return index
Problem 31 字典排序题
看了solution的启示写的,升序的空间来源于非降序的排列,也就是97521没有空间升序了,因此只要找到a[i]>a[i-1],便可进行升序,最邻近的升序排列需要一次交换以及逆序。设立哨兵对应321的情况。
class Solution:
def swap(self,num,i,j):
temp=num[i]
num[i]=num[j]
num[j]=temp
return num
def reverse(self,num,i):
num[i:len(num)]=num[i:len(num)][::-1]
return num
def nextPermutation(self, num: 'List[int]') -> 'None':
"""
Do not return anything, modify nums in-place instead.
"""
army=0
for i in range(len(num)-1,0,-1):
if num[i]>num[i-1]:
army=1
dis=num[i]-num[i-1]
k=i
for j in range(i,len(num),1):
if num[j]-num[i-1]<=dis and num[j]-num[i-1]>0:
dis=num[j]-num[i-1]
k=j
self.swap(num,i-1,k)
self.reverse(num,i)
break
if len(num)==1 or army==0:
self.reverse(num,0)
Problem 32 Longest Valid Parentheses 字符匹配题
solution的做法,用栈,初始化为-1.遍历s,若为“(”,则将index压入栈等待配对,否则删除栈最近的元素(即完成配对)。连续距离即为当前位置到未匹配字符的坐标距离。
class Solution:
def max(self,a,b):
if a>=b:
return a
else:
return b
def longestValidParentheses(self, s: str) -> int:
max_length=0
stack=[-1]
for i in range(len(s)):
if s[i]=='(':
stack.append(i)
else:
stack.pop()
if len(stack)==0:
stack.append(i)
else:
max_length=self.max(max_length,i-stack[-1])
return max_length
Problem33 Search in Rotated Sorted Array
由于nums由排序数列折叠,可根据0位数判断搜索方向,减少搜索长度。
class Solution:
def search(self, nums: List[int], target: int) -> int:
if len(nums)==0:
return -1
if target<nums[0]:
for i in range(len(nums)-1,-1,-1):
if nums[i]==target:
return i
elif nums[i]<nums[i-1]:
return -1
else:
for i in range(len(nums)):
if nums[i]==target:
return i
elif nums[i]<nums[0]:
return -1
Problem34 Find First and Last Position of Element in Sorted Array
主要用两小段遍历查找first和last,首先由左到右遍历nums,第一个等于target的index返回存为first,跳出循环,否则不存在匹配target,返回[-1,-1]。第二次遍历从first右边开始,第一个不等于target的index-1存为last。
class Solution(object):
def searchRange(self, nums, target):
first, last = 0, 0
i, j = 0, 0
for i in range(len(nums)):
if nums[i] == target:
first = i
break
else:
return [-1, -1]
for j in range(i+1, len(nums)):
if nums[j] != target:
return [i, j-1]
return [i, j or i]
Problem 35:Search Insert Position
查找插入数字的位置,目标序列已排序,因此用最直接的做法,就是找到大于等于target的位置,O(n)复杂度
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
if len(nums)==0:
return 0
for i in range(len(nums)):
if nums[i]>=target:
return i
else:
return len(nums)
Problem 36: Valid Sudoku
建立99 行、列、九格矩阵,用于遍历board时存储各行、列、九格内的数字分布情况,当有数字发生重复时返回false。
一开始用[None9]*9初始化,但是发现创建的后面八行实际上是对第一行的复制,所以会跟随前面的赋值行为。
class Solution:
def isValidSudoku(self, board: List[List[str]]) -> bool:
rows = [[0 for i in range(9)] for j in range(9)]
cols = [[0 for i in range(9)] for j in range(9)]
boxs = [[0 for i in range(9)] for j in range(9)]
for i in range(9):
for j in range(9):
num=board[i][j]
if num is not '.':
num=int(num)-1
if (rows[i][num]==1) or (cols[j][num]==1) or (boxs[3*int(i/3)+int(j/3)][num]==1):
return False
else:
rows[i][num]=boxs[3*int(i/3)+int(j/3)][num]=cols[j][num]=1
return True
Problem 37: Sudoku Solver
求解数独。先用row,cols,boxes三个变量存储各行各列各块已有数字,以及用blank记录空值坐标。
函数fill用于求解。选定含有信息量最大的位置开始填充,可选数字为1-9除去同行同列以及同块已有的数字,循环调用fill,如果blank全为空,即填充满,便结束循环,否则退回上一步的数字选择。
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
if board == None or len(board) == 0: return
nums=set('123456789')
rows = [set() for j in range(9)]
cols = [set() for j in range(9)]
boxs = [[set() for j in range(3)] for i in range(3)]
blank= []
for i in range(9):
for j in range(9):
num=board[i][j]
if num is not '.':
rows[i].add(num)
cols[j].add(num)
boxs[i//3][j//3].add(num)
else:
blank.append([i,j])
def fill():
i,j=max(blank,key=lambda index: len(rows[index[0]])+len(cols[index[1]])+len(boxs[index[0]//3][index[1]//3])) #firstly try the index where collect most information
blank.remove([i,j])
for num in nums-rows[i].union(cols[j]).union(boxs[i//3][j//3]):
board[i][j] = num; rows[i].add(num); cols[j].add(num); boxs[i//3][j//3].add(num)
if not blank: return True
if fill(): return True
board[i][j] = '.'; rows[i].remove(num); cols[j].remove(num); boxs[i//3][j//3].remove(num)
blank.append([i, j])
return False
if not blank: return
fill()
38. Count and Say
递归调用countandsay函数,用read函数读出上一行的输出作为输出。
class Solution:
def countAndSay(self, n: int) -> str:
if n==1:
return '1'
temp=self.countAndSay(n-1)
def read(temp):
ans=''
count=1
for k,i in enumerate(temp):
if k+1<len(temp) and temp[k]!=temp[k+1]:
ans=ans+str(count)+i
count=1
elif k+1<len(temp):
count+=1
return ans+str(count)+i
temp=read(temp)
return temp
39. Combination Sum
给定target和不重复正整数数列,数列元素可重复使用,找出所有求和为target的不重复组合。
看的是LeetCode社区分享的答案,这个递归调用太绕了,理解了一晚上。
class Solution:
def combinationSum(self, candidates: 'List[int]', target: 'int') -> 'List[List[int]]':
candidates.sort()
return self.combinationSum_helper(candidates, 0, target)
def combinationSum_helper(self, candidates, idx, target):
if target==0:
return [[]]
com=[]
for i in range(idx,len(candidates)):
if candidates[i]>target:
break
else:
new=self.combinationSum_helper(candidates, i, target-candidates[i])
if new!=[]:
for s in new:
com.append(s+[candidates[i]])
return com
40. Combination Sum II
和前面一题差不多,区别在于数列元素会重复,且不能重复使用元素。因此修改了combination_helper里面的起始检索位置,改成从当前坐标+1即可,但是会有重复数列组合,因此对com里面的元素做了重复检查。
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
candidates=[i for i in candidates if i<=target]
candidates.sort()
return self.combinationSum_helper(candidates, 0, target)
def combinationSum_helper(self, candidates, idx, target):
if target==0:
return [[]]
com=[]
for i in range(idx,len(candidates)):
if candidates[i]>target:
break
else:
new=self.combinationSum_helper(candidates, i+1, target-candidates[i])
if new!=[]:
for s in new:
if s+[candidates[i]] not in com:
com.append(s+[candidates[i]])
return com