字符串

3. 无重复字符的最长子串open in new window 💯

3. 无重复字符的最长子串
# 这道题主要用到思路是:滑动窗口

# 什么是滑动窗口?

# 其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列!

# 如何移动?

# 我们只要把队列的左边的元素移出就行了,直到满足题目要求!

# 一直维持这样的队列,找出队列出现最长的长度时候,求出解!

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        left = 0
        window = set()
        cur_len = 0
        max_len = 0
        for i in range(len(s)):
            cur_len += 1
            while s[i] in window:
                window.remove(s[left])
                left += 1
                cur_len -= 1
            if cur_len > max_len:
                max_len = cur_len
            window.add(s[i])
        return max_len

    def lengthOfLongestSubstring2(self, s: str) -> int:
        left = 0
        right = 0
        res = 0
        window = dict()
        while right < len(s):
            if s[right] not in window:
                window[s[right]] = 1
            else:
                window[s[right]] += 1

            while window[s[right]] > 1:
                window[s[left]] -= 1
                left += 1

            res = max(res, right - left + 1)

            right += 1
        return res

    def lengthOfLongestSubstring3(self, s):
        left, right = 0, 0
        charset = set()
        res = 0
        while left < len(s) and right < len(s):
            if s[right] in charset:
                if s[left] in charset:
                    charset.remove(s[left])
                left += 1
            else:
                charset.add(s[right])
                right += 1
                res = max(res, len(charset))
        return res

5. 最长回文子串open in new window

最长回文子串
class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        if n < 2:
            return s

        max_len = 1
        begin = 0
        # dp[i][j] 表示 s[i..j] 是否是回文串
        dp = [[False] * n for _ in range(n)]
        for i in range(n):
            dp[i][i] = True

        # 递推开始
        # 先枚举子串长度
        for L in range(2, n + 1):
            # 枚举左边界,左边界的上限设置可以宽松一些
            for i in range(n):
                # 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得
                j = L + i - 1
                # 如果右边界越界,就可以退出当前循环
                if j >= n:
                    break

                if s[i] != s[j]:
                    dp[i][j] = False
                else:
                    if j - i < 3:
                        dp[i][j] = True
                    else:
                        dp[i][j] = dp[i + 1][j - 1]

                # 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是回文,此时记录回文长度和起始位置
                if dp[i][j] and j - i + 1 > max_len:
                    max_len = j - i + 1
                    begin = i
        return s[begin:begin + max_len]

125. 验证回文串open in new window

125. 验证回文串
# 描述:给定一个字符串 s。

# 要求:判断是否为回文串(只考虑字符串中的字母和数字字符,并且忽略字母的大小写)。

class Solution:
    # 双指针
    def isPalindrome(self, s: str) -> bool:
        left = 0
        right = len(s) - 1
        while left < right:
            if not s[left].isalnum():
                left += 1
                continue
            if not s[right].isalnum():
                right -= 1
                continue

            if s[left].lower() == s[right].lower():
                left += 1
                right -= 1
            else:
                return False
        return True

    def isPalindrome2(self, s: str) -> bool:
        s1 = "".join(ch.lower() for ch in s if ch.isalnum())
        return s1 == s1[::-1]

151. 反转字符串中的单词open in new window 💯

反转字符串中的单词
class Solution:
    # 移除多余空格
    def trim(self, s):
        left = 0
        right = len(s) - 1
        while left <= right and s[left] == " ":
            left += 1
        while left <= right and s[right] == " ":
            right -= 1
        res = []
        while left <= right:
            if s[left] != " ":
                res.append(s[left])
            elif res[-1] != " ":
                res.append(s[left])
            left += 1
        return res

    # 翻转字符串数组
    def reverse(self, s, left, right):
        while left < right:
            s[left], s[right] = s[right], s[left]
            left += 1
            right -= 1
        return None

    # 翻转每个单词
    def reverse_each_word(self, l):
        start = 0
        end = 0
        n = len(l)
        while start < n:
            while end < n and l[end] != " ":
                end += 1
            self.reverse(l, start, end - 1)
            start = end + 1
            end += 1
        return None

    def reverseWords(self, s: str) -> str:
        l = self.trim(s)
        self.reverse(l, 0, len(l) - 1)
        self.reverse_each_word(l)
        return "".join(l)

