算法刷题打卡007 | 字符串相关题目5道

LeetCode 344 反转字符串

题目链接:344. 反转字符串 - 力扣(Leetcode)

 由于题目要求原地修改,因此必须使用双指针进行前后交换,实现反转字符串(列表形式):

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:
            # left == right时中间字符不用反转
            s[left], s[right] = s[right], s[left]
            left += 1
            right -= 1

 时间复杂度是O(n)。

LeetCode 541 反转字符串II

题目链接:541. 反转字符串 II - 力扣(Leetcode)

反转字符串进阶,其实就是限制条件多了些,分区间进行反转:

class Solution:
    def reverse(self, s, start, end):
        # 左闭右开区间
        end -= 1
        while start < end:
            s[start], s[end] = s[end], s[start]
            start += 1
            end -= 1

    def reverseStr(self, s: str, k: int) -> str:
        i, n = 0, len(s)
        s = list(s)  # 转为字符列表(python字符串无法直接修改)
        while i < n:
            end = min(n, i + k)
            self.reverse(s, i, end)  
            i += 2 * k
        return ''.join(s)

 通过min确定反转的右边界(注意区间的开闭特性),可以直接将最终小于k的部分也一起处理,总体时间复杂度也是O(n)。

LeetCode 剑指Offer 05 替换空格

题目链接:剑指 Offer 05. 替换空格 - 力扣(Leetcode)

基本做法是遍历一遍字符串,把对应空格按要求替换即可。Python中需要先将字符串转换为字符列表,才能做替换操作:

class Solution:
    def replaceSpace(self, s: str) -> str:
        s = list(s)
        for i in range(len(s)):
            if s[i] == ' ':
                s[i] = '%20'
        return ''.join(s)

利用字符串的库函数split,可以先将字符串按空格划分为 单词,再用目标字符串连接起来:

class Solution:
    def replaceSpace(self, s: str) -> str:
        # split方法
        s = s.split()
        return '%20'.join(s)

 但第二种方法对一些奇奇怪怪的测试用例不管用,比如s全是空格,或者s=" 0 ",需要在代码中做一些特殊处理。

尝试用题解的扩展空间方法:

class Solution:
    def replaceSpace(self, s: str) -> str:
        c = s.count(' ')  # 空格计数
        s , n = list(s), len(s)
        s.extend([' '] * c * 2)
        left, right = n - 1, len(s) - 1  # left,right分别是原数组末尾和扩展后的数组末尾
        while left >= 0:
            if s[left] != ' ':
                s[right] = s[left]
                right -= 1
            else:
                s[right - 2: right + 1] = ['%', '2', '0']
                right -= 3
            left -= 1
        return ''.join(s) 

 

LeetCode 151 翻转字符串里的单词

题目链接:151. 反转字符串中的单词 - 力扣(Leetcode)

之前做过一次题,写得比较繁琐,单独写一个函数删除多余的空格,又设了很多变量和判断条件:

class Solution:
    def reverse(self, s, start, end):
        while start < end:
            s[start], s[end] = s[end], s[start]
            start += 1
            end -= 1

    def remove_emptys(self, s):
        slow, f = 0, 0  # 快慢指针初始化
        # 去除前面多余的空格
        while len(s) > 0 and f < len(s) and s[f] == ' ':
            f += 1
        # 去除中间多余的空格
        for fast in range(f, len(s)):
            if fast-1 > 0 and s[fast-1] == s[fast] and s[fast] == ' ':
                continue
            else:
                s[slow] = s[fast]
                slow += 1
        # 去除最后多余的空格
        if slow-1>0 and s[slow-1] == ' ':
            return s[:slow-1]
        else:
            return s[:slow]

    def reverseWords(self, s: str) -> str:
        s = list(s)  # python字符串不可修改,转为字符列表
        s = self.remove_emptys(s)
        self.reverse(s, 0, len(s)-1)
        entry = False
        for i in range(len(s)):
            if not entry or (s[i] != ' ' and s[i-1] == ' '):
                start = i
                entry = True
            if entry and s[i] == ' ' and s[i-1] != ' ':
                end = i-1 
                entry = False
                self.reverse(s, start, end)
            if entry and i == len(s)-1 and s[i] != ' ':
                end = i
                entry = False
                self.reverse(s, start, end)
        return ''.join(s)

 再次做题已经有更简洁的写法:

class Solution:
    def reverseWords(self, s: str) -> str:
        n = len(s)
        # 去除前导空格和尾随空格
        i, j = 0, n - 1 
        while i < n and s[i] == ' ':
            i += 1
        while j >= 0 and s[j] == ' ':
            j -= 1
        s = s[i: j+1].split()  # 按空格划分
        if ' ' in s: 
            s.remove(' ')  # 删除中间所有空格
        s.reverse()  # 单词反转
        return ' '.join(s)
            

 简洁写法基本用库函数实现,时间效率还可以。

看题解想起来可以用整体反转+局部反转,但前提是预处理掉所有多余的空格。

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

题目链接:151. 反转字符串中的单词 - 力扣(Leetcode)

之前的做法直接运用python字符串切片完成:

class Solution(object):

    def reverseLeftWords(self, s, n):
        """
        :type s: str
        :type n: int
        :rtype: str
        """
        return s[n:] + s[0:n]

使用整体反转+局部反转的思路:

class Solution:
    def reverse(self, s, st, en):
        while st < en:
            s[st], s[en] = s[en], s[st]
            st += 1
            en -= 1
        
    def reverseLeftWords(self, s: str, n: int) -> str:
        s = list(s)
        # 先整体反转,再局部反转
        self.reverse(s, 0, len(s)-1)
        self.reverse(s, 0, len(s)-n-1)  # 反转前半段
        self.reverse(s, len(s)-n, len(s)-1)
        return ''.join(s)

整体和局部反转的先后顺序没有影响,时间复杂度都是O(n)。

你可能感兴趣的:(刷题,算法,leetcode,动态规划)