代码随想录算法训练营第8天 | ● 344.反转字符串 ● 541. 反转字符串II ● 卡码网:54.替换数字 ● 151.翻转字符串里的单词 ● 卡码网:55.右旋转字符串


前言

讲解链接

344.反转字符串

在这里插入图片描述

思路 双指针

讲解:反转字符串依然是使用双指针的方法,只不过对于字符串的反转,其实要比链表简单一些。因为字符串也是一种数组,所以元素在内存中是连续分布,这就决定了反转链表和反转字符串方式上还是有所差异的
如果是c++,可以用库函数reverse()函数,也可以用swap函数来交换两个数,但是本题肯定是不希望使用库函数,肯定是想让大家了解库函数的内部实现。

本题正式解体思路和我自己的思路一样,很简单;
使用左右双指针:都是从最左边最右边开始同时往中间移动;
边界情况:是<n//2还是<=n//2,代入检验就行
【到这里要学会了快速检验;例如长度为4,n//2为2,肯定是<;如果是5的话,也是截止到1的index,所以<】

python交换位置的方法

  1. 使用元组交换:a, b = b, a

自己写的小细节:
3.

方法一 双指针

"""
我自己写的,元组交换
"""
class Solution(object):
    def reverseString(self, s):
        """
        :type s: List[str]
        :rtype: None Do not return anything, modify s in-place instead.
        """
        n = len(s)
        left, right = 0, n-1
        while left < n//2 :
            s[left],s[right] = s[right],s[left]
            left += 1
            right -= 1
        
        return s

方法二 使用栈、slice、reverse、reversed等

但是我觉得这个方法多了一个栈,需要多开辟一个空间,但是速度快

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

调用函数使用slice切片、reverse、reversed

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

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        s[:] = reversed(s)
# 列表推导
s[:] = [s[i] for i in range(len(s) - 1, -1, -1)]
# range
class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        n = len(s)
        for i in range(n // 2):
            s[i], s[n - i - 1] = s[n - i - 1], s[i]

541. 反转字符串II

在这里插入图片描述

思路

核心想法:for循环的时候每一次迭代都是2k来进行迭代,i += (2 * k);而不是习惯性的i++,然后再判断是否有需要翻转的区间;
主要思路:固定i,判断i+k是否存在,存在就翻转,不存在就有多少翻多少
注意小细节:

  1. 一般库函数中的reverse都是左闭右开
  2. 翻转的时候,传入数组s,起始index
  3. 注意边界:(仍然是代入检验)i+k是<还是<=numsize?A:因为是左闭右开,所以包括=

在这里插入图片描述

方法一 自己写的

直接参考后面的,自己写的修修补补
自己写的注意点

  1. python数组一段进行reverse函数的实现:我是额外写的一个使用range的reverse函数

  2. python的slice是n[start:stop:step]但是注意不到stop,别忘了。。🧁

  3. 定义函数的时候不要写出这种错误啊:def reverse1(self,s,i,i+k):很离谱的。。。。k是哪来的??应该是def reverse1(self,s,i,k)==

  4. 报错:是因为python不可以直接处理字符串,不可以改动,要转换成list(S),最后return ‘’.join(S)才可以

    在这里插入图片描述
    5. 用了while之后每一种情况都需要加i+= 2k,我一开始continue忘记写了

class Solution(object):

    def reverse1(self,s,i,k):
        s[i:k] = [s[j] for j in range(k-1,i-1,-1)]

    def reverseStr(self, s, k):
        """
        :type s: str
        :type k: int
        :rtype: str
        """
        n = len(s)
        i = 0
        s = list(s)
        while i < n:
            # 判断i+k的情况
            if i+k <= n:
                self.reverse1(s,i,i+k)
                i += 2*k #莫要漏了
                continue #第二种情况,有k个字符串,满足了就进入下一个循环
            #如果i+k超过范围了,就直接倒
            self.reverse1(s,i,n)
            i += 2*k
        return ''.join(s)

方法二 参考代码-多学习

第一种:利用双指针;最重要的是超过的切片python会返回最大长度,不用担心边界条件,艹;
对于字符串s = ‘abc’,如果使用s[0:999] ===> ‘abc’。字符串末尾如果超过最大长度,则会返回至字符串最后一个值,这个特性可以避免一些边界条件的处理。

class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        """
        1. 使用range(start, end, step)来确定需要调换的初始位置
        2. 对于字符串s = 'abc',如果使用s[0:999] ===> 'abc'。字符串末尾如果超过最大长度,则会返回至字符串最后一个值,这个特性可以避免一些边界条件的处理。
        3. 用切片整体替换,而不是一个个替换.
        """
        def reverse_substring(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 cur in range(0, len(s), 2 * k):
            res[cur: cur + k] = reverse_substring(res[cur: cur + k])
        
        return ''.join(res)

第二种:代码很简洁,只需要把中间一段[::-1]就行,天才!

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

卡码网:54.替换数字

题目链接
在这里插入图片描述

思路

本题针对c++语言才有意义,python完全没有用,python太好写了;我已经在考虑改语言了。啊好烦;

方法一

python就很简单,注意判断语句**isdigit()**背诵一下就行
或者用s[i] >= ‘0’ && s[i] <= '9’也可以(python加个ord,我这是扣的c++代码)

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)

方法二 c++

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;       
    }
}

