leetcode题解python版:6-10题

6、Z字形变换
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:

L   C   I   R
E T O E S I I G
E   D   H   N

之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
请你实现这个将字符串进行指定行数变换的函数:

解答:本题只要找到相应的数学规律就十分容易,算法的时间复杂度和空间复杂度都能维持在O(n)。

class Solution:
    def convert(self, s: str, numRows: int) -> str:
        outputS=""
        n=len(s)
        if numRows==1:
            return s
        elif numRows==2:
            for i in range(2):
                k=i
                while k<n:
                    outputS=outputS+s[k]
                    k=k+2
            return outputS
        else:
            k=0
            while k<n:
                outputS=outputS+s[k]
                k=k+2*numRows-2
            for i in range(1,numRows-1):
                k1=i
                k2=2*numRows-2-i
                while k1<n:
                    outputS=outputS+s[k1]
                    if k2<n:
                        outputS=outputS+s[k2]
                    k1=k1+2*numRows-2
                    k2=k2+2*numRows-2
            k=numRows-1
            while k<n:
                outputS=outputS+s[k]
                k=k+2*numRows-2
            return outputS

算法的运行时间是64 ms,内存消耗是13.8 MB。

7、整数反转
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
解答:把数变成列表,用alist.reverse()或者自己写一个反转的语句,看看哪个效率高。

class Solution:
    def reverse(self, x: int) -> int:
        if x==0:
            return 0
        else:
            xList=list(str(abs(x)))
            xList.reverse()
            #n=len(xList)
            #for i in range(n//2):
                #temp=xList[i]
                #xList[i]=xList[n-1-i]
                #xList[n-1-i]=temp
            if xList[0]=='0':
                xList=xList[1:]
            if x<0:
                x2=int("-"+"".join(xList))
            else:
                x2=int("".join(xList))
            if x2 > 2 ** 31-1 or x2 < -2 ** 31:
                return 0
            else:
                return x2

自己编的反转要60 ms ,13.6 MB。用alist.reverse()之后运行时间变成了40 ms,内存消耗为13.7 MB,不变。可见还是系统自带的函数功能更强。

8、字符串转换整数 (atoi)
请你来实现一个 atoi 函数,使其能将字符串转换成整数。

首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。接下来的转化规则如下:
如果第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字字符组合起来,形成一个有符号整数。
假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成一个整数。
该字符串在有效的整数部分之后也可能会存在多余的字符,那么这些字符可以被忽略,它们对函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换,即无法进行有效转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0 。
提示:
本题中的空白字符只包括空格字符 ’ ’ 。
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
该题有很多细节需要处理,例如输入"-"的情况,有+出现的情况等。尤其是需要排出的各类情况,不要遗漏。

class Solution:
    def myAtoi(self, str: str) -> int:
        n=len(str)
        i=0
        while i<n and str[i]==' ':
            i=i+1
        if i==n or n==0:
            return 0
        str=str[i:]
        num=""
        if str[0]=='-':
            num=num+"-"
            for i in str[1:]:
                if '0'<=i and i<='9':
                    num=num+i
                else:
                    break
            if len(num)<2:#防止"-"的形式出现
                return 0
        elif '0'<=str[0]<='9':
            for i in str:
                if '0'<=i and i<='9':
                    num=num+i
                else:
                    break
            if len(num)<1:#防止全是字母的形式出现
                return 0
        elif str[0]=="+":
            for i in str[1:]:
                if '0'<=i and i<='9':
                    num=num+i
                else:
                    break
            if len(num)<1:#防止全是字母的形式出现
                return 0
        else:
            return 0
        num=int(num)
        INT_MAX=2**31-1
        INT_MIN=-2**31
        if num>INT_MAX:
            return INT_MAX
        elif num<INT_MIN:
            return INT_MIN
        else:
            return num

因为一直在加情况,代码比较乱,也懒得整理了。
最后运行时间是40 ms,内存消耗是13.8 MB
9、回文数
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
注:负数不是回文数

class Solution:
    def isPalindrome(self, x: int) -> bool:
        if x<0:
            return False
        else:
            xStr=str(x)
            n=len(xStr)
            if n==1:
                return True
            else:
                a=1
                for i in range(n//2):
                    if xStr[i]!=xStr[n-1-i]:
                        a=0
                        break
                if a==1:
                    return True
                else:
                    return False

运行时间是76 ms,内存消耗是13.7 MB。
这里比较有意思的是return False打印的是false。

10、正则表达式匹配(hard)
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。

'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素

所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。

解法一:这种乱七八糟的题的一个朴素的想法就是用递归,只要每次能减少就行。
如果p空,那么s必须要空才行。此外事实上我们只需要考虑’*'位于p[1]的情况,这是p[0]p[1]可以当0个使用或者当n个p[0]使用,n必然>=1,我们在一次调用中只需要让这对组合使用0次或一次就行,这样要么把p[0]p[1]组合删去,要么在首字母匹配后可以将s[0]删去,如此一来这样的递归肯定能够终止,问题也就解决了。

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        if not p:
            return not s
        firstMatch= len(s)>0 and (p[0]=="." or p[0]==s[0])#首字母匹配
        if len(p)>=2 and p[1]=="*":#可以是零个或任意多个,多个时s[0]与p[0]要匹配
            return self.isMatch(s,p[2:]) or (firstMatch and self.isMatch(s[1:],p))
        else:
            if firstMatch:#检验第一个是否符合
                return self.isMatch(s[1:],p[1:])
            else:
                return False

因为本题的情况很少,所以递归的代码相当简洁,只是效率低下,运行时间为1284 ms只超过了27.33%的用户,内存消耗为13.4 MB。

解法二:
事实上我们可以基于上述的递归方法进行改进。改进递归法的思路就是储存一些递归中间结果,避免重复运算。还有就是代码里的切片可以改为标记左右点,这样能剩下不少内存也能节约时间。

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        if not p:
            return not s
        self.memory={}#初始化记忆,要加self的
        self.buildMemory(s,p)#构建缓存
        return self.memory[(s,p)]
    def buildMemory(self,s,p):#self必不可少
        if not p:
            return not s
        if (s,p) in self.memory:
            return self.memory[(s,p)]
        firstMatch= len(s)>0 and (p[0]=="." or p[0]==s[0])#首字母匹配
        if len(p)>=2 and p[1]=="*":#可以是零个或任意多个,多个时s[0]与p[0]要匹配
            result=self.buildMemory(s,p[2:]) or (firstMatch and self.buildMemory(s[1:],p))#firstMatch必不可少
        else:
            if firstMatch:#检验第一个是否符合
                result=self.buildMemory(s[1:],p[1:])
            else:
                result=False
        self.memory[(s,p)]=result
        return result

运行时间为52 ms,超过93.12%的用户,但是内存基本不变

你可能感兴趣的:(python,算法,leetcode,递归法,正则表达式)