LeetCode刷题——字符串(python语言)

本文介绍了LeetCode中涉及字符串处理的四道题目,包括验证回文串、翻转字符串里的单词、删除字符形成回文串和Excel表列名称的转换。分别采用双指针、切分与连接、删除字符检查及正则表达式解码等方法,展示了多种解决问题的策略和技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LeetCode刷题——字符串(python语言)

一、字符串

1.1 字符串定义

字符串就是一系列字符的连接。字符串可以遍历,每次遍历都是字符。

1.2 字符串匹配

首先,我们称待匹配的字符串(长)为主串,用来匹配的字符串(短)为子串(模式串),字符串匹配就是要找到主串中存在模式串的位置。字符串匹配算法主要分为/字符串的朴素匹配)BF算法和(字符串的高效匹配)KMF算法,由于笔者能力有限,这里附上大佬的链接。BF算法和KMF算法的区别

二、刷题

2.1 验证回文串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。

示例 1:
输入: “A man, a plan, a canal: Panama”
输出: true
解释:“amanaplanacanalpanama” 是回文串

示例 2:
输入: “race a car”
输出: false
解释:“raceacar” 不是回文串

提示:
1 <= s.length <= 2 * 105
字符串 s 由 ASCII 字符组成

#很常规的题,首先排除非字母的和大写的,比较前后是否对称,双指针的思想
class Solution:
    def isPalindrome(self, s: str) -> bool:
        n = len(s)
        i = 0
        j = n - 1
        while(i<j):
            if not (s[i].isalnum()): #排除非字母的
                i += 1
                continue
            if not (s[j].isalnum()): #排除非字母的
                j -= 1
                continue
            if((s[i].lower())==(s[j].lower())): #不区分大小写的
                i += 1 
                j -= 1
            else:
                return False 
        return True
#	48 ms	15 MB

2.2 翻转字符串里的单词

给你一个字符串 s ,逐个翻转字符串中的所有 单词 。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
请你返回一个翻转 s 中单词顺序并用单个空格相连的字符串。

说明:
输入字符串 s 可以在前面、后面或者单词间包含多余的空格。
翻转后单词间应当仅用一个空格分隔。
翻转后的字符串中不应包含额外的空格。

示例 1:
输入:s = “the sky is blue”
输出:“blue is sky the”

示例 2:
输入:s = " hello world "
输出:“world hello”
解释:输入字符串可以在前面或者后面包含多余的空格,但是翻转后的字符不能包括。

示例 3:
输入:s = “a good example”
输出:“example good a”
解释:如果两个单词间有多余的空格,将翻转后单词间的空格减少到只含一个。

示例 4:
输入:s = " Bob Loves Alice "
输出:“Alice Loves Bob”

示例 5:
输入:s = “Alice does not even like bob”
输出:“bob like even not does Alice”

提示:
1 <= s.length <= 104
s 包含英文大小写字母、数字和空格 ’ ’
s 中 至少存在一个 单词

进阶:
请尝试使用 O(1) 额外空间复杂度的原地解法。

#切分(记得去除多余的空格,没找到一次空格,查看是否有单词存储),倒置,连接     
#2_1 
class Solution:
    def reverseWords(self, s: str) -> str:
        words = s.split() #按照空格,切分
        words.reverse() #倒置
        return " ".join(words) #连接
