代码随想录算法训练营第8天| leetcode 344. 反转字符串、541. 反转字符串 II、 Offer 05. 替换空格、151. 反转字符串中的单词、Offer 58 - II.左旋转字符串

344. 反转字符串

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

  • 如何做到反转的效果?其实就是不断地首尾交换,利用双指针法,一个左指针从头开始,一个右指针从尾开始,两个指针同时向中间移动,不断地交换左右指针对应的元素即可
class Solution(object):
    def reverseString(self, s):
        """
        :type s: List[str]
        :rtype: None Do not return anything, modify s in-place instead.
        """
        left = 0
        right = len(s)-1
        while left < right:   # 当left=right的时候,指向同一个元素,就不用交换了(奇数个字符的场景)
            s[left], s[right] = s[right], s[left]
            left += 1
            right -= 1
        

541. 反转字符串 II

https://leetcode.cn/problems/reverse-string-ii/
重点:

  • 注意这道题每次是反转2k个字符中的前k个字符,然后处理下一段2k个字符,当需要固定规律一段一段去处理字符串的时候,要想想在for循环的表达式上做文章。
  • 编写reverse函数,只反转字符串从i到i+k-1的部分
class Solution(object):
    def reverseStr(self, s, k):
        """
        :type s: str
        :type k: int
        :rtype: str
        """
        def reverse(s, left, right):  # 只反转s从left到right的部分
            while left < right:
                s[left], s[right] = s[right], s[left]
                left += 1
                right -= 1
            return s 
        remain = len(s)
        s = list(s)
        i = 0
        while i < len(s):
            if remain < k:
                s = reverse(s, i, len(s)-1)  # 将剩余字符全部反转
            else:
                s = reverse(s, i, i+k-1)  # 反转前k个字符
            i += 2*k
            remain -= 2*k
        return ''.join(s)


剑指 Offer 05. 替换空格

注意,如果将s变成一个列表,然后去遍历里面的元素,如果遇到空格,则将元素改为’%20’,这样写的话,不能写for i in s,因为这样写i就是一个字符串,在python中,字符串是不可变类型,所以当i=空格时,如果令i=‘%20’,相当于是新建了一个i,令i=‘20%’,而不是对列表中的迭代项i进行修改,所以会发现程序运行后空格依然存在,并没有被修改。

class Solution(object):
    def replaceSpace(self, s):
        """
        :type s: str
        :rtype: str
        """
        s = s.split(' ')
        return '%20'.join(s)
        

151. 反转字符串中的单词

  • 用python的split函数,只会去掉单词间的一个空格,不会去掉多余的空格以及前导空格和尾随空格
    12
  • 先去除前导空格,尾随空格,以及单词之间多余的空格
  • 反转整个字符串
  • 逐个将单词反转
  • 整体反转+局部反转,即可达到反转单词的目的。先整体反转,让单词的顺序反转(不管单词的内部),再局部反转,使得单词内部的字母顺序正确。
class Solution(object):
    def reverseWords(self, s):
        """
        :type s: str
        :rtype: str
        """
        def reverse(s, left, right):  # 左闭右开
            right -= 1
            while left < right:
                s[left], s[right] = s[right], s[left]
                left += 1
                right -= 1
            return s
        s = list(s)
        res = []
        # 去除前导空格
        i = 0
        while s[i] == ' ':
            i += 1
        # 去除尾随空格
        j = len(s)-1
        while s[j] == ' ':
            j -= 1
        while i <= j:  # 去除单词之间的空格
            if s[i] == ' ':
                while s[i] == ' ':
                    i += 1
                res.append(' ')
            else:
                res.append(s[i])
                i += 1
        res = res[::-1]  # 将整个字符串反转
        start = 0   # 单词的起始位置
        end = 0     # 单词的结束位置(不包含end)
        while end < len(res):
            # 遇到空格,说明一个单词结束了,则从索引start到end-1是一个单词
            if res[end] == ' ':   # 注意end是索引,要加上res啊
                res = reverse(res, start, end)  # 反转单词
                start = end+1  # 将start更改到下一个单词的起始位置
            end += 1
        res = reverse(res, start, end)   # 反转最后一个单词
        return ''.join(res)
        

剑指 Offer 58 - II. 左旋转字符串

  • python切片操作:s[start_index:end_index:step]
    包含start_index,不包含end_index(不用管左闭右开还是什么,就是不包含end_index(两个冒号之间)这个位置的索引)
    step是步长,如果为正则代表方向从左往右(索引从小到大)
    如果为负则代表方向从右往左(索引从大到小)
    注意步长的方向要和start_index:end_index的方向一致
  • 这道题的关键点是整体反转+局部反转先反转整个字符串,然后反转末尾的n个字符,最后反转剩余的字符。
class Solution(object):
    def reverseLeftWords(self, s, n):
        """
        :type s: str
        :type n: int
        :rtype: str
        """
        s = list(s)
        l = len(s)
        s = s[::-1]
        s[:l-n] = s[l-n-1::-1]
        s[l-n::] = s[l-1:l-n-1:-1]
        return ''.join(s)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值