58. 最后一个单词的长度

方法一:反向遍历

class Solution:
    def lengthOfLastWord(self, s: str) -> int:
        s = s.strip() # 处理后面的空格
        n = len(s)
        for i in range(n-1, -1, -1):
            if s[i] == ' ':
                return n - i - 1

        return n # 只有一个单词
        
        # return len(s.split()[-1])

1、1957. 删除字符使字符串变好

知识点: 字符串(索引、切片、长度),len,!=,+=,in (not in) ,or 和 for。
教程:Python 1-09 字符串

class Solution:
    def makeFancyString(self, s: str) -> str:
        # n = len(s)
        # if n < 3: return s
        res = s[:2]
  
        for c in s[2:]:
            if c != res[-1] or c != res[-2]:
                res += c

        return res

2、1221. 分割平衡字符串

class Solution:
    def balancedStringSplit(self, s: str) -> int:
        res = d = 0
        for ch in s:
            d += (1 if ch == "R" else -1)
            if d == 0: res += 1
            
        return res

3、796. 旋转字符串

知识点: find,True,False,all,%

方法一:穷举法

class Solution:
    def rotateString(self, s: str, goal: str) -> bool:
        m, n = len(s), len(goal)
        if m != n:  return False        
        if m == 0:  return True
        # if s == goal: return True

        for i in range(n):
            # if all(s[(i+j) % n] == goal[j] for j in range(n)):
            #     return True 
          
            s = s[1:] + s[0]
            if s == goal: return True
          
        return False

方法二:判断子串

先判断长度是否相同,不相同返回 False,其次拼接两个 s,则如果 goal 是由 s 旋转而成,则拼接后的 s 一定包含 goal。

class Solution:
    def rotateString(self, s: str, goal: str) -> bool:
        # if len(s) != len(goal): return False
        # return goal in s * 2

        # return len(s) == len(goal) and (s * 2).find(goal) != -1     
        
        return len(s) == len(goal) and goal in s * 2

4、1768. 交替合并字符串

方法一:

class Solution:
    def mergeAlternately(self, word1: str, word2: str) -> str:
        x, res = min(len(word1), len(word2)), ''
       
        for i in range(x):        
            res += word1[i] + word2[i]
        
        res += word1[x:] + word2[x:]   # 处理剩余的部分     
        
        return res

方法二:队列,zip_longest

class Solution:
    def mergeAlternately(self, word1: str, word2: str) -> str:
        # a, b = deque(word1), deque(word2)
        # res = ""
        # while a and b:
        #     res += a.popleft()
        #     res += b.popleft()

        # res += "".join(a) + "".join(b)
        # return res
		
		# from  itertools import zip_longest
        return "".join(sum(zip_longest(word1, word2, fillvalue=""), ()))

5、面试题 01.06. 字符串压缩

class Solution:
    def compressString(self, S: str) -> str:
        # n, res, i = len(S), '', 0

        # while i < n:
        #     j = i
        #     while j < n and S[j] == S[i]:
        #         j += 1

        #     res += S[i] + str(j - i)
        #     i = j
        
        if not S: return S
        tmp, cnt, res = S[0], 0, ''

        for c in S:
            if c == tmp:
                cnt += 1
            else:
                res += tmp + str(cnt)
                tmp, cnt = c, 1

        res += tmp + str(cnt)

        return res if len(res) < len(S) else S

6、415. 字符串相加

知识点: divmod,//,%,str,int,if … else …

方法一:模拟

设定 i,j 两指针分别指向 num1,num2 尾部,模拟人工加法;
计算进位: 计算 carry = tmp // 10,代表当前位相加是否产生进位;
添加当前位: 计算 tmp = n1 + n2 + carry,并将当前位 tmp % 10 添加至 res 头部;
索引溢出处理: 当指针 i 或 j 走过数字首部后,给 n1,n2 赋值为 0,相当于给 num1,num2 中长度较短的数字前面填 0,以便后续计算。
当遍历完 num1,num2 后跳出循环,并根据 carry 值决定是否在头部添加进位 1,最终返回 res 即可。

