代码随想录|344反转字符串,541反转字符串II,剑指offer0.5 替换空格,151反转字符串里的单词,剑指 offer 58- II左旋转字符串

反转字符串

题目链接:leetcode 344.

题目描述: 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。

首尾依次调换即可. 对比反转单链表,由于单链表只能一个方向遍历,而数组可以两个方向,所以两个双指针的使用方法不同。

Python 代码

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        i,j = 0,len(s)-1
        while i < j:
            tmp = s[i]
            s[i] = s[j]
            s[j] = tmp
            i,j = i+1,j-1

反转字符串II

题目链接:leetcode 541.

题目描述: 给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

  • 如果剩余字符少于 k 个,则将剩余字符全部反转。
  • 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

考虑到每 2k 个为一个循环体做相同的操作。可以使用python中的 range(start,end,step)作为起始点。
另外python中的切片 (list[a:b]) 不会出现下标出界的问题,可以用来处理边界条件。

Python 代码

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

        while i < len(s)-1:
            j = min(j,len(s)-1)
            l,r = i,j 
            while l < r:
                tmp = s[l]
                s[l] = s[r]
                s[r] = tmp
                l,r = l+1,r-1
            i += 2*k
            j += 2*k
        return ''.join(s)

参考代码 代码随想录

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)

替换空格

题目链接: leetcode 剑指offer 0.5

题目描述:
请实现一个函数,把字符串 s 中的每个空格替换成"%20"

python 有简单的函数split和join来完成。
这里提供另一种想法,使用双指针法。首先需要确定新字符串的长度,统计空格的个数,然后原字符串长度加上两倍的空格个数。然后从后往前填充, 非空格的照常填充,遇到空格则填充‘%20’。从后往前填充不会覆盖,而从前面开始的话,为了不被覆盖,所有元素得往后移。

class Solution:
    def replaceSpace(self, s: str) -> str:
        count = s.count(' ')
        res = list(s)

        res.extend([' ']* count * 2)

        l,r = len(s)-1,len(res)-1
        while l >= 0:
            if s[l] != ' ':
                res[r] = s[l]
                r -= 1
            else:
                res[r-2:r+1] = '%20'
                r = r-3
            l -=1
        return ''.join(res)

反转字符串里的单词

题目链接:leetcode 151.

题目描述: 给你一个字符串 s ,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

想法:

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

升级版:原地改变字符串。(debug 太久 未完成)

class Solution:
    def removeExtraSpace(self,s:str) -> list:
        s = list(s)
        n = len(s)
        # 去除多余空格
        left, right = 0,n-1
        while left <= right and s[left] == ' ':
            left += 1
        while left <= right and s[right] == ' ':
            right -= 1
        tmp = []
        while left <= right:
            if s[left] != ' ':
                tmp.append(s[left])
            elif tmp[-1] != ' ':
                tmp.append(s[left])
            left += 1
        return tmp

    # 反转所有字母
    def reverse(self,s:list,left,right):
        while left < right:
            s[left],s[right] = s[right],s[left]
            left,right = left + 1, right -1
        return None
        

    def reverseWords(self, s: str) -> str:
        s = self.removeExtraSpace(s)
        n = len(s)
        self.reverse(s,0,n-1)

        start, end = 0,0
        while start < n:
            while end < n and s[end] != ' ':
                end += 1
            self.reverse(s,start,end-1)
            start,end = end + 1, end +1
        
        return ''.join(s)        

左旋转字符串

题目链接:剑指 offer 58- II

字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"
注: 原地改动字符串

类似反转字符串的单词,整体反转局部再反转,适用于局部不变但是顺序改变。这里不需要考虑空格问题,而且局部反转区间也给定了。所以我们可以先反转前n个,然后反转后面的,最后反转整体就得到。

class Solution:
    def reverse(self,s,start,end):
        while start < end:
            s[start], s[end] = s[end], s[start]
            start,end = start +1, end -1
    def reverseLeftWords(self, s: str, n: int) -> str:
        s = list(s)
        self.reverse(s,0,n-1)
        self.reverse(s,n,len(s)-1)
        self.reverse(s,0,len(s)-1)
        return "".join(s)

你可能感兴趣的:(leetcode,算法,python)