代码随想录算法训练营第八天 | 344.反转字符串 541. 反转字符串II 剑指Offer 05.替换空格 151.翻转字符串里的单词

344.反转字符串

Reverse String - LeetCode

什么时候用库函数:

如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。

如果库函数仅仅是 解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以考虑使用库函数。

解题思路

左右双指针,一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        l = 0
        r = len(s) - 1
        while l < r:
            s[l], s[r] = s[r], s[l]
            l += 1
            r -= 1

时间复杂度 O(N)

空间复杂度 O(1)


541. 反转字符串II

Reverse String II - LeetCode

解题思路

1. 左右双指针,反转字符串

2. res = list(a), 遍历res, 让i 每次走 2k步,通过切片更新res[i:i + k] 。

        for loop里其实需要讨论两种情况:

        if i + k <= len(s): 

                res[i:i+k] = reverse_s(res[i:i+k])

        else:

                res[i:len(s)] = reverse_s( res[i:len(s)])

     但res[i: i + k] ,i始终不会越界,i+k即使大于了数组长度,切片时,也会在len(s) -1的index终止。

遇到的问题 

要将string先转化为list

为了处理逻辑:每隔2k个字符的前k的字符,写了一堆逻辑代码。其实在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。

class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        def reverse_s(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 i in range(0, len(s), 2 * k):
            res[i:i+k] = reverse_s(res[i:i+k])
        return "".join(res)

时间复杂度 O(N)

空间复杂度 O(N)


剑指Offer 05.替换空格

力扣

很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作.

这么做有两个好处:

  1. 不用申请新数组。
  2. 从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。

算法:

统计字符串里有几个空格

res =字符串转化的list

给res扩容

左右指针,左指针指向原字符串的末位index,右指针指向res的末位。都向左移动,遍历res数组:

        如果原字符串的index值不是空格,交换res[right] res[left] 值,right 和left各左移一位

        否则,将切片值替换,res[right - 2: right + 1] = '%20', right左移三位,left左移一位

最后将res数组转化为字符串返回

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:
                # [right - 2, right), 左闭右开
                res[right - 2: right + 1] = '%20'
                right -= 3
            left -= 1
        return ''.join(res)

时间复杂度 O(N)

空间复杂度 O(N)


151.翻转字符串里的单词

Reverse Words in a String - LeetCode

解题思路

先整体反转再局部反转

  1. 移除多余空格
  2. 将整个字符串反转
  3. 将每个单词反转
    class Solution:
        def reverseWords(self, s: str) -> str:
            l = self.trim_spaces(s)
            self.reverse(l, 0, len(l) - 1)
            self.reverse_each_word(l)
            return "".join(l)
        
        def trim_spaces(self, s):
            a = list(s)
            slow = fast = 0
            while fast < len(a):
                if a[fast] != " ":
                    if slow != 0:
                        a[slow] = " "
                        slow += 1
                    while fast < len(a) and a[fast] != " ":
                        a[slow] = a[fast]
                        slow += 1
                        fast += 1
                else:
                    fast += 1
            return a[:slow]
    
    
        def reverse(self, l, left, right):
            while left < right:
                l[left], l[right] = l[right], l[left]
                left += 1
                right -= 1
        
        def reverse_each_word(self, l):
            start = 0
            for end in range(len(l) + 1):
                if end == len(l) or l[end] == " ":
                    self.reverse(l, start, end - 1)
                    start = end + 1
            

    时间复杂度 O(N)

    空间复杂度 O(N)


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

力扣

通过局部反转+整体反转 达到左旋转的目的。

具体步骤为:

  1. 反转区间为前n的子串
  2. 反转区间为n到末尾的子串
  3. 反转整个字符串
    class Solution:
        def reverseLeftWords(self, s: str, n: int) -> str:
            def reverse_sub(lst, left, right):
                while left < right:
                    lst[left], lst[right] = lst[right], lst[left]
                    left += 1
                    right -= 1
            
            res = list(s)
            end = len(res) - 1
            reverse_sub(res, 0, n - 1)
            reverse_sub(res, n, end)
            reverse_sub(res, 0, end)
            return ''.join(res)

时间复杂度 O(N)

空间复杂度 O(N)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值