拓展 c++

在这里插入图片描述
在这里插入图片描述

151.翻转字符串里的单词

在这里插入图片描述

思路

读题尤其注意:单词之间可能会有多个空格的,需要变成一个空格
简单方法:

  1. 空间复杂度不为O(1)也就是创建一个新的数组,失去了这道题目的意义
  2. 调用库函数:比如使用split,然后concat使用‘ ’,也可以不用
  3. 使用erase来删除空格:也不,因为erase删除的时间复杂度为O(n)

总体思路:首先使用快慢指针将多余的空格去掉,然后先先总体reverse之后再对单个字母reverse,得到我们想要的结果

举个例子,源字符串为:"the sky is blue "
移除多余空格 : “the sky is blue”
字符串反转:“eulb si yks eht”
单词反转:“blue is sky the”
在这里插入图片描述

方法一: 针对python

class Solution:
    def reverseWords(self, s: str) -> str:
        # 删除前后空白
        s = s.strip()
        # 反转整个字符串
        s = s[::-1]
        # 将字符串拆分为单词,并反转每个单词
        s = ' '.join(word[::-1] for word in s.split())
        return s

使用双指针

class Solution:
    def reverseWords(self, s: str) -> str:
        # 将字符串拆分为单词,即转换成列表类型
        words = s.split()

        # 反转单词
        left, right = 0, len(words) - 1
        while left < right:
            words[left], words[right] = words[right], words[left]
            left += 1
            right -= 1

        # 将列表转换成字符串
        return " ".join(words)

方法二 按照讲解的来

因为python的for语句执行逻辑是:无论如何处理fast指针,只要到for语句,它都是一个一个往后移动;比如说我已经处理到3了,过了一下for,又从1开始。
所以讲解完全不能用;不写了,根本没时间。
python还有一个限制是,没有resize,去除空格之后多余的部分删除不了
会出现下面的结果
在这里插入图片描述

class Solution(object):
    def reverse1(self,s,i,k):
        s[i:k] = [s[j] for j in range(k-1,i-1,-1)]
    def removeExtraSpaces(self,s):
        slow, fast = 0, 0
        # for fast in range(0,len(s)):#绝对不能用for,python里面for会一个一个加的
        while fast < len(s):

            if s[fast] != ' ':
                if slow !=0:#手动给单词开头加空格
                    s[slow] = ' '
                    slow += 1

                while fast < len(s) and s[fast] != ' ':
                    # print("slow "+s[slow]+" "+str(slow))
                    s[slow] = s[fast]
                    fast += 1
                    slow += 1
            else:
                fast += 1

    def reverseWords(self, s):
        """
        :type s: str
        :rtype: str
        """
        s = list(s)
        n = len(s)
        self.removeExtraSpaces(s)
        print(s)
        self.reverse1(s,0,n)
        #下面开始翻转单个字符,也是使用双指针的方法
        start = 0#慢指针
        for i in range(0,n+1): #左闭右开
            if i == n or s[i] == ' ':#如果到最后了或者是空格,说明可以翻转了
                self.reverse1(s,start,i)
                start = i + 1
        print(s)
        return s

卡码网:55.右旋转字符串

在这里插入图片描述

思路

使用整体反转+局部反转就可以实现反转单词顺序的目的
首先整体翻转一下,然后将两个部分分别翻转就可以得到想要的结果【不懂看讲解】
卡码网的代码需要自己写输入输出,海康的题目就是这样的🥚
自己写的错误:记得输入的k要加一个int

#获取输入的数字k和字符串
k = int(input())
s = input()

#通过切片反转第一段和第二段字符串
#注意:python中字符串是不可变的,所以也需要额外空间
s = s[len(s)-k:] + s[:len(s)-k]
print(s)

总结

c++和python还是差太多了,空间分配不一样,二刷一定要用c++,一刷了解算法思想

  • 41
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第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、付费专栏及课程。

余额充值