class Solution:
    def addStrings(self, num1: str, num2: str) -> str:
        res = ""
        i, j, carry = len(num1) - 1, len(num2) - 1, 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, rem = divmod(tmp, 10) # carry = tmp // 10 ;rem = tmp % 10
            res = str(rem) + res
            i, j = i - 1, j - 1 # i -= 1; j -= 1

        return "1" + res if carry else res

        # return str(int(num1) + int(num2))

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

方法一:dict

class Solution:
    def firstUniqChar(self, s: str) -> int:
        # d = defaultdict(int)
        # for c in s:
        #     d[c] += 1
        d = collections.Counter(s)
        for i, c in enumerate(s):
            if d[c] == 1:
                return i
        return -1

方法二:find rfind

class Solution:
    def firstUniqChar(self, s: str) -> int:
        for i, c in enumerate(s):
            if s.find(c) == s.rfind(c):
                return i
        
        return -1

方法三:set

class Solution:
    def firstUniqChar(self, s: str) -> int:
        seen = set()
        for i, c in enumerate(s):
            if s.rfind(c) == i and c not in seen:
                return i
            else:
                seen.add(c)
                
        return -1

8、344. 反转字符串

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:
        #     s[i], s[j] = s[j], s[i]
        #     i += 1
        #     j -= 1 

        for i in range(len(s)//2):
            s[i], s[-i-1] = s[-i-1], s[i]
		
        # s[:] = s[::-1]

9、1417. 重新格式化字符串

class Solution:
    def reformat(self, s: str) -> str:        
        nums, string, res = [], [], ''

        for c in s:
            if c.isdigit(): nums.append(c)
            else: string.append(c)
        m, n = len(string), len(nums)
        if abs(m - n) > 1:
            return ""
        if m > n:
            for i in range(n):
                res += string[i] + nums[i]

            res += string[-1]
        else:
            for i in range(m):
                res += nums[i] + string[i]

            if m < n:
                res += nums[-1]
        
        return res

10、2000. 反转单词前缀

class Solution:
    def reversePrefix(self, word: str, ch: str) -> str:
        idx = word.find(ch)
        return word[:idx+1][::-1] + word[idx+1:] if idx != -1 else word

1796. 字符串中第二大的数字

class Solution:
    def secondHighest(self, s: str) -> int:
        # 方法一:
        # res = first = second = -1
        
        # for c in s:
        #     if c.isdigit():
        #         d = int(c)
        #         if d > first:
        #             first, second = d, first
        #         else:
        #             if first > d > second:
        #                 second = d
        # return second
        
        # 方法二:list sort
        # digit = []
        # for c in s:
        #     if c.isdigit() and int(c) not in digit:
        #         digit.append(int(c))
        
        # digit.sort()
        # return digit[-2] if len(digit) > 1 else -1

        # 方法三:filter list sort map 高阶函数
        digit = sorted(map(int, set(filter(str.isdigit, s))))  # 过滤英文字母
        return digit[-2] if len(digit) > 1 else -1

1790. 仅执行一次字符串交换能否使两个字符串相等

class Solution:
    def areAlmostEqual(self, s1: str, s2: str) -> bool:
        first = second = False
        for i, c in enumerate(s1):
            if s2[i] != c:
                if not first: # 第一次不同,记录下来。
                    first = True
                    x = s2[i]
                    y = c
                elif not second: # 第二次不同
                    if c != x or s2[i] != y:return False
                    second = True
                else:
                    return False
                    
        return not first or (first and second)
class Solution:
    def areAlmostEqual(self, s1: str, s2: str) -> bool:
        if sorted(s1) != sorted(s2): return False

        first = second = True
        for i, c in enumerate(s1):
            if s2[i] != c:
                if first:
                    first = False
                elif second:
                    second = False
                else:
                    return False
                    
        return True

1446. 连续字符

class Solution:
    def maxPower(self, s: str) -> int:
        res = tmp = 1
        x = s[0]
        for i in range(1, len(s)):
            if s[i] == x:
                tmp += 1
            else:
                res = max(res, tmp)
                x = s[i]
                tmp = 1
                
        return max(res, tmp)