LeetCode刷题4:字符串篇

提示:本篇共7道力扣题目供大家食用,时间自行把控~

算法刷题系列

  • LeetCode刷题1:数组篇
  • LeetCode刷题2:链表篇
  • LeetCode刷题3:哈希篇

文章目录

  • 算法刷题系列
  • 作者有话说
  • 一、Python中的字符串
    • 1.1 字符串的定义
    • 1.2 字符串的运算
      • 1.2.1 字符串与字符串相加
      • 1.2.2 字符串与整数相乘
      • 1.2.3 字符串切片
      • 1.2.4 遍历字符串
    • 1.3 字符串常用函数
  • 二、经典题目
    • 2.1 LeetCode344. 反转字符串
    • 2.2. LeetCode541. 反转字符串II
    • 2.3. 题目:剑指Offer 05.替换空格
      • 2.3.1 方法一:遍历添加
      • 2.3.1 方法二:原地修改
    • 2.4. LeetCode151. 翻转字符串里的单词
    • 2.5. 题目:剑指Offer58-II.左旋转字符串
    • 2.6. LeetCode28. 找出字符串中第一个匹配项的下标
    • 2.7. LeetCode459. 重复的子字符串
  • 总结


作者有话说

  1、本篇是算法刷题系列文章的第 4,写此系列的目的是为了让自己对题目的理解更加深刻。

  2、本系列博客主要参考了卡哥的 代码随想录博客 以及 卡哥本人B站讲解的视频 代码随想录B站视频 ,强烈推荐给大家,因为本人学习中 Python为主,因此博客主要由 Python 代码呈现给大家,需要其他语言的版本,卡哥博客链接自取。


一、Python中的字符串

1.1 字符串的定义

   字符串简单来讲就是一串字符,字符串用双引号引起来,里面的内容几乎包含任何字符,英文字符和中文字符都可以。下面是python里面的字符串创建。

# 第一种
>>> s = str()
>>> s
''  # 空字符
# 第二种
>>> s = "我爱 Python!"
>>> s
# 输出
我爱 Python!  

1.2 字符串的运算

   字符串是有序的、不可变的字符集合。可以使用索引方式访问字符串种的任意字符。字符串可以与字符串相加,与整数相乘。

1.2.1 字符串与字符串相加

   字符串与字符串相加 等于 两个字符串的拼接。

s1 = "Hello,"
s2 = "Python!"
s3 = s1 + s2
print(s3)
# 输出结果
Hello,Python!

1.2.2 字符串与整数相乘

   字符串与整数 n 相乘 等于 n个 字符串的拼接。代码如下所示。

s1 = "Python"
s2 = s1 * 3
print(s2)
# 输出结果
PythonPythonPython

1.2.3 字符串切片

   切片是去部分元素的操作,是 Python 中特有的操作,不仅在字符串中可以使用,列表、元组都支持切片。切片操作有 3 个参数 [start: stop: step],其中 start 是切片的起始位置;stop 是切片的终止位置(不包含 stop);step 代表步长,默认是 1 。代码如下:

>>> s = "abcdefghijk"
>>> s[1:2]
'b'
>>> s[1:10:3]
'beh'

1.2.4 遍历字符串

  Python 中有两种方法遍历字符串:1、根据索引遍历;2、迭代遍历。代码如下:

# 方法一:索引
s = "Hello"
for i in range(len(s)):
	print(s[i], end=" ")
##输出
H e l l o
# 方法二:迭代
for i in s:
	print(i, end=" ")
##输出
H e l l o	

1.3 字符串常用函数

函数 语法说明 返回值
str.isdigit() 判断一个字符串是否只含有纯数字 若是,返回 True ;否则返回 False
str.isnumeric() 判断一个字符串是否只含有纯数字 若是,返回 True ;否则返回 False
str.isalpha() 判断一个字符串中是否只含有字母 若是,返回 True ;否则返回 False
str.upper() 将字符串中的小写字母转为大写字母 返回全部为大写字母的字符串
str.lower() 将字符串中的大写字母转为小写字母 返回全部为小写字母的字符串
str.find(str, beg=0, end=len(straing)) 用于检测字符串中是否包含子字符串str。str:指定检索的字符串;beg:开始索引,默认为0;end:结束索引,默认为字符串的长度 如果包含子字符串,则返回开始的索引值,否则返回 -1
str.replace(old, new[, max]) 把字符串中的 old 字符串替换成 new 字符串。old:要被替换的字符串;new:用于替换的新字符串;max:可选,字符串替换不超过 max 返回替换后的新字符串
str.split(str=“”, num=string.count(str)) 通过指定的 分隔符对字符串进行切分,如果 num 有指定值,则切分成 num+1 个子字符串。str:分隔符,默认是空字符;num:切分次数,默认是 -1 , 即切分所有子字符串 返回切分后的字符串列表

