📌  相关文章
📜  具有恰好 K 个不同字符的最小长度子串

📅  最后修改于: 2021-10-28 01:36:39             🧑  作者: Mango

给定一个字符串S和一个数字K 。任务是找到恰好具有 K 个不同字符的最小长度子串。
注意:字符串S 仅由小写英文字母组成。
例子:

Input:  S = "ababcb", K = 3
Output:  abc

Input:  S="efecfefd", K = 4
Output:  cfefd

简单的解决方案:简单的解决方案是考虑每个子字符串并检查它是否包含 k 个不同的字符。如果是,则将此子字符串的长度与之前找到的最小长度子字符串进行比较。这种方法的时间复杂度是 O(N 2 ),其中 N 是字符串 S 的长度。
有效的解决方案:一个有效的解决方案是使用滑动窗口技术和散列。这个想法是使用两个指针stend来表示滑动窗口的起点和终点。最初将两者都指向字符串的开头。向前移动 end 并增加相应字符的计数。如果计数为 1,则找到一个新的不同字符并增加不同字符数的计数。如果不同字符数的计数大于k则向前移动st并减少字符的计数。如果字符计数为零,则删除一个不同的字符,并且可以通过这种方式将不同元素的计数减少到k 。如果不同元素的计数为k ,则通过向前移动 st 从滑动窗口的开头删除计数大于 1 的字符。将当前滑动窗口的长度与迄今为止找到的最小长度进行比较,并在必要时进行更新。
请注意,每个字符最多只能从滑动窗口中添加和删除一次,因此每个字符被遍历两次。因此时间复杂度是线性的。
下面是上述方法的实现:

C++
// C++ program to find minimum length substring
// having exactly k distinct character.
 
#include 
using namespace std;
 
// Function to find minimum length substring
// having exactly k distinct character.
string findMinLenStr(string str, int k)
{
    int n = str.length();
 
    // Starting index of sliding window.
    int st = 0;
 
    // Ending index of sliding window.
    int end = 0;
 
    // To store count of character.
    int cnt[26];
    memset(cnt, 0, sizeof(cnt));
 
    // To store count of distinct
    // character in current sliding
    // window.
    int distEle = 0;
 
    // To store length of current
    // sliding window.
    int currlen;
 
    // To store minimum length.
    int minlen = n;
 
    // To store starting index of minimum
    // length substring.
    int startInd = -1;
 
    while (end < n) {
 
        // Increment count of current character
        // If this count is one then a new
        // distinct character is found in
        // sliding window.
        cnt[str[end] - 'a']++;
        if (cnt[str[end] - 'a'] == 1)
            distEle++;
 
        // If number of distinct characters is
        // is greater than k, then move starting
        // point of sliding window forward,
        // until count is k.
        if (distEle > k) {
            while (st < end && distEle > k) {
                if (cnt[str[st] - 'a'] == 1)
                    distEle--;
                cnt[str[st] - 'a']--;
                st++;
            }
        }
 
        // Remove characters from the beginning of
        // sliding window having count more than 1
        // to minimize length.
        if (distEle == k) {
            while (st < end && cnt[str[st] - 'a'] > 1) {
                cnt[str[st] - 'a']--;
                st++;
            }
 
            // Compare length with minimum length
            // and update if required.
            currlen = end - st + 1;
            if (currlen < minlen) {
                minlen = currlen;
                startInd = st;
            }
        }
 
        end++;
    }
 
    // Return minimum length  substring.
    return str.substr(startInd, minlen);
}
 
// Driver code
int main()
{
    string str = "efecfefd";
 
    int k = 4;
 
    cout << findMinLenStr(str, k);
 
    return 0;
}


Java
// Java program to find minimum length subString
// having exactly k distinct character.
class GFG
{
 
// Function to find minimum length subString
// having exactly k distinct character.
static String findMinLenStr(String str, int k)
{
    int n = str.length();
 
    // Starting index of sliding window.
    int st = 0;
 
    // Ending index of sliding window.
    int end = 0;
 
    // To store count of character.
    int cnt[] = new int[26];
    for(int i = 0; i < 26; i++)cnt[i] = 0;
 
    // To store count of distinct
    // character in current sliding
    // window.
    int distEle = 0;
 
    // To store length of current
    // sliding window.
    int currlen;
 
    // To store minimum length.
    int minlen = n;
 
    // To store starting index of minimum
    // length subString.
    int startInd = -1;
 
    while (end < n)
    {
 
        // Increment count of current character
        // If this count is one then a new
        // distinct character is found in
        // sliding window.
        cnt[str.charAt(end) - 'a']++;
        if (cnt[str.charAt(end) - 'a'] == 1)
            distEle++;
 
        // If number of distinct characters is
        // is greater than k, then move starting
        // point of sliding window forward,
        // until count is k.
        if (distEle > k)
        {
            while (st < end && distEle > k)
            {
                if (cnt[str.charAt(st) - 'a'] == 1)
                    distEle--;
                cnt[str.charAt(st) - 'a']--;
                st++;
            }
        }
 
        // Remove characters from the beginning of
        // sliding window having count more than 1
        // to minimize length.
        if (distEle == k)
        {
            while (st < end && cnt[str.charAt(st) - 'a'] > 1)
            {
                cnt[str.charAt(st) - 'a']--;
                st++;
            }
 
            // Compare length with minimum length
            // and update if required.
            currlen = end - st + 1;
            if (currlen < minlen)
            {
                minlen = currlen;
                startInd = st;
            }
        }
 
        end++;
    }
 
    // Return minimum length subString.
    return str.substring(startInd,startInd + minlen);
}
 
// Driver code
public static void main(String args[])
{
    String str = "efecfefd";
    int k = 4;
    System.out.println(findMinLenStr(str, k));
}
}
 
