持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第29天,点击查看活动详情
测试岗位也越来卷了,除了基本的功能测试外,还要有编程基础、脚本经验才脱颖而出。
怎么才能提高我们的编程能力呢,刷LeetCode是最佳的途径之一,话不多数,刷题走起~
一、题目描述:
-
题目内容
-
题目示例
-
题目解析
1 <= s.length, p.length <= 3 * 104s和p仅包含小写字母
二、思路分析:
我们拿到本题,读取题意要求在字符串中给出字符串P的异位词,并返回在字符串中起始索引列表。看完题目,我们对题目中的一些细节点需要明确的:
- 异位词:由相同字母组成的字符串。如"abc"与"cba"是异位词,因为它们都是由a,b,c三个字符组成的
- 字符串s与字符串p都是由小写字母组成的
- 字符串s中要找出字符串p的异位词,那么字符串s的长度要大于字符串p的,才有可能有异位词
以上明确了题目的要求,对于本题解答时,我们很容易想到了用滑动窗口方法来实现
- 以字符串p长度的滑动窗口,在字符串s中中进行遍历查找
那么怎么判断滑动窗口中字符串与字符串p是异位词,如果只通过判断s[i]在字符串p中存在,那么对于p字符串重复字符就没有办法筛选出来了。
这个时候,如383. 赎金信中构建26字母初始列表来存储每一个字符出现的次数的方法来辅助我们s字符串滑动窗口中的字符次数
因此,实现的思路就比较清晰了,大致如下:
- 初始化两个26个字母的列表次数默认为0,pcount和scount
- p字符串和s字符串都是由小写字母组成,可以使用ord()-97来得到26字母列表的索引位置
- 循环遍历p字符串,pcount记录每一个字符出现的次数
- 遍历以p字符串长度遍历s字符串,滑动串口中的字符次数更新在scount,与pcount进行对比
- 如果scount与pcount相等,则ans添加索引i到结果中
按照这个思路,滑动串口中使用for循环来计算次数,代码很轻松的写出来了,但是超出时间限制通过不了
思考一番,滑动窗口中的字符串可以通过i和i+len(p)索引来更新scount.
- 先求出当i=0时的scount字符串次数,并判断scount与pcount,如果相等则ans添加索引0
- 当遍历s字符串中字符时,s[i]的次数被更新为0,添加一个s[i+len(p)]字符的次数
- 同理判断scount与pcount相等,则ans添加i+1 根据上述优化思路,实现的Python代码如下:
class Solution(object):
def findAnagrams(self, s, p):
pcount = [0]*26
scount = [0]*26
ans = []
if len(s) < len(p):
return ans
for i in range(len(p)):
pcount[ord(p[i])-97] +=1
scount[ord(s[i])-97] +=1
if scount == pcount:
ans.append(0)
for i in range(len(s)-len(p)):
scount[ord(s[i])-97] -=1
scount[ord(s[i+len(p)])-97] +=1
print(scount)
if scount == pcount:
ans.append(i+1)
return ans
上述遍历使用一个for循环+固定滑动窗口的思想,可以通过本题,但是效率还是比较慢的,我们继续思考优化:
- 使用可变大小的滑动窗口,创建两个指针left和right,都指向s字符串起始位置
- right指针开始移动,每一次移到scount更新所指的字符的次数
- 当right-left+1与len(p)相等且pcount与scount相等,则ans添加left
- 当right-left+1大于len(p)时,s[left]字符次数进行减1,left指针向右+1
- 当right指针大于len(s),则退出循环
class Solution(object):
def findAnagrams(self, s, p):
"""
:type s: str
:type p: str
:rtype: List[int]
"""
pcount = [0]*26
scount = [0]*26
ans = []
left = 0
right = 0
if len(s) < len(p):
return ans
for i in range(len(p)):
pcount[ord(p[i])-97] +=1
while right < len(s):
scount[ord(s[right])-97] +=1
if right-left+1 > len(p):
scount[ord(s[left])-97] -=1
left +=1
if right -left +1 == len(p) and scount == pcount:
ans.append(left)
right +=1
return ans
三、总结:
本题考察使用滑动串口思想遍历字符串,字符次数记录使用26个字母初始列表来进行记录,AC提交记录如下:
- 时间复杂度O(n+m+s),n为s字符串长度,m为p字符串长度,s为26字母长度
- 空间复杂度O(s),s为26个字母长度列表
以上是本期内容,欢迎大佬们点赞评论,下期见~~