【LeetCode】187. 重复的DNA序列

208 阅读3分钟

image.png

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情

测试岗位也越来卷了,除了基本的功能测试外,还要有编程基础、脚本经验才脱颖而出。

怎么才能提高我们的编程能力呢,刷LeetCode是最佳的途径之一,话不多数,刷题走起~

一、题目描述:

  • 题目内容

image.png

  • 题目示例

image.png

  • 题目解析

    • 本题给出一个由"A"、"C"、"G"和"T"组成的字符串s
    • 字符串s的长度为0~10000

二、思路分析:

我们已经刷题一段时间了,对于指针类型的已经有了了解。本题将学会新的技能--滑动窗口

  • 什么是滑动窗口?

  • 滑动窗口是基于双指针概念,左右指针指向元素之间形式一个范围(窗口)

  • 通常滑动窗口分为:固定大小的窗口和动态变化的窗口

  • 使用数据类型通常是数组或者字符串 image.png

根据本题题意,要求我们在一串字符串中查找子串,判断条件如下:

  • 子串要求长度为10
  • 子串在字符串s中出现的次数大于1

查看本题示例后,对于本题的解答,无脑是使用滑动窗口的思想就能解答了。(此处有坑)

  • 使用for循环对字符串s进行遍历,范围在[0,len(s)-9]
  • 因为要求是子串长度为10的,因此使用字符串分片的方法去s[i:i+10]的子串
  • 使用第二个for循环,对取出的子串s[i:i+10]在字符串s中查找出现的次数
  • 当出现次数大于1并且没有出现ans列表中,则进行添加ans
  • 知道遍历完字符串,返回ans结果

使用Python将上述思路实现后,测试几个case无误,提交一看case 30/31,出现超时

ans = []
for i in range(len(s)-9):
    tmp = s[i:i+10]
    t = 0
    for j in range(len(s)-9):
        if  tmp == s[j:j+10]:
            t = t + 1
        if t > 1 and tmp not in ans:
            ans.append(tmp)
return ans

使用两个for循环,执行效率的确很低,那有什么方式可以优化呢?

  • 着力点:必须要干掉一个for循环
  • 方法:借助字典,来存储子串在字符串s中出现的次数
  • 子串 tmp 作为win字典key,出现的次数作为value
  • 当win[tmp]次数大于1时,则ans列表将tmp进行添加

干掉for循环,代码优化如下

ans = []
win = {}
for i in range(len(s) - 9):

    tmp = s[i:i + 10]
    if tmp in win.keys():
        win[tmp] = win[tmp] + 1
    else:
        win[tmp] = 1

    if win[tmp] > 1 and tmp not in ans:
        ans.append(tmp)
return ans

由于字符串s长度在0~10000之间,我们可以在代码开始前进行判断,不符合直接返回空列表

if len(s) < 10 or len(s) > 10000:
    return ans

三、总结:

本题考察是滑动窗口思想,为了提高运行效率,可以先对字符串范围进行判断。AC提交记录如下:

image.png

时间复杂度O(NL),N为字符串长度,L为子串目标长度10 空间复杂度O(NL)

以上是本期内容,欢迎大佬们点赞评论,下期见~~~