今日份的算法题【leetcode76】最小覆盖子串

96 阅读2分钟

我正在参加「掘金·启航计划」

最小覆盖子串

题目描述

image.png

题目分析

这道题目是典型的滑动窗口解决题目。 我们可以通过两个步骤来解决

  • 定义两个指针。通过改变指针的位置来寻找所有子串。
  • 在子串中找出长度最小的子串

注意题目最后一句。此题目的解法需要将时间复杂度控制在O(n)内 大家注意这个t字符串里面是可以有重复的值出现的。这个时候。选择一种合适的数据结构来存储字符串t和t的数量。尤为重要。

什么样的数据结构既能存储字符串的长度。字符串内每个字符出现的个数。还能动态改变字符串数量?

es6中有一种结构是字典。我们可以通过字典来存储t字符串。

比如t="a,b,c,d,a"

a->2 ,b->1, c->1, d->1

  let tMap = new Map()
  for (let i in t) {
    tMap.set(t[i], tMap.has(t[i]) ? tMap.get(t[i]) + 1 : 1)
  }
  let tSize = tMap.size

这样就完成对t字符串的存储。接下来。我们就可以开始解题了。

解题步骤

  • 定义两个指正 l和r,都指向s字符串的0位置。
  • 从0开始移动r的坐标。如果遇到tMap中存储的key。则动态减少此key对应的值。可以减少到负数。
  • 如果tMap中的key减少到0。则将tSize对应减少1。
  • 当tSize减少到0。则找到一个子串。
  while (r < s.length ) {
    if (tMap.has(s[r]) ) {
      tMap.set(s[r], tMap.get(s[r]) - 1)
      if (tMap.get(s[r]) === 0) tSize--
    }
    r++
  }

这个时候我们已经找到第一个子串了。r的坐标可以暂时锁定。开始移动l坐标。

  • l坐标从零开始移动。
  • tMap中有l坐标对应的key。则操作tMap数据。当tMap中某一项值为1,tSize++

这个时候,我们将会把l坐标,移动到第一个不符合子串的位置。后开始重新移动l坐标。

    while (tSize === 0) {
      if (tMap.has(s[l])) {
        const newRes = s.substring(l, r + 1)
        res = !res||newRes.length<res.length?newRes:res
        tMap.set(s[l], tMap.get(s[l]) + 1)
        if (tMap.get(s[l]) === 1) {
          tSize++
        }
      }
      l++
    }

循环上述步骤。则会得到所有子串。在子串中找到最小子串,就完美解决该题目。

完整解题代码

/**
 * @param {string} s
 * @param {string} t
 * @return {string}
 */
var minWindow = function (s, t) {
  let l = 0,
    r = 0,
    tMap = new Map(),
    res='';
  for (let i in t) {
    tMap.set(t[i], tMap.has(t[i]) ? tMap.get(t[i]) + 1 : 1)
  }
  let tSize = tMap.size
  while (r < s.length ) {
    if (tMap.has(s[r]) ) {
      tMap.set(s[r], tMap.get(s[r]) - 1)
      if (tMap.get(s[r]) === 0) tSize--
    }
    while (tSize === 0) {
      if (tMap.has(s[l])) {
        const newRes = s.substring(l, r + 1)
        res = !res||newRes.length<res.length?newRes:res
        tMap.set(s[l], tMap.get(s[l]) + 1)
        if (tMap.get(s[l]) === 1) {
          tSize++
        }
      }
      l++
    }
    r++
  }
  return res
}

复杂度

我们解决此题目的 时间复杂度:O(m)+O(n) 空间复杂度:O(m)

其中 m为t字符串的长度 n为s字符串的长度