LeetCode Cookbook 字符串习题 上篇

LeetCode Cookbook 字符串习题 上篇

   开始 字符串部分了,这一部分的花的时间不少了 今天上午给整理出来,主要就是一些有关字符串的基本函数应用,非常需要勤加练习.

13. 罗马数字转整数

题目链接:13. 罗马数字转整数
题目大意:罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000
  • 例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
  • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
  • X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
  • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
  • 给定一个罗马数字,将其转换成整数。

例如:

输入: s = "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.

解题思路:非常基础的一道题 使用哈希表是不错的选择.

class Solution:
    def romanToInt(self, s: str) -> int:
        hash_map = {
            'I':1,'IV':4,'V':5, 'IX':9,
            'X':10,'XL':40,'L':50,'XC': 90,
            'C':100,'CD':400 ,'D':500,'CM':900,
            'M':1000 
        }
        idx,n = 0,len(s)
        ans = 0
        while idx < n:
            if s[idx:idx+2] in hash_map:
                ans += hash_map[s[idx:idx+2]]
                idx += 2
            else:
                ans +=  hash_map[s[idx]]
                idx += 1
        return ans

28. 实现 strStr()

题目链接:28. 实现 strStr()
题目大意:实现 strStr() 函数。给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串出现的第一个位置(下标从 0 开始)。如果不存在,则返回 -1 。
说明:

  • 当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。
  • 对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与 C 语言的 strstr() 以及 Java 的 indexOf() 定义相符。

例如:

输入:haystack = "hello", needle = "ll"
输出:2
输入:haystack = "aaaaa", needle = "bba"
输出:-1

解题思路: 简单题 直接使用 in 函数就很简单.

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        if len(needle) == 0: return 0
        if needle not in haystack:
            return -1
        for i,ch in enumerate(haystack):
            if ch == needle[0]:
                if haystack[i:i+len(needle)] == needle:
                    return i

67. 二进制求和

题目链接:67. 二进制求和
题目大意:给你两个二进制字符串,返回它们的和(用二进制表示)。输入为 非空 字符串且只包含数字 1 和 0。

例如:

输入: a = "11", b = "1"
输出: "100"
输入: a = "1010", b = "1011"
输出: "10101"

解题思路:经典习题啊! 需要额外设置 进位位 carry,具体看代码.

class Solution:
    def addBinary(self, a: str, b: str) -> str:
        n1,n2 = len(a),len(b)
        ans = ''
        i,j,carry = n1-1,n2-1,0
        while i>=0 or j>=0:
            num1 = int(a[i]) if i>=0 else 0
            num2 = int(b[j]) if j>=0 else 0
            tmp = num1 + num2 + carry
            carry = tmp // 2
            ans = str(tmp%2) + ans
            i -= 1
            j -= 1
        return '1'+ans if carry else ans

91. 解码方法 **

题目链接:91. 解码方法
题目大意:一条包含字母 A-Z 的消息通过以下映射进行了 编码 :

'A' -> "1"
'B' -> "2"
...
'Z' -> "26"

要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,“11106” 可以映射为:

  • “AAJF” ,将消息分组为 (1 1 10 6)
  • “KJF” ,将消息分组为 (11 10 6)
  • 注意,消息不能分组为 (1 11 06) ,因为 “06” 不能映射为 “F” ,这是由于 “6” 和 “06” 在映射中并不等价。
  • 给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数 。
  • 题目数据保证答案肯定是一个 32 位 的整数。

例如:

输入:s = "12"
输出:2
解释:它可以解码为 "AB"1 2)或者 "L"12)。
输入:s = "226"
输出:3
解释:它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6)

解题思路: 动态规划经典题,一看就懵,要多背一背这类题的求解方式,有点类似于递归的思想.

class Solution:
    def numDecodings(self, s: str) -> int:
        n = len(s)
        dp = [1] + [0]*n
        for i in range(1,n+1):
            if s[i-1] != '0':
                dp[i] += dp[i-1]
            if i>=2 and s[i-2] != '0' and int(s[i-2:i])<=26:
                dp[i] += dp[i-2]
            print(dp)
        return dp[n]

125. 验证回文串

题目链接:125. 验证回文串
题目大意: 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。字母和数字都属于字母数字字符。给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 。

例如:

输入: s = "A man, a plan, a canal: Panama"
输出:true
解释:"amanaplanacanalpanama" 是回文串。

输入:s = "race a car"
输出:false
解释:"raceacar" 不是回文串。。