344. 反转字符串open in new window 💯

反转字符串 【双指针】
# 使用两个指针 left,right。left 指向字符数组开始位置,right 指向字符数组结束位置。
# 交换 s[left] 和 s[right],将 left 右移、right 左移。
# 如果遇到 left == right,跳出循环

# 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题

class Solution:
    def reverseString(self, s):
        left = 0
        right = len(s) - 1
        while left < right:
            s[left], s[right] = s[right], s[left]
            left += 1
            right -= 1

    # 使用额外空间
    def reverseString2(self, s):
        res = []
        for i in range(len(s) - 1, -1, -1):
            res.append(s[i])
        return res

415. 字符串相加open in new window 💯

415. 字符串相加
# 描述:给定两个字符串形式的非负整数 num1 和num2。

# 要求:计算它们的和,并同样以字符串形式返回。

class Solution:
    def addStrings(self, num1: str, num2: str) -> str:
        res = ""
        i = len(num1) - 1
        j = len(num2) - 1
        # 进位
        carry = 0
        while i >= 0 or j >= 0:
            n1 = int(num1[i]) if i >= 0 else 0
            n2 = int(num2[j]) if j >= 0 else 0
            tmp = n1 + n2 + carry
            carry = tmp // 10
            res = str(tmp % 10) + res
            i -= 1
            j -= 1
        return "1" + res if carry else res

# 用一个数组存储按位相加后的结果,每一位对应一位数。
# 然后分别使用一个指针变量,对两个数 num1、num2 字符串进行反向遍历,将相加后的各个位置上的结果保存在数组中,这样计算完成之后就得到了一个按位反向的结果。
# 最后返回结果的时候将数组反向转为字符串即可。

    def addStrings2(self, num1: str, num2: str) -> str:
        carry = 0
        res = []
        n1 = len(num1) - 1
        n2 = len(num2) - 1
        while carry > 0 or n1 >= 0 or n2 >= 0:
            num1_d = int(num1[n1]) if n1 >= 0 else 0
            num2_d = int(num2[n2]) if n2 >= 0 else 0
            n1 -= 1
            n2 -= 1
            num = num1_d + num2_d + carry
            res.append(str(num % 10))
            carry = num // 10

        return "".join(res[::-1])

459. 重复的子字符串open in new window

459. 重复的子字符串
# 给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        return True if s in (s + s)[1:-1] else False

541. 反转字符串 IIopen in new window

反转字符串 II
class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        res = list(s)
        for i in range(0, len(res), k * 2):
            res[i:i + k] = reversed(res[i:i + k])
        return "".join(res)

    def reverseStr(self, s: str, k: int) -> str:
        def reverse_str(alist):
            left = 0
            right = len(alist) - 1
            while left < right:
                alist[left], alist[right] = alist[right], alist[left]
                left += 1
                right -= 1
            return alist

        res = list(s)
        for i in range(0, len(res), k * 2):
            res[i: i + k] = reverse_str(res[i: i + k])
        return "".join(res)

剑指 Offer 05. 替换空格open in new window

剑指 Offer 05. 替换空格
class Solution:
    def replaceSpace(self, s: str) -> str:
        res = []
        for i in s:
            if i == " ":
                res.append("%20")
            else:
                res.append(i)
        return "".join(res)

剑指 Offer 58 - II. 左旋转字符串open in new window

剑指 Offer 58 - II. 左旋转字符串
class Solution:
    def reverseLeftWords(self, s: str, n: int) -> str:
        return s[n:] + s[:n]

    def reverseLeftWords2(self, s: str, n: int) -> str:
        res = []
        for i in range(n, len(s)):
            res.append(s[i])
        for i in range(n):
            res.append(s[i])
        return "".join(res)
上次更新:
贡献者: kongzZ