题解 | #寻找完成任务所需最短时间#

寻找完成任务所需最短时间

https://www.nowcoder.com/practice/107342346ad44329a35c7e5b890e7d40

知识点

hash,双指针

思路

由于我们需要在s中找到最小连续子串res来满足t中的每个字母都在res中出现过,且重复字母出现次数也要保证子串中该字符的数量必须不少于 t 字符串中该字符的数量。

所以,我们可以用两个map建立从char到int的映射a、b,用于记录t和res的每个字符出现次数。对于s,我们可以用双指针来维护res。

我们先编写一个函数用于检查当前res是否合法,显然需要遍历a的每一位,并在b中检测是否满足b.second>=a.second的合法关系(即res中当前字符出现次数大于t中当前字符出现次数)

 bool check(map<char, int>a, map<char, int>b) {
        for (auto v : a) {
            if (b[v.first] < v.second)return false;
        }
        return true;
    }

然后假定i为res左端点,j为res右端点,这两个是临时端点,不断右移j并更新b,若b合法,则尝试右移i,若i向右移动后仍合法,则可以右移,以达到缩减子串长度的目的。

对每个合法状态,维护最小的i-j+1,即为子串长度,若需要更新,则同步更新ii与jj,用于复原最终需要返回的答案字符串。

代码c++

class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param s string字符串
     * @param t string字符串
     * @return string字符串
     */
    bool check(map<char, int>a, map<char, int>b) {
        for (auto v : a) {
            if (b[v.first] < v.second)return false;
        }
        return true;
    }
    string minWindow(string s, string t) {
        // write code here
        map<char, int>a;
        map<char, int>b;
        for (int i = 0; i < t.size(); i++) {
            a[t[i]]++;
        }
        int i = 0, j = 1;
        int ans = 1000000;
        b[s[0]]++;
        bool flag = 0;
        int ii, jj;
        for (; j < s.size(); j++) {
            b[s[j]]++;
            if (check(a, b)) {
                while (b[s[i]] > a[s[i]]) {
                    b[s[i]]--;
                    i++;
                    flag = 1;
                }
                if (j - i + 1 < ans) {
                    ii = i;
                    jj = j;
                    cout << i << " " << j << endl;
                    ans = j - i + 1;
                }

            }
        }
        string res = "";
        if (!flag)return res;
        else {
            for (int k = ii; k <= jj; k++)res += s[k];
            return res;
        }

    }
};
全部评论

相关推荐

评论
点赞
收藏
分享
牛客网
牛客企业服务