代码随想录算法训练营Day 8 | 344.反转字符串541. 反转字符串II剑指Offer 05.替换空格151.翻转字符串里的单词剑指Offer58-II.左旋转字符串

344.反转字符串

力扣题目链接

编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。

不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:
输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]

示例 2:
输入:["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]

版本一:双指针

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        left, right = 0, len(s) - 1
        
        # 该方法已经不需要判断奇偶数,经测试后时间空间复杂度比用 for i in range(len(s)//2) 更低
        # 因为 while 每次循环需要进行条件判断,而 range 函数不需要,直接生成数字,因此时间复杂度更低。推荐使用 range
        while left < right:
            s[left], s[right] = s[right], s[left]
            left += 1
            right -= 1

  1. class Solution::这是一个类定义,通常在LeetCode中用于将解决方案封装成一个类的形式。解决方案通常是作为类的方法来实现的。

  2. def reverseString(self, s: List[str]) -> None::这是一个方法定义,用于反转输入的字符串列表 sself 是类方法的第一个参数,表示该方法是一个成员方法。s 是输入参数,它是一个字符串列表。-> None 表示这个方法不返回任何值,它会在原地修改输入的字符串列表。

  3. left, right = 0, len(s) - 1:这一行代码初始化两个指针 leftright,它们分别指向字符串列表的开头和末尾。left 初始化为0,表示字符串列表的第一个元素,right 初始化为 len(s) - 1,表示字符串列表的最后一个元素。

  4. while left < right::这是一个 while 循环,它的条件是 left 指针小于 right 指针,意味着只要 left 还在 right 的左边,就继续执行循环。

  5. s[left], s[right] = s[right], s[left]:这一行代码实际上是交换了 left 指针和 right 指针指向的元素的值。通过使用 Python 的多重赋值特性,可以很方便地交换两个变量的值,这里用于交换字符串列表中对应位置的元素。

  6. left += 1right -= 1:这两行代码分别将 left 指针向右移动一位,将 right 指针向左移动一位,以便继续下一次循环,直到完成整个字符串列表的反转。

总的来说,这段代码使用了双指针的方法,从字符串列表的两端开始,逐渐向中间移动,并交换元素的值,最终实现了字符串列表的反转。这种方法是一种常见的反转列表的方式,它的时间复杂度是 O(n),其中 n 是字符串列表的长度。

版本二:使用栈

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        stack = []  # 创建一个空栈
        for char in s:
            stack.append(char)  # 将字符依次入栈
        for i in range(len(s)):
            s[i] = stack.pop()  # 从栈中弹出字符并赋值给原字符串列表,实现反转
  1. 栈 = []:创建一个空的栈(堆栈)。

  2. for char in s::遍历输入的字符串列表 s 中的每个字符,将它们依次添加到栈中。

  3. for i in range(len(s))::通过索引 i 遍历整个字符串列表 s

  4. s[i] = 栈.pop():从栈中弹出最后一个字符,并将其赋值给字符串列表 s 中的当前位置 i,从而实现了字符串列表的反转。

这种方法的时间复杂度为 O(n),其中 n 是字符串列表的长度,因为我们对字符串列表进行了两次完整的遍历。空间复杂度为 O(n),因为我们使用了一个额外的栈数据结构来存储字符。这是一种简单而直观的方法来反转字符串列表。

版本三:使用range

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        n = len(s)  # 获取字符串列表的长度
        for i in range(n // 2):  # 只需要遍历一半的列表
            s[i], s[n - i - 1] = s[n - i - 1], s[i]  # 交换对应位置的元素
  1. n = len(s):获取输入字符串列表 s 的长度,并将其存储在变量 n 中。这个长度将帮助我们确定需要遍历多少次来完成反转。

  2. for i in range(n // 2)::这是一个 for 循环,它只需要遍历一半的列表,因为在反转的过程中,前半部分的元素会与后半部分的元素进行交换,反转完成后列表就会变为原来的逆序。

  3. s[i], s[n - i - 1] = s[n - i - 1], s[i]:这一行代码使用了多重赋值的方式,将前半部分 s[i] 和后半部分 s[n - i - 1] 的值进行交换。这个操作会将列表中对应位置的元素进行反转

 版本四:使用reverse

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        s[:] = reversed(s)

 s[:] = s[::-1]:这一行代码使用了 Python 的切片(slicing)操作来反转列表 s。具体来说,s[::-1] 表示一个切片,它从最后一个元素到第一个元素,以逆序的方式提取元素。然后,s[:] 表示将切片的结果重新赋值给列表 s,这样就完成了列表的反转。

版本五:使用列表

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        s[:] = [s[i] for i in range(len(s) - 1, -1, -1)]
  1. [s[i] for i in range(len(s) - 1, -1, -1)]:这是一个列表推导式,它遍历了从 len(s) - 10 的索引范围,以逆序的方式提取字符串列表 s 中的元素,并将它们构建成一个新的列表。这个新列表就是原列表的逆序版本。

  2. s[:]:这是一个切片操作,它将新的逆序列表重新赋值给原列表 s,从而实现了字符串列表的反转。

541. 反转字符串II

力扣题目链接

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

如果剩余字符少于 k 个,则将剩余字符全部反转。

如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

示例:

输入: s = "abcdefg", k = 2
输出: "bacdfeg"

class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        """
        1. 使用range(start, end, step)来确定需要调换的初始位置
        2. 对于字符串s = 'abc',如果使用s[0:999] ===> 'abc'。字符串末尾如果超过最大长度,则会返回至字符串最后一个值,这个特性可以避免一些边界条件的处理。
        3. 用切片整体替换,而不是一个个替换.
        """
        def reverse_substring(text):
            left, right = 0, len(text) - 1
            while left < right:
                text[left], text[right] = text[right], text[left]
                left += 1
                right -= 1
            return text
        
        res = list(s)  # 将输入字符串转换为字符列表,以便后续修改

        for cur in range(0, len(s), 2 * k):  # 以 2*k 为步长遍历字符串
            res[cur: cur + k] = reverse_substring(res[cur: cur + k])  # 对每个块内的字符进行反转
        
        return ''.join(res)  # 将字符列表转换回字符串并返回
  1. reverse_substring(text) 函数:这个函数接受一个字符串 text,然后使用双指针技巧反转字符串。它通过不断交换字符来实现反转,最终返回反转后的字符串。

  2. res = list(s):这一行代码将输入的字符串 s 转换为字符列表 res,以便后续可以通过索引修改其中的字符。

  3. for cur in range(0, len(s), 2 * k):这是一个 for 循环,它以步长 2 * k 遍历字符串,其中 cur 是当前块的起始位置。每次循环处理一个块。

  4. res[cur: cur + k] = reverse_substring(res[cur: cur + k]):在循环内部,对每个块的字符列表进行了反转操作。具体来说,它使用 reverse_substring 函数对当前块内的字符进行反转,并将反转后的结果赋值回 res 列表中的相应位置。

  5. return ''.join(res):最后,将字符列表 res 转换回字符串,并返回最终的结果。

这段代码的主要思路是将字符串分成块,对每个块内的字符进行反转,最后将块拼接在一起。这样就实现了按照长度为 k 的块进行反转的操作。时间复杂度取决于字符串的长度,但是对于每个块内的字符反转,它的时间复杂度是 O(k),因此总的时间复杂度是 O(n),其中 n 是字符串的长度。

剑指Offer 05.替换空格

力扣题目链接(opens new window)

请实现一个函数,把字符串 s 中的每个空格替换成"%20"。

示例 1: 输入:s = "We are happy."
输出:"We%20are%20happy."

法一:添加空列表,添加匹配的结果

class Solution:
    def replaceSpace(self, s: str) -> str:
        res = []
        for i in range(len(s)):
            if s[i] == ' ':
                res.append('%20')
            else:
                res.append(s[i])
        return ''.join(res)
  1. res = []:这一行代码创建一个空的列表 res,用于存储替换后的字符。

  2. for i in range(len(s))::这是一个 for 循环,它遍历字符串 s 中的每个字符,使用索引 i 来访问每个字符。

  3. 在循环内部,使用条件语句检查当前字符是否是空格 s[i] == ' '。如果是空格,就执行以下操作:

    • res.append('%20'):将 %20 添加到列表 res 中,以替换空格。
  4. 如果当前字符不是空格(else 分支),就执行以下操作:

    • res.append(s[i]):将原字符添加到列表 res 中,以保持字符不变。
  5. return ''.join(res):最后,将列表中的字符使用 join 方法拼接成一个字符串,并返回这个字符串作为结果。

法二:使用replace

class Solution:
    def replaceSpace(self, s: str) -> str:

 s.replace(' ', '%20'):这一行代码调用了字符串 sreplace 方法,用于将字符串中的空格 ' ' 替换为 %20。这个方法会返回一个新的字符串,其中空格被替换为 %20

151.翻转字符串里的单词

力扣题目链接

给定一个字符串,逐个翻转字符串中的每个单词。

示例 1:
输入: "the sky is blue"
输出: "blue is sky the"

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

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

class Solution:
    def reverseWords(self, s: str) -> str:
        # 删除前后空白
        s = s.strip()
        # 反转整个字符串
        s = s[::-1]
        # 将字符串拆分为单词,并反转每个单词
        s = ' '.join(word[::-1] for word in s.split())
        return s
  1. s = s.strip():这一行代码用于删除字符串两端的空白字符(包括空格、制表符和换行符等),确保字符串没有前导和尾随的空格。

  2. s = s[::-1]:这一行代码通过切片操作将整个字符串反转。[::-1] 表示从字符串末尾向前逆序遍历,实现字符串反转。

  3. s = ' '.join(word[::-1] for word in s.split()):这一行代码实现了将字符串拆分为单词,并反转每个单词后重新拼接成字符串。具体操作如下:

    • s.split():将字符串按照空格拆分成一个单词列表。
    • word[::-1] for word in s.split():使用列表推导式,对每个单词进行反转,得到一个反转后的单词列表。
    • ' '.join(...):将反转后的单词列表用空格拼接成一个字符串,这样单词之间仍然以空格分隔。

剑指Offer58-II.左旋转字符串

力扣题目链接

class Solution:
    def reverseLeftWords(self, s: str, n: int) -> str:
        return s[n:] + s[:n]
  1. s[n:]:这部分代码表示从字符串 s 的第 n 个字符开始到末尾的子字符串。它实际上提取了字符串 s 中从第 n 个字符到末尾的部分。

  2. s[:n]:这部分代码表示从字符串 s 的开头到第 n 个字符的子字符串。它实际上提取了字符串 s 中从开头到第 n 个字符的部分。

  3. s[n:] + s[:n]:将第 1 步和第 2 步提取的两个子字符串进行拼接,即将原字符串 s

你可能感兴趣的:(leetcode,leetcode)