解题思路: 简单题,重拳出击,两种编写方法,思路是一致的.

(一) 使用 循环分解字符串

class Solution:
    def isPalindrome(self, s: str) -> bool:
        if len(s) == 0: return True
        s =  ''.join(ch.lower() for ch in s if ch.isalnum())
        return s == s[::-1]

(二)使用 filter 迭代器 分解字符串 稍微快一些

class Solution:
    def isPalindrome(self, s: str) -> bool:
        # filter 函数要比使用循环快一些
        s = ''.join(filter(str.isalnum,s)).lower()
        return s == s[::-1]

151. 反转字符串中的单词

题目链接:151. 反转字符串中的单词
题目大意:给你一个字符串 s ,请你反转字符串中 单词 的顺序。单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

  • 注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

例如:

输入:s = "the sky is blue"
输出:"blue is sky the"

解题思路 :大胆做就成 其实也可以使用 reversed 函数

class Solution:
    def reverseWords(self, s: str) -> str:
        return ' '.join(s.split()[::-1])

205. 同构字符串

题目链接:205. 同构字符串
题目大意: 给定两个字符串 s 和 t ,判断它们是否是同构的。如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。

例如:

输入:s = "egg", t = "add"
输出:true
输入:s = "foo", t = "bar"
输出:false

解题思路: 后面好像有一道更难一点的,一会比较一下!

class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        if len(set(s)) != len(set(t)): return False
        seen = dict()
        for ch1,ch2 in zip(s,t):
            if ch1 not in seen:
                seen[ch1] = ch2
            else:
                if seen[ch1] != ch2:
                    return False
        return True

344. 反转字符串

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

例如:

输入:s = ["h","e","l","l","o"]
输出:["o","l","l","e","h"]

