代码随想录 Day 8 | 344.反转字符串、541. 反转字符串II、卡码网:54.替换数字

一、344.反转字符串

建议: 本题是字符串基础题目,就是考察 reverse 函数的实现,同时也明确一下 平时刷题什么时候用 库函数,什么时候 不用库函数

题目链接/文章讲解/视频讲解:代码随想录

1. 看到这道题的第一想法

        因为题目要求时间复杂度为O(1),不可以另外申请空间,所以直接调用reverse()函数。

        已AC的代码如下:

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

2. 看完代码随想录的想法

        使用双指针法,首先定义左指针和右指针分别指向字符串数组的头和尾;

        然后进入循环遍历,将左右指针同时向中间移动,直到两个指针指向同一个字符;

        接下来在循环遍历过程中,利用中间变量先存放左指针的元素,然后将右指针值传递给左指针,再将中间变量所存放的原左指针的值传递给右指针,这样就完成了两个元素的交换,每次交换完成后需要将左右指针向中间移动一位;

        最后返回交换完毕后的字符串数组。

class Solution:
    def reverseString(self, s: List[str]) -> None:
        left = 0
        right = len(s)-1

        while left < right:
            mid = s[left]
            s[left] = s[right]
            s[right]=mid
            left += 1
            right -= 1
        return s

二、541. 反转字符串II

建议:本题又进阶了,自己先去独立做一做,然后在看题解,对代码技巧会有很深的体会。

题目链接/文章讲解/视频讲解:代码随想录

1. 看到这道题的第一想法

        首先题意理解模糊不清;其次想要使用双指针法来实现,但是题目条件过于冗杂,并且没有想到将字符串使用list()函数转化为数组形式处理;没有思考在调用反转函数时,是部分反转而不是整个数组进行反转,所以此处应该用到切片;在循环遍历时,应该将指针每次按2k的单位进行移动,并且range函数是左闭右开的,第三个位置可以设置步长,此处就设置为2k。

2. 看完代码随想录的想法

(1)首先在内层定义一个函数,命名为reverse_string,用于对字符串数组进行反转:

        使用双指针法,定义左指针和右指针,初始化存放于数组头和尾;然后以left < right为循环边界条件对数组进行遍历反转;首先定义一个中间遍量wrap,将左指针的值暂存wrap,然后将右指针的值赋值给左指针,然后将wrap存放的原左指针的值赋值给右指针,完成变量交换;接下来完成一次交换需要对左右指针进行更新,分别往中间移动一个单位;最后交换完成返回数组。

(2)对传入的字符串s进行类型转换,通过 list() 函数将它转换为数组类型nums_s。

(3)对数组进行切片循环遍历,设置指针i通过range()函数,[0, len(nums_s)),并且将循环步长设置为2*k;接下来调用上述定义的reverse_string函数对传入的切片数组[i:i+k]进行反转。

(4)拼接完成反转后的数组并返回。

class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        # 定义一个反转函数,用于后续调用

        def reverse_string(nums):
            #定义左右指针用于反转数组
            left = 0
            right = len(nums)-1
            
            while left < right:
                wrap = nums[left]
                nums[left] = nums[right]
                nums[right] = wrap
                
                left += 1
                right -= 1

            return nums

        # 将字符串转换为数组形式,用于后续切片反转
        nums_s = list(s)

        for i in range(0, len(nums_s), 2k):
            nums_s[i:i+k] = reverse_string(nums_s[i:i+k])

        # 将切片并完成反转后的数组拼接起来,最终返回结果
        return ''.join(nums_s)

三、卡码网:54.替换数字

建议:对于线性数据结构,填充或者删除,后序处理会高效的多。好好体会一下。

题目链接/文章讲解:替换数字

1. 看到这道题的第一想法

        没有考虑到数组空间是固定的,要扩充内存需要将size进行增加

        以下代码未AC:

def reverseString(self, s: str) -> str:
    list_s = list(s)
    for i in range(len(list_s)):
        if list_s[i].isnumeric()==True:
            list_s[i] = 'number'
            
        size+=1
    return ''.join(list_s)

2. 看完代码随想录的想法

        如果想把这道题目做到极致,就不要只用额外的辅助空间了! (不过使用Java刷题的录友,一定要使用辅助空间,因为Java里的string不能修改)

        首先扩充数组到每个数字字符替换成 "number" 之后的大小。

        例如 字符串 "a5b" 的长度为3,那么 将 数字字符变成字符串 "number" 之后的字符串为 "anumberb" 长度为 8。

        如图:

        然后从后向前替换数字字符,也就是双指针法,过程如下:i指向新长度的末尾,j指向旧长度的末尾。

 

        为什么要从后向前填充,从前向后填充不行么?

        从前向后填充就是O(n^2)的算法了,因为每次添加元素都要将添加元素之后的所有元素整体向后移动。

        其实很多数组填充类的问题,其做法都是先预先给数组扩容带填充后的大小,然后在从后向前进行操作。

        这么做有两个好处:

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

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值