// This code is contributed by Arnab Kundu


Python 3
# Python 3 program to find minimum length
# substring having exactly k distinct character.
 
# Function to find minimum length substring
# having exactly k distinct character.
def findMinLenStr(str, k):
 
    n = len(str)
 
    # Starting index of sliding window.
    st = 0
 
    # Ending index of sliding window.
    end = 0
 
    # To store count of character.
    cnt = [0] * 26
 
    # To store count of distinct
    # character in current sliding
    # window.
    distEle = 0
 
    # To store length of current
    # sliding window.
    currlen =0
 
    # To store minimum length.
    minlen = n
 
    # To store starting index of minimum
    # length substring.
    startInd = -1
 
    while (end < n):
 
        # Increment count of current character
        # If this count is one then a new
        # distinct character is found in
        # sliding window.
        cnt[ord(str[end]) - ord('a')] += 1
        if (cnt[ord(str[end]) - ord('a')] == 1):
            distEle += 1
 
        # If number of distinct characters is
        # is greater than k, then move starting
        # point of sliding window forward,
        # until count is k.
        if (distEle > k):
            while (st < end and distEle > k):
                if (cnt[ord(str[st]) -
                        ord('a')] == 1):
                    distEle -= 1
                cnt[ord(str[st]) - ord('a')] -= 1
                st += 1
 
        # Remove characters from the beginning of
        # sliding window having count more than 1
        # to minimize length.
        if (distEle == k):
            while (st < end and cnt[ord(str[st]) -
                                    ord('a')] > 1):
                cnt[ord(str[st]) - ord('a')] -= 1
                st += 1
 
            # Compare length with minimum length
            # and update if required.
            currlen = end - st + 1
            if (currlen < minlen):
                minlen = currlen
                startInd = st
 
        end += 1
 
    # Return minimum length substring.
    return str[startInd : startInd + minlen]
 
# Driver code
if __name__ == "__main__":
     
    str = "efecfefd"
 
    k = 4
 
    print(findMinLenStr(str, k))
 
# This code is contributed by Ita_c


C#
// C# program to find minimum length subString
// having exactly k distinct character.
using System;
 
class GFG
{
 
    // Function to find minimum length subString
    // having exactly k distinct character.
    static String findMinLenStr(string str, int k)
    {
        int n = str.Length;
     
        // Starting index of sliding window.
        int st = 0;
     
        // Ending index of sliding window.
        int end = 0;
     
        // To store count of character.
        int []cnt = new int[26];
        for(int i = 0; i < 26; i++)cnt[i] = 0;
     
        // To store count of distinct
        // character in current sliding
        // window.
        int distEle = 0;
     
        // To store length of current
        // sliding window.
        int currlen;
     
        // To store minimum length.
        int minlen = n;
     
        // To store starting index of minimum
        // length subString.
        int startInd = -1;
     
        while (end < n)
        {
     
            // Increment count of current character
            // If this count is one then a new
            // distinct character is found in
            // sliding window.
            cnt[str[end] - 'a']++;
            if (cnt[str[end] - 'a'] == 1)
                distEle++;
     
            // If number of distinct characters is
            // is greater than k, then move starting
            // point of sliding window forward,
            // until count is k.
            if (distEle > k)
            {
                while (st < end && distEle > k)
                {
                    if (cnt[str[st] - 'a'] == 1)
                        distEle--;
                    cnt[str[st] - 'a']--;
                    st++;
                }
            }
     
            // Remove characters from the beginning of
            // sliding window having count more than 1
            // to minimize length.
            if (distEle == k)
            {
                while (st < end && cnt[str[st] - 'a'] > 1)
                {
                    cnt[str[st] - 'a']--;
                    st++;
                }
     
                // Compare length with minimum length
                // and update if required.
                currlen = end - st + 1;
                if (currlen < minlen)
                {
                    minlen = currlen;
                    startInd = st;
                }
            }
     
            end++;
        }
     
        // Return minimum length subString.
        return str.Substring(startInd, minlen);
    }
     
    // Driver code
    public static void Main()
    {
        string str = "efecfefd";
        int k = 4;
        Console.WriteLine(findMinLenStr(str, k));
    }
}
 
// This code is contributed by Ryuga


Javascript


输出:
cfefd

时间复杂度: O(N),其中 N 是给定字符串的长度。
辅助空间: O(1)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程