leetcode题解python版:46-50

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%的用户

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值