力扣Day8(2.13)| 第四章 字符串 (344. 反转字符串 541. 反转字符串II 剑指Offer 05.替换空格 151.翻转字符串里的单词 剑指Offer58-II.左旋转字符串)

题一:344. 反转字符串(easy)

链接

题目链接:
视频链接:
文章链接:

视频总结

本题非常简单,唯一需要注意的是库函数的使用时机,只要不是题目的关键步骤,且库函数已经知道如何实现,那么还是可以使用的

编程思路

Me:
  1. 双指针,一个0一个len减一
    while l<r 等于时不操作,互换
卡尔:

注意尝试while和for的写法

力扣实战

思路一:

 class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        # for 循环的写法,和while循环的写法的思路如出一辙
        l = 0
        r = len(s)-1
        for i in range(len(s)):
            if i < r:
                s[i],s[r] = s[r],s[i]      
                r -= 1
            else:
                break
        return s
        

题二: 541. 反转字符串II

链接

题目链接:
视频链接:
文章链接:

视频总结

关键点

编程思路

Me:
  1. 1.写一个反转字符串的函数
    2.获取字符串长度,根据要求截取字符串,然后过定义函数
    3.拼接几个部分

疑问:最后剩余的>2k怎么办

卡尔:

1.for循环的自加很多人默认为i+=1,此处+=2k会比较好。即操作数组或者字符串是一段一段的处理时,i可以一段段跳,而不是只加一。
2.定义reverse函数,要么传入完整字符串,那么就要讨论情况,然后截取,然后反转。或者在定义reverse函数时也输入反转的起点和终点

力扣实战

思路一:

 class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        l = len(s)
        i = 0
        s=list(s)

        def reverse1(m,n,s):  # 翻转字符串s的i到j段.其中m和n是索引
            while m < n:
                s[m],s[n]=s[n],s[m]
                m += 1
                n -= 1
            return s
            
        while i<l:
            if l-i>2*k:  # 长度大于2k,此处不可等于,等于时翻转后就得输出了
                s = reverse1(i,i+k-1,s)
                i += 2*k
            elif k<=l-i<=2*k:  # 大于等于k小于2k
                s = reverse1(i,i+k-1,s)
                return ''.join(s) # 若写成s,则结果为["c","b","a","d","e","f","g"],
            else:
                s = reverse1(i,l-1,s)
                return ''.join(s)   #若写str(s)结果是"['c', 'b', 'a', 'd', 'e', 'f', 'g']",也就是我们需要把["c","b","a","d","e","f","g"]转为"cbadefg"
        
# 反思1:

思路二:

 #官方解答,第二段无需讨论,非常精彩,其次for的每次步进非1的方法也可以学习!
 class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        t = list(s)
        for i in range(0, len(t), 2 * k):
            t[i: i + k] = reversed(t[i: i + k])
        return "".join(t) # join方法指把t里的对象以""里的东西分隔在组成一个字符串,此处双引号里啥也没有


文档总结

1. 

题三:剑指Offer 05.替换空格

链接

题目链接:
视频链接:
文章链接:

视频总结

关键点

编程思路

Me:

1.一层for循环,遇到空格时换(换了之后索引会变,所以思路错误)

卡尔:
  1. 字符串扩充0,空格替换后的长度来算0的个数
  2. 从后往前,(而不是从前往后,从前往后后面的元素都要移动),一个指针在老数组末尾,一个在新的末尾

力扣实战

思路一:

class Solution:
    def replaceSpace(self, s: str) -> str:
        #思路:一次遍历获得空格数k;在结尾补充2k个0(加上前面的k个正好3k个,)双指针      
        ##i指向老字符串的末尾,j指向新字符串的末尾,从后向前遍历;当i处不为空格时移到末尾;等于空格时末尾覆盖
        #三个字符。 
        count=0
        m = len(s)-1   
        for i in s: # 获得空格数,错因:‘’里面没有写空格‘ ’
            if i == ' ':
                count+=1
        s = s+'00'*count
        l = len(s)-1  
        s = list(s)
        while m>-1:
            if s[m] !=' ':
                s[l]=s[m]
                l-=1
            else:
                s[l-2:l+1]=['%','2','0']
                l-=3
            m-=1
        return ''.join(s)
        
# 反思1:

思路二:

 #另一种写法,部分库函数不一样
 class Solution:
    def replaceSpace(self, s: str) -> str:
        counter = s.count(' ')
        
        res = list(s)
        # 每碰到一个空格就多拓展两个格子,1 + 2 = 3个位置存’%20‘
        res.extend([' '] * counter * 2)
        
        # 原始字符串的末尾,拓展后的末尾
        left, right = len(s) - 1, len(res) - 1
        
        while left >= 0:
            if res[left] != ' ':
                res[right] = res[left]
                right -= 1
            else:
                # [right - 2, right), 左闭右开 这里很重要!!左闭右开!!
                res[right - 2: right + 1] = '%20' 	# 也可以是一个列表,里面的三个元素是字符串,可debug观看。观看后可知两种操作都合法
                right -= 3
            left -= 1
        return ''.join(res)

