代码随想录算法训练营第八天|344.反转字符串 541. 反转字符串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"]

思路:首先排除最简单的暴力法,需要额外的O(n)空间,不是原地修改。由于题目要求原地修改数组,那么立马就想到交换字符,即头和尾交换字符。设置left和right 指针,每做一次循环后进行一次相向平移,直到left和right指针相遇结束。

代码如下: 

class Solution:

    def reverseString(self, s: List[str]) -> None:

        """

        Do not return anything, modify s in-place instead.

        """

        left, right = 0, len(s)-1

        while left < right:

            s[left], s[right] = s[right], s[left]

            left += 1

            right -= 1

这个题目很基础,所以趁此多接触一些其他的方法。

使用栈(后进先出,所以pop后尾会变成头,以此实现倒序,但理解应该是用了额外空间的):

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()

直接使用自带的函数reversed:

class Solution:

    def reverseString(self, s: List[str]) -> None:

        """

        Do not return anything, modify s in-place instead.

        """

        s[:] = reversed(s)

使用自带的字符串reverse函数:

class Solution:

    def reverseString(self, s: List[str]) -> None:

        """

        Do not return anything, modify s in-place instead.

        """

        # 原地反转,无返回值

        s.reverse()

以上reversed和reverse进行区分:

reverse() 方法

  • 是列表(list)对象的一个方法。
  • 用于就地(in-place)反转列表中的元素,也就是说它直接修改原列表,而不返回新列表。
  • 没有返回值(即返回 None)。
  • 只能用于可变序列,比如列表。

reversed() 函数

  • 是一个内建函数,可以用于反转任何支持迭代的对象,如列表、元组、字符串等。
  • 不会就地修改原序列,而是返回一个新的反转迭代器。
  • 需要通过 list() 函数或其他方式来转换为列表或其他数据结构。
  • 可以用于不可变序列,如元组。

使用切片:

class Solution:

    def reverseString(self, s: List[str]) -> None:

        """

        Do not return anything, modify s in-place instead.

        """

        s[:] = s[::-1]

使用列表推导:

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)]


541. 反转字符串II

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

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

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

示例:

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

思路其实没有什么特殊的,自然就是起点往后k个字符进行reverse,然后令起点往后移2k个字符,然后循环重复以上过程。需要注意的是,需要分两种情况:【起点+k大于字符串尾部】和【起点+k小于字符串尾部】,如果大于则直接将剩下部分全部反序,如果小于则可以顺利执行以上过程。

思路一直是这样没问题,但是由于对str类型的操作不够熟练,导致反复在用法上卡bug,例如:错误信息 TypeError: 'str' object does not support item assignment 表示你尝试对一个字符串对象进行项赋值操作,但是字符串(str)在 Python 中是不可变的(immutable),这意味着你不能改变字符串中的单个字符。

在 Python 中,字符串被视为一系列字符的序列,但是一旦创建,你就不能更改它。尝试像这样修改字符串中的某个位置的字符会引发类型错误:

python

s = "hello"

s[0] = "H"  # 这会引发 TypeError

如果你需要修改字符串中的字符,你可以通过创建一个新的字符串来实现。例如,你可以使用字符串切片和拼接来创建一个修改后的字符串:

python

s = "hello"

s = "H" + s[1:]  # 创建一个新的字符串 "Hello"

如果你在处理列表中的字符串,并且想要交换两个字符串元素的位置,你可以这样做:

python

s = ["hello", "world"]

s[0], s[1] = s[1], s[0]  # 交换列表中的两个元素

在这个例子中,s 是一个列表,列表是可变的,所以你可以更改列表中的元素。这里我们交换了列表中第一个和第二个元素的位置。

如果你确实需要修改字符串中的字符,并且想要原地修改(in-place),你需要将字符串转换为列表(因为列表是可变的),修改列表,然后再将列表转换回字符串。这里是如何做到这一点的例子:

python

s = list("hello")  # 将字符串转换为列表

s[0], s[1] = s[1], s[0]  # 现在可以交换元素了

s = "".join(s)  # 将列表转换回字符串

在这个例子中,我们首先将字符串 "hello" 转换为字符列表 ['h', 'e', 'l', 'l', 'o'],然后交换了列表中的第一个和第二个元素,最后使用 "".join(s) 将列表转换回字符串 "elloh"

另外记录一个当时在debug的时候自己也想到的思路,但是因为字符串操作太生疏没通过的例子,在这里直接附代码不复现了:

class Solution:

    def reverseStr(self, s: str, k: int) -> str:

        # Two pointers. Another is inside the loop.

        p = 0

        while p < len(s):

            p2 = p + k

            # Written in this could be more pythonic.

            s = s[:p] + s[p: p2][::-1] + s[p2:]

            p = p + 2 * k

        return s

替换数字

给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。

例如,对于输入字符串 "a1b2c3",函数应该将其转换为 "anumberbnumbercnumber"。

对于输入字符串 "a5b",函数应该将其转换为 "anumberb"

输入:一个字符串 s,s 仅包含小写字母和数字字符。

输出:打印一个新的字符串,其中每个数字字符都被替换为了number

样例输入:a1b2c3

样例输出:anumberbnumbercnumber

数据范围:1 <= s.length < 10000。

思路:很简单,对字符串进行遍历,遍历到数字将其转化为’number’,python直接使用字符串切片进行重新拼接即可。而在C++等可以直接对str进行修改的语言里,可以先遍历字符串统计数字的个数,然后再根据需要扩容原字符串,需要注意的是,在这个情况下,要进行替换操作一定应该倒序操作,因为只有倒序操作复杂度才是O(n),如果正序操作的话需要额外遍历将索引后面的字符串后移,导致复杂度增加变成O(n²)。所以记录一下C++写法:

#include <iostream>using namespace std;int main() {

    string s;

    while (cin >> s) {

        int sOldIndex = s.size() - 1;

        int count = 0; // 统计数字的个数

        for (int i = 0; i < s.size(); i++) {

            if (s[i] >= '0' && s[i] <= '9') {

                count++;

            }

        }

        // 扩充字符串s的大小,也就是将每个数字替换成"number"之后的大小

        s.resize(s.size() + count * 5);

        int sNewIndex = s.size() - 1;

        // 从后往前将数字替换为"number"

        while (sOldIndex >= 0) {

            if (s[sOldIndex] >= '0' && s[sOldIndex] <= '9') {

                s[sNewIndex--] = 'r';

                s[sNewIndex--] = 'e';

                s[sNewIndex--] = 'b';

                s[sNewIndex--] = 'm';

                s[sNewIndex--] = 'u';

                s[sNewIndex--] = 'n';

            } else {

                s[sNewIndex--] = s[sOldIndex];

            }

            sOldIndex--;

        }

        cout << s << endl;       

    }}

Python写法:

可以先将字符串转换为list,由于每个元素都是一个单独的字符,可以直接将字符替换为字符串’number’然后再重新拼接,所以不涉及平移的操作,直接令number[i]=’number’即可。代码如下:

class Solution:

    def change(self, s):

        lst = list(s) # Python里面的string也是不可改的,所以也是需要额外空间的。空间复杂度:O(n)。

        for i in range(len(lst)):

            if lst[i].isdigit():

                lst[i] = "number"

        return ''.join(lst)

以下是ACM输入模式下,自己的复现:

def main():

    data = input()

    d = list(data)

    for i in range(len(d)):

        if d[i].isdigit(): # 也可以用ascii码, if ord("0") <= ord(d[i]) <= ord("9"):

            d[i] = 'number'

    data = "".join(d)

    print(data)

    

    

    

if __name__ == "__main__":

    main()

代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值