算法训练Day8| LeetCode344. 反转字符串(双指针);541. 反转字符串II(模拟);offer5. 替换空格(双指针后序);151.反转字符串中的单词(综合);off58.左旋字符串

本文详细解析了四道关于字符串反转的算法题目,包括LeetCode344的双指针反转,541的反转字符串II,剑指Offer5的替换空格,151的反转字符串中的单词以及剑指Offer58II的左旋转字符串。文章介绍了各种反转策略,如整体反转、局部反转、模拟实现等,并探讨了在不同场景下使用库函数的考量。同时,文章强调了理解算法实现原理的重要性,以及如何在面试中合理使用库函数。
摘要由CSDN通过智能技术生成

LeetCode344. 反转字符串

链接:344. 反转字符串 - 力扣(LeetCode) 

1. 思路

在反转链表中,用了双指针的方法,所以,反转字符串,仍然是用双指针的方法,只不过字符串的反转,要比链表更简单。因为字符串也是一种数组,所以元素在内存中是连续分布,这就决定了反转链表和反转字符串方式上还是有所差异的。

对于字符串,我们定义两个指针(也可以说是索引下标),一个从字符串前面,一个从字符串后面,两个指针同时向中间移动,并交换元素。

2. 代码实现

# time:O(N);space: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:
            s[left],s[right] = s[right],s[left]
            left += 1
            right -= 1
        return s

3. 复杂度分析

时间复杂度: O(N)

两个指针一个从头往后,一个从后往前,直到他们相遇,总共会把长度为N的字符数组全部遍历一遍,因此时间复杂度为O(N);

空间复杂度:O(1)

原地修改的字符数组,没有占用和创建其他空间,只有两个常数级的指针。

4. 思考

  1. 关于调用库函数,对于这道题目直接用一个库函数 reverse,调一下直接完事了, 相信每一门编程语言都有这样的库函数。如果这么做题的话,这样大家不会清楚反转字符串的实现原理了。但是也不是说库函数就不能用,是要分场景的。如果在现场面试中,我们什么时候使用库函数,什么时候不要用库函数呢?如果题目关键的部分直接用库函数就可以解决,建议不要使用库函数。毕竟面试官一定不是考察你对库函数的熟悉程度, 如果使用python和java 的同学更需要注意这一点,因为python、java提供的库函数十分丰富。如果库函数仅仅是 解题过程中的一小部分,并且你已经很清楚这个库函数的内部实现原理的话,可以考虑使用库函数。建议大家平时在leetcode上练习算法的时候本着这样的原则去练习,这样才有助于我们对算法的理解。不要沉迷于使用库函数一行代码解决题目之类的技巧,不是说这些技巧不好,而是说这些技巧可以用来娱乐一下。真正自己写的时候,要保证理解可以实现是相应的功能;
  2. 也可以不用while循环,用for循环,for i in range(right//2) ; 但事实证明时间空间复杂度来说,用while循环是更优解,也通俗易懂。

Reference

代码随想录 (programmercarl.com)

本题学习时间:30分钟。


 LeetCode541. 反转字符串II

链接: 541. 反转字符串 II - 力扣(LeetCode)

1. 思路

乍一看也是反转字符串,但是给它加上了一些特殊的规则,这道题实际上也不涉及到算法层面的知识,就是模拟实现规定的规则就可以了。

一些同学可能为了处理逻辑:每隔2k个字符的前k的字符,写了一堆逻辑代码或者再搞一个计数器,来统计2k,再统计前k个字符。其实在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。因为要找的也就是每2 * k 区间的起点,这样写,程序会高效很多。所以当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。

那么这里具体反转的逻辑我们要不要使用库函数呢,其实用不用都可以,使用reverse来实现反转也没毛病,毕竟不是解题关键部分。

最后尾部有两种情况,一种是凑足了K个,另一种是没凑足K个,需要注意分开处理。

第一种写法:

  1. 首先,写一个子函数,用于反转输入的字符串,代码和上一题4.1非常类似
  2. **当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章。**使用range(start,end,step)来确定需要调换的位置,左闭右开[start,end)
  3. 因为string类型,是不支持子函数中的交换指令slides[left],slides[right] = slides[right],slides[left],不支持item assignment,所以要先把这个字符串转换为数组操作。直接用res = list(string_name) 就可以了。
  4. 对于字符串s=’abc’ ,如果使用s[0:999] ⇒ ‘abc’ 字符串末尾如果超过最大长度,则会返回至,字符串最后一个值,这个特性可以避免一些边界条件的处理。
  5. 用切片进行整体替换,而不是一个个替换
  6. “” .join (res)可以把数组转换为字符串

第二种写法:

  1. 首先也写一个子函数,输入参数为数组S,然后需要反转的区间,左闭右闭;
  2. 然后为了便于操作,把字符串变成字符数组,直接写s = list(s)就可以;最后把result= “”.join(s),就又可以把字符数组变成字符串返回了;
  3. 初始化要反转的区间,i和j,检查j是否还在数组范围内,如果在,就可以凑足K个,直接调用reverse反转;
  4. 如果j已经不在数组范围内了,但是i还在,就说明最后凑不足K个,直接把最后一段翻转即可;
  5. 返回转换后最后的字符串结果。

2. 代码实现

第一种写法:

# for循环跳跃取值+数组切片赋值+双指针定义子函数
# time:O(N);space:O(N)
class Solution(object):
    def reverseStr(self, s, k):
        """
        :type s: str
        :type k: int
        :rtype: str
        """
        def reverseSlides(slides):
            lef
  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值