46、全排列
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
解法一:用递归的方法,考虑n-1的情况,最后再加上nums[i]。停止条件为nums空或len(nums)<2。
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
n=len(nums)
if not nums or n<2:
return [nums]
ans=[]
for i in range(n):
curans=self.permute(nums[:i]+nums[i+1:])
for lists in curans:
lists.insert(0,nums[i])
ans=ans+curans
return ans
执行用时:40 ms, 中击败了84.36%的用户
内存消耗:13.8 MB, 击败了45.50%的用户
解法二:也可以把本题变成一个树的问题,越上层就是先被挑出来的元素,因此可以用DFS对该树进行遍历。
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
def dfs(ans,path,used,nums,n,depth):
if depth==n:
ans.append(path[:])#这里要注意不能直接用append(path),否则为空
return
for i in range(n):
if not used[i]:
used[i]=True
path.append(nums[i])
dfs(ans,path,used,nums,n,depth+1)
path.pop()
used[i]=False
n=len(nums)
if not nums or n<2:
return [nums]
ans=[]
path=[]
used=[False for _ in range(n)]
depth=0
dfs(ans,path,used,nums,n,depth)
return ans
执行用时:36 ms, 击败了94.98%的用户
内存消耗:13.9 MB, 在击败了37.01%的用户
47、全排列 II
给定一个可包含重复数字的序列,返回所有不重复的全排列。
解法一:最简单的方案是直接照抄上一道题的思路,然后再加入path时判断有没有重复。
以dfs法为例。
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
def dfs(nums,depth,n,path,used,ans):
if depth==n:
if path[:] not in ans:
ans.append(path[:])
return
for i in range(n):
if not used[i]:
used[i]=True
path.append(nums[i])
dfs(nums,depth+1,n,path,used,ans)
path.pop()
used[i]=False
ans=[]
n=len(nums)
if not nums or n<2:
return [nums]
used=[False for i in range(n)]
dfs(nums,0,n,[],used,ans)
return ans
执行用时:1180 ms, 击败了14.13%的用户
内存消耗:13.8 MB, 击败了75.83%的用户
可以看出这样粗暴的修改效率极差
解法二:这里考虑产生重复的源头
首先是如果与nums[i]相等的nums[i-1]出现在上面若干层,nums[i]的出现不会造成重复,而如果nums[i]在nums[i-1]之前出现则一定会造成重复(这是因为由于i-1的位置靠前,之前一定会考虑过nums[i-1])出现在相应位置的情况。
所以当nums[i]==nums[i-1]且nums[i-1]不在path中,则nums[i]也不能出现。
此外容易忽略的一点是一定要对nums进行排序,否则相等的数不一定挨在一起,这与上一题不同。
class Solution:
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
def dfs(nums,depth,n,path,used,ans):
if depth==n:
ans.append(path[:])
return
for i in range(n):
if not used[i]:
if i>0 and nums[i]==nums[i-1] and not used[i-1]:
continue
used[i]=True
path.append(nums[i])
dfs(nums,depth+1,n,path,used,ans)
path.pop()
used[i]=False
ans=[]
n=len(nums)
if not nums or n<2:
return [nums]
nums.sort()
used=[False for i in range(n)]
dfs(nums,0,n,[],used,ans)
return ans
执行用时:32 ms, 击败了99.91%的用户
内存消耗:13.9 MB, 击败了54.97%的用户
48、旋转图像
给定一个 n × n 的二维矩阵表示一个图像。
将图像顺时针旋转 90 度。
说明:
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
解:顺时针旋转就是一圈一圈的旋转,可以用整体平移来实现。一个循环是从外到里,一个循环是圈内平移。
class Solution:
def rotate(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
n=len(matrix)
if not matrix or n==1:
return matrix
count=0
for i in range(n,1,-2):
for j in range(count,n-count-1):
temp=matrix[count][j]
matrix[count][j]=matrix[n-1-j][count]
matrix[n-1-j][count]=matrix[n-count-1][n-j-1]
matrix[n-count-1][n-j-1]=matrix[j][n-count-1]
matrix[j][n-count-1]=temp
count=count+1
return matrix
执行用时:40 ms, 击败了71.24%的用户
内存消耗:13.6 MB, 击败了67.13%的用户
49、字母异位词分组
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
解法一:朴素的想法就是用字典区分不同的字符串从而分类。对每个字符串都构造一个字典,再对不同的类,看该字典与类中元素的字典是否相同,相同则加进去,不相同则创造新类。
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
if not strs or len(strs)==1:
return [strs]
ans=[]
ansdict=[]
for s in strs:
adict={}
for ss in s:
if ss in adict:
adict[ss]+=1
else:
adict[ss]=1
if not ansdict:
ans.append([s])
ansdict.append(adict)
else:
equal=False
n=len(ans)
for i in range(n):
if adict==ansdict[i]:
equal=True
ans[i].append(s)
break
if not equal:
ans.append([s])
ansdict.append(adict)
return ans
执行用时:3164 ms, 击败了5.00%的用户
内存消耗:19.1 MB, 击败了6.13%的用户
该方法效率极差。
解法二:先把字符串拆成列表,然后把列表排序,再join成字符串,在用上一种方法进行比对,最后发现虽然会有提高,但是提高有限,还是一千多ms。最后发现存储上可以用字典,key对应一个列表,列表中是排序后为key的元素。等遍历完再把dict中的值加进去。
class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
if not strs or len(strs)==1:
return [strs]
ans=[]
ansdict={}
for s in strs:
key="".join(list(sorted(s)))
if key in ansdict.keys():
ansdict[key].append(s)
else:
ansdict[key]=[s]
for key,value in ansdict.items():
ans.append(value)
return ans
执行用时:56 ms, 击败了87.45%的用户
内存消耗:16.5 MB, 击败了81.60%的用户
50、 Pow(x, n)
实现 pow(x, n) ,即计算 x 的 n 次幂函数。
解:用快速幂法加速
class Solution:
def myPow(self, x: float, n: int) -> float:
if x==0 and n<=0:
return False
if x==0:
return 0
if n<0:
x=1/x
n=-n
n1=str(bin(n))
ans=1
t=x
for i in range(len(n1)-1):
if n1[len(n1)-1-i]=='1':
ans=ans*t
t=t*t
return ans
执行用时:40 ms, 击败了74.69%的用户
内存消耗:13.7 MB, 击败了37.97%的用户