解题思路:简单题 这里使用的是切片的方法.

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        n = len(s)
        for i in range(n//2):
            s[i],s[n-1-i] = s[n-1-i],s[i]

345. 反转字符串中的元音字母

题目链接:345. 反转字符串中的元音字母
题目大意:给你一个字符串 s ,仅反转字符串中的所有元音字母,并返回结果字符串。元音字母包括 ‘a’、‘e’、‘i’、‘o’、‘u’,且可能以大小写两种形式出现。

例如:

输入:s = "hello"
输出:"holle"

解题思路: 双指针 不难.

class Solution:
    def reverseVowels(self, s: str) -> str:
        def isVowel(ch: str) -> bool:
            if ch in 'aeiouAEIOU':
                return True
            else:
                return False
            
        n = len(s)
        c = list(s)
        i,j = 0,n-1
        while i<j:
            while i<=n-1 and not isVowel(c[i]):
                i += 1
            while j>=0 and not isVowel(c[j]):
                j -= 1 
            if i<j:
                c[i],c[j] = c[j],c[i]
                i += 1
                j -= 1
        return ''.join(c) 

387. 字符串中的第一个唯一字符

题目链接:387. 字符串中的第一个唯一字符
题目大意:给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1

例如:

输入: s = "leetcode"
输出: 0

解题思路: Counter 特别好用.

class Solution:
    def firstUniqChar(self, s: str) -> int:
        
        counter = collections.Counter(s)
        for i,ch in enumerate(s):
            if counter[ch] == 1:
                return i
        return -1

        # 最好不要用 s.count 太tm慢了 
        # for i,ch in enumerate(s):
        #     if s.count(ch) == 1:
        #         return i
        # return -1

409. 最长回文串

题目链接:409. 最长回文串
题目大意:「给定一个包含大写字母和小写字母的字符串 s ,返回 通过这些字母构造成的 最长的回文串 。在构造过程中,请注意 区分大小写 。比如 “Aa” 不能当做一个回文字符串。

例如:

输入:s = "abccccdd"
输出:7
解释:我们可以构造的最长的回文串是"dccaccd", 它的长度是 7

解题思路: 全部偶数+一个奇数或没有奇数

class Solution:
    def longestPalindrome(self, s: str) -> int:
        n = len(s)
        if n == 1: return 1
        counter = collections.Counter(s)
        tmp = 0
        for ch in counter:
            if counter[ch] % 2 == 1:
               tmp += 1
        return  n-tmp+1 if tmp else n

412. Fizz Buzz

题目链接:412. Fizz Buzz
题目大意:给你一个整数 n ,找出从 1 到 n 各个整数的 Fizz Buzz 表示,并用字符串数组 answer(下标从 1 开始)返回结果,其中:

  • answer[i] == “FizzBuzz” 如果 i 同时是 3 和 5 的倍数。

  • answer[i] == “Fizz” 如果 i 是 3 的倍数。

  • answer[i] == “Buzz” 如果 i 是 5 的倍数。

  • answer[i] == i (以字符串形式)如果上述条件全不满足。

    例如:

输入:n = 5
输出:["1","2","Fizz","4","Buzz"]

解题思路: if条件判断

class Solution:
    def fizzBuzz(self, n: int) -> List[str]:
        ans = []
        for i in range(1,n+1):
            if i % 3 == 0 and i % 5 == 0:
                ans.append("FizzBuzz")
            elif i % 3 == 0:
                ans.append("Fizz")
            elif i % 5 == 0:
                ans.append('Buzz')
            else:
                ans.append(str(i))
        return ans

500. 键盘行 **

题目链接:500. 键盘行
题目大意:
给你一个字符串数组 words ,只返回可以使用在 美式键盘 同一行的字母打印出来的单词。键盘如下图所示。
美式键盘 中:

  • 第一行由字符 “qwertyuiop” 组成。

  • 第二行由字符 “asdfghjkl” 组成。

  • 第三行由字符 “zxcvbnm” 组成。

    例如:

输入:words = ["Hello","Alaska","Dad","Peace"]
输出:["Alaska","Dad"]

解题思路: all 函数 很好用!

class Solution:
    def findWords(self, words: List[str]) -> List[str]:
        hash_map =["qwertyuiop","asdfghjkl","zxcvbnm"]
        ans = []
        for word in words:
            flag = 0
            word1 = word.lower()
            for i in range(3):
                if all(ch in hash_map[i] for ch in word1):
                    ans.append(word)   
        return ans

537. 复数乘法

题目链接:537. 复数乘法
题目大意:复数 可以用字符串表示,遵循 “实部+虚部i” 的形式,并满足下述条件:

  • 实部 是一个整数,取值范围是 [-100, 100]
  • 虚部 也是一个整数,取值范围是 [-100, 100]
  • i 2 = = − 1 i^2 == -1 i2==1
  • 给你两个字符串表示的复数 num1 和 num2 ,请你遵循复数表示形式,返回表示它们乘积的字符串。

例如:

输入:num1 = "1+1i", num2 = "1+1i"
输出:"0+2i"
解释:(1 + i) * (1 + i) = 1 + i2 + 2 * i = 2i ,你需要将它转换为 0+2i 的形式。

解题思路: 按照题意进行即可,需要注意 map split 等函数的运用.

class Solution:
    def complexNumberMultiply(self, num1: str, num2: str) -> str:
        
        real1, imag1 = map(int,num1[:-1].split('+'))
        real2, imag2 = map(int,num2[:-1].split('+'))
        real = real1*real2 - imag1*imag2
        imag = real1*imag2 + real2*imag1
        return str(real)+'+'+str(imag)+'i'

        # return f'{real}+{imag}i'

541. 反转字符串 II

题目链接:541. 反转字符串 II
题目大意:给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

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

例如:

输入:s = "abcdefg", k = 2
输出:"bacdfeg"

解题思路: reversed() 函数挺好用的!

class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        s = list(s)
        n = len(s)
        # 切片[::-1] 有返回值, reverse()函数没有返回值
        # 使用反向切片注意 start > end
        for i in range(0,n,2*k):
            # 方法1
            s[i:i+k] = reversed(s[i:i+k])
            # 方法2 切片的 end 位置不能写-1 即[:-1:-1] 返回空数组
            # s[i:i+k] = s[i:i+k][::-1]
        return ''.join(s)

557. 反转字符串中的单词 III

题目链接:557. 反转字符串中的单词 III
题目大意:给定一个字符串 s ,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。

例如:

输入:s = "Let's take LeetCode contest"
输出:"s'teL ekat edoCteeL tsetnoc"

解题思路: 切片倒序

class Solution:
    def reverseWords(self, s: str) -> str:
        ans = s.split()
        for i,word in enumerate(ans):
            ans[i] = word[::-1]
        # print(ans)
        return ' '.join(ans)

总结

  字符串这一部分还是 比较简单 这一部分就只有上下了! 加油,努力,奋斗!

你可能感兴趣的:(LC分类题型汇总,python算法学习,leetcode,算法,python,字符串,切片)