代码随想录算法训练营第八天| 344.反转字符串 541. 反转字符串II 剑指Offer 05.替换空格 151.翻转字符串里的单词 剑指Offer58-II.左旋转字符串

 

344.反转字符串

这道题的要求是不开辟新的内存空间,原地修改输入数组

所以采用了双指针法,一个指针指向首位一个指针指向末位,交换首位末位并且两个指针向内各走一步

记住这种做法

def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        l,r=0,len(s)-1
        while l

541. 反转字符串II

操作字符串前还要明确一件事,字符串属于不可变类型,我们可以去模拟的改变字符串列表。

不然会出现,‘str’ object does not support item assignment

这道题的题意大概是说 以2k为一段,反转前k个字符串;如果最后还剩一小段在 k-2k之间长度,依然反转前k个字符串;如果最后还剩一下段在k长度以下,就直接反转这一段。

 def reverseStr(self, s: str, k: int) -> str:
        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)

其中的反转函数直接用了344反转字符串中的那种从两端两两交换的方法,然后以2k为步长,去遍历整段字符串,去反转每一段前k字符串;由于python切片的语言特性,剩余长度不足k的话它也是可以自动反转的。这样的代码不用判别很多边界条件,看起来逻辑十分简洁。

剑指Offer 05.替换空格

首先很容易想到,str.replace('old', 'new') . 但是由于字符串是不可变类型,这个函数是不会修改原有的str的。在这里把卡哥关于字符串和数组的比较搬过来吧:

{ 这里也给大家拓展一下字符串和数组有什么差别,

字符串是若干字符组成的有限序列,也可以理解为是一个字符数组,但是很多语言对字符串做了特殊的规定,接下来我来说一说C/C++中的字符串。

在C语言中,把一个字符串存入一个数组时,也把结束符 '\0'存入数组,并以此作为该字符串是否结束的标志。

例如这段代码:

char a[5] = "asd";
for (int i = 0; a[i] != '\0'; i++) {
}

在C++中,提供一个string类,string类会提供 size接口,可以用来判断string类字符串是否结束,就不用'\0'来判断是否结束。

例如这段代码:

string a = "asd";
for (int i = 0; i < a.size(); i++) {
}

那么vector< char > 和 string 又有什么区别呢?

其实在基本操作上没有区别,但是 string提供更多的字符串处理的相关接口,例如string 重载了+,而vector却没有。

所以想处理字符串,我们还是会定义一个string类型。}

那么这道题的思路是什么:

首先需要去统计一下有多少空格,接着拿一个数组去扩充到把这些空格都填成字符后的大小,原始空格只要增加两个空格位置就行了. nums.extend()函数等于 += ,因此追加的元素也要是[ ].

接着定义两个指针, l, r 分别指向原始字符串s的尾端 和扩容后的数组nums的尾端,

然后用 l 去遍历原始s, while l >= 0:

                                               l -= 1

如果说nums[l] != '  ', 把nums[l]的值赋给nums[r], r -= 1, 后退一位

如果说 nums[l] == '  ' , 这个时候要填%20, nums[r-2]  nums[r-1] nums[r] 要填成 % 2 0,此时r 后退三位

def replaceSpace(self, s: str) -> str:
        n_space = s.count(' ')
        res = list(s)
        res.extend([' '] * n_space * 2)
        l, r = len(s) - 1, len(res) - 1
        while l >= 0:
            if res[l] != ' ':
                res[r] = res[l]
                r -= 1
            else:
                res[r-2:r+1] = '%20'
                r -= 3
            l -= 1
        return ''.join(res)

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

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

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

这么做有两个好处:

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

151.翻转字符串里的单词(小米测开的面试遇到)

这个题以我七八月份刷牛客网上的华为机考题库的经验来说,我是可以用模拟的手段去做的。就是先把字符串以空格为界,变成数组;然后拿数组去把每个单词倒序输出;最后再转成字符return。这时空复杂度都是O(n)。

代码大概长这个样子:

def reverseWords(self, s: str) -> str:
        res = []
        s = list(s.split())
        for i in range(len(s)-1, -1, -1):
            res.append(s[i])
        str_res = ''
        for i in range(len(res)):
            str_res += str(res[i])
            str_res += ' '
        str_res = str_res.rstrip()
        return str_res

卡哥的思路是让我们锻炼字符串的基本操作的,是先把字符串整体反转,然后把每个单词中的字符进行反转。这个纯不用库函数的写法我不想在抄了。纯属是哈人,就算是面试,面试官也不会想让你这样写,但是思路可以抄一下

可以直接用两个切片的反转,先整体字符串反转一下,然后遍历的时候,每个单词再用切片反转一下。

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

首先,切片是可以过的

def reverseLeftWords(self, s: str, n: int) -> str:
        length = len(s)
        return s[n:length] + s[:n]

 其次,正经思路是局部反转加全局反转

代码随想录算法训练营第八天| 344.反转字符串 541. 反转字符串II 剑指Offer 05.替换空格 151.翻转字符串里的单词 剑指Offer58-II.左旋转字符串_第1张图片

def reverseLeftWords(self, s: str, n: int) -> str:
        s = list(s)
        s[0:n] = list(reversed(s[0:n]))
        s[n:] = list(reversed(s[n:]))
        s.reverse()
        
        return "".join(s)

当然我觉得也可以自己写一下这个reverse函数

你可能感兴趣的:(代码随想录算法训练营打卡,算法,python)