Day8代码随想录字符串part01-344.反转字符串、541. 反转字符串II、卡码网:54.替换数字、151.翻转字符串里的单词、卡码网:55.右旋转字符串

344.反转字符串(易)

非常像206反转列表,当时是用的双指针方法,需要得知前一个pre的位置和当前的cur进行调换

字符串也是一种数组,所以元素在内存中是连续分布,这就决定了反转链表和反转字符串方式上还是有所差异的。

思路:对于字符串,我们定义最前和最后两个指针,交换位置再向中间移动

  • 时间复杂度: O(n)
  • 空间复杂度: O(1)
class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        双指针方法
        """
        i = 0
        j = len(s) -1
        while i<j:
            swap = s[i]
            s[i] = s[j]
            s[j] = swap
            i+=1
            j-=1

一些补充的非常高效的方式:

# 使用库函数reversed
s[:] = reversed(s)
# 使用reverse()
s.reverse()
# 使用切片
s[:] = s[::-1]
# 使用列表推导
# 从len(s)-1最后一位开始,到0(左闭右开),以-1移动
s[:] = [s[i] for i in range(len(s)-1, -1, -1)]
# 使用栈
stack = []
for char in s:
	stack.append[char]
for i in range(len(s)):
	s[i] = stack.pop()

541. 反转字符串II

在自己尝试编写这道题时犯了3个错误:

(1)交换的方式错误-思考错;

(2)list和str转换错误:reverse_str 方法试图将列表转换回字符串,但使用了 str(s1),这实际上会生成类似于 "['a', 'b', 'c']" 的字符串,而不是你想要的 "abc"。正确的做法是使用 ''.join(s1) 将字符列表连接成字符串。

(3)字符串连接更新处理有误:python中字符串的内容不可以像list一样逐位变化所以要按位处理先转为list,最后再用’’.join(s)的形式转为字符串

(4)本题理解题意之后是发现对[0,2k),[2k, 4k)…这样做前k个的字符反转,如果用while计数过于麻烦了,所以用for循环,for i in range(0, len(s), 2k)以步长2k移动

(5)补充一点知识:

在Python中,[:][::] 都是切片操作符的用法,用于操作列表(以及其他序列类型如字符串和元组)的子集,但它们有细微的差别:

[:] - 复制整个序列: 用于创建序列的一个浅拷贝。

[::] - 带步长的切片操作:长定义了在遍历序列时每次跳过的元素数量。如果步长省略(如在 [::] 中),它默认为 1,这意味着每个元素都被包括,所以在这种情况下,[::] 的效果与 [:] 相同。长定义了在遍历序列时每次跳过的元素数量。如果步长省略(如在 [::] 中),它默认为 1,这意味着每个元素都被包括,所以在这种情况下,[::] 的效果与 [:] 相同。 例如:

lst = [1, 2, 3, 4, 5]

# 创建lst的一个完整副本
copy_lst = lst[:]

# 创建lst的一个完整副本,步长为1
copy_lst_with_step = lst[::]

# 每隔一个元素取值,步长为2
every_second_element = lst[::2]

本题代码:

class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        if len(s) <k:
            return self.reverse_str(list(s))
        if k < len(s) <2*k:
            return self.reverse_str(list(s[0:k]))+s[k:]
        s = list(s) # 注意python中字符串的内容不可以像list一样逐位变化
        for start in range(0, len(s), 2*k): # 重要!当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章
            s[start:start+k] = self.reverse_str(list(s[start:start+k])) # 和上一题是一样的
        return ''.join(s) #注意列表转字符串的方式!!

    def reverse_str(self, s1: list)->str:
        i = 0
        j = len(s1) -1
        while i <j:
            swap = s1[i]
            s1[i] = s1[j]
            s1[j] = swap
            i+=1
            j-=1
        return ''.join(s1)

卡码网:54.替换数字

思路重点:(1)双指针思想:i指向新长度的末尾,j指向旧长度的末尾(2)从后向前填充而不是从前向后填充:从前向后填充就是O(n^2)的算法了,因为每次添加元素都要将添加元素之后的所有元素整体向后移动;很多数组填充类的问题,其做法都是先预先给数组扩容带填充后的大小,然后在从后向前进行操作。

string = input()
s = list(string)
for i in range(len(s)):
    if ord('9')>=ord(s[i])>=ord('0'):
        s[i] = 'number'
print(''.join(s))

151.翻转字符串里的单词

如果直接用split然后倒叙输入,这道题就失去意义了

想一下,我们将整个字符串都反转过来,那么单词的顺序指定是倒序了,只不过单词本身也倒序了,那么再把单词反转一下,单词不就正过来了。

所以解题思路如下:

  • 移除多余空格
  • 将整个字符串反转
  • 将每个单词反转

举个例子,源字符串为:"the sky is blue "

  • 移除多余空格 : "the sky is blue"
  • 字符串反转:"eulb si yks eht"
  • 单词反转:"blue is sky the"

1、双指针移除空格:

类似之前数组中的移除元素的题,快指针fast获取题目要求的字母,慢指针指向要替换的位置

# 伪代码
void removeExtraSpaces(string& s) {//去除所有空格并在相邻单词之间添加空格, 快慢指针。
    int slow = 0;   //整体思想参考https://programmercarl.com/0027.移除元素.html
    for (int i = 0; i < s.size(); ++i) { //
        if (s[i] != ' ') { //遇到非空格就处理,即删除所有空格。
            if (slow != 0) s[slow++] = ' '; //手动控制空格,给单词之间添加空格。slow != 0说明不是第一个单词,需要在单词前添加空格。
            while (i < s.size() && s[i] != ' ') { //补上该单词,遇到空格说明单词结束。
                s[slow++] = s[i++];
            }
        }
    }
    s.resize(slow); //slow的大小即为去除多余空格后的大小。
}

**2、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

感觉应该把c++的双指针移除空格的方式写一遍

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

**思路:**通过 整体倒叙,把两段子串顺序颠倒,两个段子串里的的字符在倒叙一把,负负得正,这样就不影响子串里面字符的顺序了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值