文档总结

1. 其实很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
这么做有两个好处:1.不用申请新数组。2.从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。时间复杂度,空间复杂度均超过100%的用户。
2.在cpp中字符串和数组是有区别的,虽然字符串可以视为字符数组;应该继续研究一下python中的字符串和数组的区别

题四:151.翻转字符串里的单词

链接

题目链接:
视频链接:
文章链接:

视频总结

关键点

编程思路

Me:无思路
卡尔:

删空格:双指针,快指针遍历字符串,找到我们需要移动的对象(非空格),慢指针指向待移动的位置,初始为0,而且还要在每个单词之间留下一个空格,最后一步我没想到
然后把整体翻转,再以空格为界来翻转。

力扣实战

思路一:

 class Solution:
    def reverseWords(self, s: str) -> str:
        def trim_space(s):  #删去空格
            left = 0
            right = len(s)-1
            while left<right and s[left] ==' ':
                left += 1 
            while left<right and s[right] == ' ':
                right -= 1
            l = r = left
            out =[]
            while l <=right:
                if s[l] != ' ':   # if elif else同时出现和if if if 同时出现的逻辑不一样,前者三个子语句只会执行一条,后者满足调节就都会执行
                    out.append(s[l])
                elif out[-1] != ' ':  #执行到这里则说明if没执行,也就是s[l]此时为空,那么此时判断out里最后一个是不是空,如果不是则说明前一个单词到了末尾,可以把当前l处的空格放进out作为单词间的分割空格,若遇到了连续的空格,过判断语句发现out末尾是空格,则跳过,也就避免了单词中间的连续的空格
                    out.append(s[l]) 
                l += 1
            return out
        tem = trim_space(s)
        tem.reverse()
        i = j = 0
        while i<len(tem):
            if tem[i] == ' ':	#找到第一个空格,然后对这一段单词翻转
                tem[j:i]=list(reversed(tem[j:i])) # 此处写成tem[j:i].reverse()就错误,这不是部分翻转的代码,这样写数组保持不变
                j = i+1
            elif i == len(tem)-1: # 必须考虑走到末尾的情况,否则最后一个单词不会翻转
                tem[j:i+1]=list(reversed(tem[j:i+1]))	# reversed返回的是一个容器,故需要转成列表
            i+=1
        return ''.join(tem)
        

        
# 反思1:

题五: 剑指Offer58-II.左旋转字符串

链接

题目链接:
文章链接:

视频总结

力扣实战

思路一:

# s长度×2,然后截取一部分,时间上最短
 class Solution:
    def reverseLeftWords(self, s: str, n: int) -> str:
        l=len(s)
        s = s+s
        tem = list(s)
        return ''.join(tem[n:n+l])
        
# 随想录文档更牛皮
# 方法一:可以使用切片方法
class Solution:
    def reverseLeftWords(self, s: str, n: int) -> str:
        return s[n:] + s[0:n]

思路二:

# 先翻转前n,再翻转n后,再翻转全部
 class Solution:
    def reverseLeftWords(self, s: str, n: int) -> str:
        # 注意这九行的写法,参照了上一题改了无数次。这一思路随想录上的写法和我的写法一模一样,说明字符串转成列表在操作确实没走弯路,也说明了字符串的自由度没有列表那么高
        l=len(s)    # 获取长度
        s=list(s)   # 字符串转为列表以便于数组翻转操作
        s[0:n] = list(reversed(s[0:n])) # 翻转前n个和n以后的
        s[n:] = list(reversed(s[n:]))
        s.reverse() #整体翻转
        return ''.join(s)   #把s里每个个体以‘’里的东西分隔开

思路三:

# 方法三:如果连reversed也不让使用,那么自己手写一个
class Solution:
    def reverseLeftWords(self, s: str, n: int) -> str:
        def reverse_sub(lst, left, right):
            while left < right:
                lst[left], lst[right] = lst[right], lst[left]
                left += 1
                right -= 1
        
        res = list(s)
        end = len(res) - 1
        reverse_sub(res, 0, n - 1)
        reverse_sub(res, n, end)
        reverse_sub(res, 0, end)
        return ''.join(res)

# 同方法二
# 时间复杂度:O(n)
# 空间复杂度:O(n),python的string为不可变,需要开辟同样大小的list空间来修改

思路四:

#方法四:考虑不能用切片的情况下,利用模+下标实现
class Solution:
    def reverseLeftWords(self, s: str, n: int) -> str:
        new_s = ''
        for i in range(len(s)):
            j = (i+n)%len(s)
            new_s = new_s + s[j]
        return new_s

文档总结

1. 文档给了三个不错的写法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值