#36 ms	15 MB
#2_2
class Solution:
    def reverseWords(self, s: str) -> str:
        words = [] #最终的文本库
        cur = ""  #存储每个字
        for ch in s: 
            if(ch==" "):#如果是空格,判断前方是不是单词
                if cur:#是单词,记录了
                    words.append(cur)#加入文本库
                    cur = ""#存储转换为空
            else:
                cur += ch#记录单词的每个字母
        if cur:
            words.append(cur)#最后一个单词存储
        n = len(words)#单词计数
        for i in range(n//2):#类似数组,调换每个单词反转
            words[i],words[n-1-i] = words[n-1-i],words[i]
        #words.reverse() #或者直接反转列表
        return " ".join(words)#用空格连接
#40 ms	15.1 MB

2.3 验证回文字符串 Ⅱ

给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。

示例 1:
输入: s = “aba”
输出: true

示例 2:
输入: s = “abca”
输出: true
解释: 你可以删除c字符。

示例 3:
输入: s = “abc”
输出: false

提示:
1 <= s.length <= 105
s 由小写英文字母组成

#删掉一个字符可以认为时
#3_1
class Solution:
    def validPalindrome(self, s: str) -> bool:
        n = len(s) #记录字符串长度
        i = 0
        j = n - 1 
        delete_s = 1 #删掉一个字符的标记
        answer_1 = answer_2 = False #分两次讨论,当不匹配时,删除左字符或者右字符
        while(i<=j):
            if(s[i]==s[j]):
                i += 1 
                j -= 1
                answer_1 = True 
            elif(delete_s):#删掉左字符
                i += 1
                delete_s = 0
            else:
                answer_1 = False 
                break
        i = 0
        j = n - 1 
        delete_s = 1
        while(i<=j):
            if(s[i]==s[j]):
                i += 1 
                j -= 1
                answer_2 = True 
            elif(delete_s):#删掉右字符
                j -= 1 
                delete_s = 0
            else:
                answer_2 = False
                break
        return answer_1 or answer_2
#188 ms	15.2 MB
#3_2

class Solution:
    def validPalindrome(self, s: str) -> bool:
        if s==s[::-1]:#前后是否相等
            return True
        l,r=0,len(s)-1#定义左右指针
        while l<r:
            if s[l]==s[r]:
                l+=1
                r-=1
            else:#不相等时,对不相等部分删除一个左右字符切片
                a=s[l+1:r+1]
                b=s[l:r]

                return a==a[::-1] or b==b[::-1]#判断其中一个是否相同
#52 ms	15.4 MB
#本题陷入蒙圈中,在leetcode上copy的大佬的代码,链接在下面

2.4 Excel表列名称

给你一个整数 columnNumber ,返回它在 Excel 表中相对应的列名称。

例如:

A -> 1
B -> 2
C -> 3

Z -> 26
AA -> 27
AB -> 28

示例 1:
输入:columnNumber = 1
输出:“A”

示例 2:
输入:columnNumber = 28
输出:“AB”

示例 3:
输入:columnNumber = 701
输出:“ZY”

示例 4:
输入:columnNumber = 2147483647
输出:“FXSHRXW”

提示:
1 <= columnNumber <= 231 - 1

#4_1
class Solution:
    def convertToTitle(self, columnNumber: int) -> str:
        res = "" 
        #因为有26个字母,但是0和26对26取余都是0,所以向商借一位,排除0的因素
        while(columnNumber>0):
            columnNumber, y = divmod(columnNumber, 26) #对数组对26取余
            if y == 0: #如果余数是0,因为排除为0的因素,我们从1-26编号。
                columnNumber -= 1#从商借一位
                y = 26#余数为26
            res = chr(y + 64) + res#字符串加法构造,chr对应将ASCII2码转化为字符,ord相反,ord(A)是65
        return res
#52 ms	15.4 MB
#4_2 和正常 0~25 的 26 进制相比,本质上就是每一位多加了 1。假设 A == 0,B == 1,那么 AB = 26 * 0 + 1 * 1,而现在 AB = 26 * (0 + 1) + 1 * (1 + 1),所以只要在处理每一位的时候减 1,就可以按照正常的 26 进制来处理
class Solution:
    def convertToTitle(self, columnNumber: int) -> str:
        res = ""
        while(columnNumber>0):
            columnNumber -= 1
            columnNumber, y = divmod(columnNumber, 26) 
            res = chr(y + 65) + res
        return res
#24 ms	14.8 MB
#4_3 思路同2
class Solution:
    def convertToTitle(self, n: int) -> str:
        return "" if n == 0 else self.convertToTitle((n - 1) // 26) + chr((n - 1) % 26 + 65)
#36 ms	15 MB

作者:powcai
链接:https://leetcode-cn.com/problems/excel-sheet-column-title/solution/shi-jin-zhi-zhuan-26jin-zhi-by-powcai/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2.5 字符串解码

给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

示例 1:
输入:s = “3[a]2[bc]”
输出:“aaabcbc”

示例 2:
输入:s = “3[a2[c]]”
输出:“accaccacc”

示例 3:
输入:s = “2[abc]3[cd]ef”
输出:“abcabccdcdcdef”

示例 4:
输入:s = “abc3[cd]xyz”
输出:“abccdcdcdxyz”

提示:
1 <= s.length <= 30
s 由小写英文字母、数字和方括号 ‘[]’ 组成
s 保证是一个 有效 的输入。
s 中所有整数的取值范围为 [1, 300]

#5 正则化写法
class Solution:
    def decodeString(self, s: str) -> str:
        def encode(t: str) -> str:
            i = t.find('[')
            return int(t[:i]) * t[i+1:-1]

        regex = re.compile(r'\d+\[\w*\]')
        mo = regex.search(s)
        while mo:
            s = s.replace(mo.group(), encode(mo.group()))
            mo = regex.search(s)
        return s     
#28 ms	15.1 MB
#5_2 用栈写
class Solution:
    def decodeString(self, s: str) -> str:
        # nums保存倍数
        nums = []
        stack = []
        # temp 保存[与]之间的字符串
        temp = []
        num = ''
        for i in s:
            # 当遇到数字字符时,将其合并起来,后面转换为倍数,比如:'66'
            if i.isdigit():
                num  += i
                continue
            # 通过判断,将num中的数字字符串转换为,int并保存进nums中,只有当num的长度大于0,且i不为数字的时候,才将数字存进去
            if not i.isdigit() and len(num)>0:
                nums.append(int(num))
                num = ''
            # 当遇到右括号],开始出栈,直到遇到[停止
            if i == ']':
                # 将stack中的字符出栈,直到遇到[停止
                m = stack.pop()
                while m != '[':
                    temp.append(m)
                    m = stack.pop()
                # [的左边一定为数字,即[...,s_num,'['],所以stack.pop()即为倍数
                s_num = nums.pop()  
                # 部分翻倍的字符串
                # 字符出栈的方向与原字符方向相反,所以注意反向回来
                s_str = ''.join(temp[::-1])
                # 将翻倍的字符串推进stack中
                # s_num是倍数
                while s_num: 
                    for j in s_str:
                        stack.append(j)
                    s_num -= 1
                temp = []
            else:
                stack.append(i)
            
        return ''.join(stack)
#36 ms	15.2 MB
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值