本系列面向刚学会基础语法、还没有刷题经验的同学,通过足够详细的注解展示此前在基础的python系列中学到的知识点如何在代码中应用以解决问题,得到更深入的理解和基础做题经验。开头会写得尽量详细,往后则逐步只挑核心,纯小白入,不必畏难,祝大家刷题愉快!
1768.交替合并字符串
给你两个字符串 word1 和 word2 。请你从 word1 开始,通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长,就将多出来的字母追加到合并后字符串的末尾。
返回 合并后的字符串 。
题目拆解
目标是:将word1与word2序列中的元素,一边一个地添加到新字符串里。超出的部分,直接全部添加。
因此:
通过循环将字符串中的元素逐个输出
循环边界是以最长的字符串长度为边界
通过判断限定输出条件,以此来控制长出另一个字符串的部分的输出是连续的。
完整题解
class Solution:
def mergeAlternately(self, word1: str, word2: str) -> str:
m, n = len(word1), len(word2)
i = j = 0
ans = list()
while i < m or j < n:
if i < m:
ans.append(word1[i])
i += 1
if j < n:
ans.append(word2[j])
j += 1
return "".join(ans)
作者:力扣官方题解
链接:https://leetcode.cn/problems/merge-strings-alternately/solutions/1913930/jiao-ti-he-bing-zi-fu-chuan-by-leetcode-ac4ih/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
逐行注释
class Solution:
定义了一个名为 Solution
的类,后续的方法会封装在这个类中,通常在算法题中,会用这种方式来组织解决问题的代码。
def mergeAlternately(self, word1: str, word2: str) -> str:
在 Solution
类中定义了一个名为 mergeAlternately
的实例方法。self
是对类实例的引用;word1
和 word2
是该方法的两个参数,类型注解表明它们都是字符串;-> str
表示这个方法的返回值类型是字符串。
m, n = len(word1), len(word2)
计算字符串 word1
的长度并赋值给 m
,计算字符串 word2
的长度并赋值给 n
,后续会用这两个变量来控制循环次数。
i = j = 0
初始化两个索引变量 i
和 j
,分别用于遍历字符串 word1
和 word2
,初始值都设为 0
。
ans = list()
创建一个空列表 ans
,用于存储交替合并后的字符。
while i < m or j < n:
设置一个循环条件,只要 i
小于 word1
的长度 m
或者 j
小于 word2
的长度 n
,循环就会继续执行,确保能处理完两个字符串中较长的那个字符串的所有字符。
if i < m:
ans.append(word1[i])
i += 1
如果 i
小于 word1
的长度 m
,说明 word1
还有未处理的字符,就将 word1
中索引为 i
的字符添加到列表 ans
中,然后将 i
的值加 1
,指向下一个字符。append()
:向列表末尾添加任意类型的元素,使用方法:列表名.append(
字符)
if j < n:
ans.append(word2[j])
j += 1
如果 j
小于 word2
的长度 n
,说明 word2
还有未处理的字符,就将 word2
中索引为 j
的字符添加到列表 ans
中,然后将 j
的值加 1
,指向下一个字符。
return "".join(ans)
循环结束后,列表 ans
中已经存储了交替合并后的字符,使用 join
方法将列表中的字符连接成一个字符串并返回,作为最终交替合并后的结果。 join()
的使用方法:"
连接符,可以为空"``.join(
列表名)
389.找不同
给定两个字符串 s 和 t ,它们只包含小写字母。
字符串 t 由字符串 s 随机重排,然后在随机位置添加一个字母。
请找出在 t 中被添加的字母。
题目拆解
找出被添加的字母,由于字符串是随机重排并且添加也是随机添加的,因此并不好用逐个对比的办法处理。
但既然是随机顺序,可以想到:字典。
因此可以先想办法完成对每个字符出现的次数进行计数,以键值对的形式储存在字符串各自对应的字典里,然后再通过键去找对应值,判断是否相等。出现次数相等的说明不是后来添加的。
完整题解
class Solution(object):
def findTheDifference(self, s, t):
"""
:type s: str
:type t: str
:rtype: str
"""
# 使用Counter计算两个字符串中字符的频率
counter_s = Counter(s)
counter_t = Counter(t)
# 找到在counter_t中存在但在counter_s中不存在或者数量更多的字符
for char in counter_t:
if counter_t[char] > counter_s.get(char, 0):
return char
逐行注释
- 统计字符频率
# 使用Counter计算两个字符串中字符的频率
counter_s = Counter(s)
counter_t = Counter(t)
- 使用Counter为字符串s中的每个字符创建一个计数器,记录每个字符出现的次数,最终得到的是一个字典。例如,如果
s = "abc"
,则counter_s
是{'a': 1, 'b': 1, 'c': 1}
。 counter_t = Counter(t)
:同理,统计字符串t
中每个字符的出现次数,并将结果存储在counter_t
中。
- 查找多出来的字符
# 找到在counter_t中存在但在counter_s中不存在或者数量更多的字符
for char in counter_t:
if counter_t[char] > counter_s.get(char, 0):
return char
for char in counter_t:
:遍历counter_t
中的每个键(即字符串t
中的每个不同字符)。counter_t[char]
:根据键索引char
找值,获取字符char
在字符串t
中出现的次数。counter_s.get(char, 0)
:使用get
方法从counter_s
中获取字符char
出现的次数。如果char
不在counter_s
中,get
方法会返回默认值0
。if counter_t[char] > counter_s.get(char, 0):
:counter_t如果字符char
在字符串t
中出现的次数比在字符串s
中出现的次数多,说明这个字符就是字符串t
中多出来的字符。return char
:一旦找到多出来的字符,就立即返回该字符。
28. 找出字符串中第一个匹配项的下标
给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
题目拆解
目标是:在h序列中找到符合n的子序列
所以也就是说,在h序列里逐个切出长度与n相等的子序列,然后与n相比较
如果相等,输出首个符合的字符下标;如果遍历完仍然不符合,输出-1
特殊情况:n序列长度0
因此:
切出长度与n相等的子序列,然后比较
循环边界是h的长度减去n的长度+1
加上特殊情况
完整题解
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
i = 0
if len(needle)==0:
return 0
for i in range(len(haystack)-len(needle)+1):
if haystack[i:i+len(needle)] == needle:
return i
return -1
逐行注释
单拎特殊情况:
if len(needle)==0:
return 0
切片,一直循环到卡最后一个子序列:
for i in range(len(haystack)-len(needle)+1):
判断是否相等,是则输出目标值
if haystack[i:i+len(needle)] == needle:
return i
直到循环结束都没有返回i,就返回-1
return -1
242. 有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的 字母异位词。
示例 1:
输入: s = “anagram”, t = “nagaram”
输出: true
示例 2:
输入: s = “rat”, t = “car”
输出: false
题目拆解
与前面的389.找不同
类似,也是无序元素组合,可以用一样的方法通过字典来存储键键值对,直接比较两个字典是否相等即可。
完整代码
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
counter_s = Counter(s)
counter_t = Counter(t)
return counter_s == counter_t
459. 重复的子字符串
给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。
示例 1:
输入: s = “abab”
输出: true
解释: 可由子串 “ab” 重复两次构成。
示例 2:
输入: s = “aba”
输出: false
题目拆解
这次是有序的了,不能参考前面无序集合的方法了。
特定技巧:滑动窗口
在这里的应用就是,当一个字符串str
自身拼接,得到s_double = str + str
后,再去掉第一个字符和最后一个字符,进一步得到修剪后的自身拼接字符串s_trimmed
,此时能在s_trimmed
里找到这个字符串str
,说明这个字符串能够由某个子串重复拼接得到。
要理解这个定义的话,就假设str是最简单的、仅由子串abc重复两次得到的abcabc;
然后,将其double得到abcabcabcabc;
此时,去掉首尾各一个字符,得到bcabcabcab;
可以发现,在其中仍然能找到abcabc。
因markdown画图不便,就不补充了,但用图像会更好理解。比如绿格子接红格子作为子串,重复几次后去掉头尾格子,然后再拿原始字符串格子段滑动着对比。
完整代码
class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
# 创建新的字符串 str = S + S
str_double = s + s
# 去除首尾字符
str_trimmed = str_double[1:-1]
# 检查去除首尾字符后的字符串是否包含原字符串
return s in str_trimmed