二、经典题目

2.1 LeetCode344. 反转字符串

  • 原题地址: 344. 反转字符串
  • 题目描述: 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以 字符数组 s 的形式给出。注意:你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
  • 解题思路: 使用双指针,left 从前往后遍历字符串,right 从后往前遍历字符串,然后交换 letfright 所指的值,即可在 O(1) 的空间下解决该问题。
  • 代码如下:
class Solution:
    def reverseString(self, s: List[str]) -> None:
        left = 0
        right = len(s) - 1
        while left < right:
            s[left], s[right] = s[right], s[left]
            left += 1
            right -= 1

2.2. LeetCode541. 反转字符串II

  • 原题地址: 541. 反转字符串II
  • 题目描述:

给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

    • 如果剩余字符少于 k 个,则将剩余字符全部反转;
    • 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
  • 解题思路: 模拟思路解题,利用题目信息,模拟出反转规则即可。其实在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。
  • 代码如下:
class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        def reverse(subString):
            left, right = 0, len(subString)-1

            while left < right:
                subString[left], subString[right] = subString[right], subString[left]
                left += 1
                right -= 1
            return subString  
        res = list(s)
        for i in range(0, len(s), 2*k):
            res[i: i+k] = reverse(res[i: i+k])
        return ''.join(res)


2.3. 题目:剑指Offer 05.替换空格

  • 原题地址: 题目:剑指Offer 05.替换空格
  • 题目描述: 请实现一个函数,把字符串 s 中的每个空格替换成 "%20"
  • 解题思路: 参考官方解法 —> 点击这里跳转官方解法

2.3.1 方法一:遍历添加

  • 解题思路: 遍历添加,找到字符串中的空格,然后替换它。
  • 代码如下:
class Solution:
    def replaceSpace(self, s: str) -> str:
        res = []
        for c in s:
            if c == ' ': 
            	res.append("%20")
            else: 
            	res.append(c)
        return ''.join(res)

2.3.1 方法二:原地修改

  • 解题思路: 原地修改。
  • 初始化:空格数量 count ,字符串 s 的长度 len
  • 统计空格数量:遍历 s ,遇空格则 count++
  • 修改 s 长度:添加完 "%20" 后的字符串长度应为 len + 2 * count
  • 倒序遍历修改:i 指向原字符串尾部元素, j 指向新字符串尾部元素;当 i = j 时跳出(代表左方已没有空格,无需继续遍历);
    • s[i] 不为空格时:执行 s[j] = s[i]
    • s[i] 为空格时:将字符串闭区间 [j-2, j] 的元素修改为 "%20";由于修改了 3 个元素,因此需要 j -= 2
  • 返回值:已修改的字符串 s
  • 代码如下:
class Solution:
    def replaceSpace(self, s: str) -> str:
        counter = s.count(' ')
        
        res = list(s)
        # 每碰到一个空格就多拓展两个格子,1 + 2 = 3个位置存’%20‘
        res.extend([' '] * counter * 2)
        
        # 原始字符串的末尾,拓展后的末尾
        left, right = len(s) - 1, len(res) - 1
        
        while left >= 0:
            if res[left] != ' ':
                res[right] = res[left]
                right -= 1
            else:
                res[right - 2: right + 1] = '%20'
                right -= 3
            left -= 1
        return ''.join(res)

2.4. LeetCode151. 翻转字符串里的单词

  • 原题地址: 151.翻转字符串里的单词
  • 题目描述: 给你一个字符串 s ,请你反转字符串中 单词 的顺序。单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。注意: 输入字符串 s 中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
  • 解题思路: 先对字符串进行一个整体的翻转,然后在对字符串里面的单词进行一个翻转。
  • 代码如下:
class Solution:
    #1.去除多余的空格
    def trim_spaces(self, s):     
        n = len(s)
        left = 0
        right = n-1
    
        while left <= right and s[left] == ' ': 
            left += 1
        while left <= right and s[right] == ' ': 
            right = right-1
        tmp = []
        while left <= right:
            if s[left] != ' ':
                tmp.append(s[left])
            elif tmp[-1] != ' ': 
                tmp.append(s[left])
            left += 1
        return tmp
    
    #2.翻转字符数组
    def reverse_string(self, nums, left, right):
        while left < right:
            nums[left], nums[right] = nums[right], nums[left]
            left += 1
            right -= 1
        return None
    
    #3.翻转每个单词
    def reverse_each_word(self, nums):
        start = 0
        end = 0
        n = len(nums)
        while start < n:
            while end < n and nums[end] != ' ':
                end += 1
            self.reverse_string(nums, start, end-1)
            start = end + 1
            end += 1
        return None

    #4.翻转字符串里的单词
    def reverseWords(self, s):
        l = self.trim_spaces(s) 
        self.reverse_string(l,  0, len(l)-1)  
        self.reverse_each_word(l)
        return ''.join(l)                   

2.5. 题目:剑指Offer58-II.左旋转字符串

  • 原题地址: 题目:剑指Offer58-II.左旋转字符串
  • 题目描述: 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。 比如,输入字符串 "abcdefg" 和数字 2 ,该函数将返回左旋转两位得到的结果 "cdefgab"
  • 解题思路: 方法一:使用Python中字符串切片操作,即 return s[n:len(s)] + s[0:n] 语句,便可解决该题。方法二: 局部反转+整体反转实现字符串左旋转操作。具体做法为 --> 1、反转区间为前 n 的子串;2、反转区间为 n 到末尾的子串;3、反转整个字符串。
  • 代码如下:
class Solution:
    def reverseLeftWords(self, s: str, n: int) -> str:
        s = list(s)
        # 1、反转区间为前 n 的子串
        s[0:n] = list(reversed(s[0:n]))
        # 2、反转区间为 n 到末尾的子串;
        s[n:] = list(reversed(s[n:]))
        # 3、反转整个字符串
        s.reverse()
        return ''.join(s)

2.6. LeetCode28. 找出字符串中第一个匹配项的下标

  • 原题地址: 28. 找出字符串中第一个匹配项的下标
  • 解题思路: 此题使用 KMP算法 进行求解,具体思路请点击跳转 LeetCode28:找出字符串中第一个匹配项的下标题解之KMP算法 。那篇博客对 KMP算法 进行了详细的阐述,这里不再赘述,只给出参考代码。
  • 代码如下:
class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        m, n = len(haystack), len(needle)
        if n == 0:
            return 0
        i, j = 0, 0
        next = self.getNext(n, needle)
        while (i<m and j<n):
            if j==-1 or needle[j]==haystack[i]:
                i+=1
                j+=1
            else:
                j=next[j]
        if j==n:
            return i-j
        else:
            return -1

    def getNext(self, n, needle):
        next = [' ' for i in range(n)]  # next的初始化
        j, k = 0, -1
        next[0] = k
        while (j < n-1 ) :
            if k==-1 or needle[k] == needle[j]: # 找到前缀表了
                k += 1
                j += 1
                next[j] = k
            else:
                k = next[k]
        return next

2.7. LeetCode459. 重复的子字符串

  • 原题地址: 459.重复的子字符串
  • 题目描述: 给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。
  • 解题思路: 使用KMP算法进行求解。关于KMP算法的讲解,请查看 KMP视频讲解。
  • 代码如下:
class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:  
        if len(s) == 0:
            return False
        nxt = [0] * len(s)
        self.getNext(nxt, s)
        if nxt[-1] != -1 and len(s) % (len(s) - (nxt[-1] + 1)) == 0:
            return True
        return False
    
    def getNext(self, nxt, s):
        nxt[0] = -1
        j = -1
        for i in range(1, len(s)):
            while j >= 0 and s[i] != s[j+1]:
                j = nxt[j]
            if s[i] == s[j+1]:
                j += 1
            nxt[i] = j
        return nxt

总结

  字符串篇 到这里就结束了,若文章中有表述不当的地方还望大家多多指出,栈与队列篇见吧。

你可能感兴趣的:(leetcode刷题,leetcode,算法,字符串,python)