给定一个字符串,找出具有给定字符串所有不同字符的最小窗口长度。例如。 str = “aabcbcdbca”,那么结果将是 4,因为最小的窗口将是 “dbca”。
例子:
Input: aabcbcdbca
Output: dbca
Explanation:
Possible substrings= {aabcbcd, abcbcd,
bcdbca, dbca....}
Of the set of possible substrings 'dbca'
is the shortest substring having all the
distinct characters of given string.
Input: aaab
Output: ab
Explanation:
Possible substrings={aaab, aab, ab}
Of the set of possible substrings 'ab'
is the shortest substring having all
the distinct characters of given string.
解决方案:上面的问题表明,即使最小的字符串包含重复元素,我们也必须找到包含给定字符串的所有不同字符的最小窗口。
例如,在“aabcbcdb”中,包含所有字符的最小字符串是“abcbcd”。
方法一:这是使用HashMap解决问题的Brute Force方法。
- 方法:为了解决这个问题,我们首先要找出字符串存在的所有不同的字符。这可以使用HashMap来完成。接下来是生成所有可能的子串。接下来是检查生成的子字符串是否具有所有必需的字符(存储在 hash_map 中)。如果是,则将其长度与遵循上述约束的最小子串长度进行比较,直到现在。
HashMap :自Java 1.2 起,HashMap 是 Java 集合的一部分。它提供了Java Map 接口的基本实现。它将数据存储在(键,值)对中。要访问一个值,必须知道它的键。 HashMap 之所以称为 HashMap,是因为它使用了一种称为 Hashing 的技术。散列是一种将大字符串转换为表示相同字符串的小字符串的技术。较短的值有助于索引和更快的搜索。 HashSet 也在内部使用 HashMap。它在内部使用一个链接列表来存储键值对,这些键值对已经在 HashSet 和进一步的文章中详细解释过。 - 算法 :
- 将给定字符串的所有不同字符存储在 hash_map 中。
- 取一个变量 count 并将其初始化为值 0。
- 使用两个指针生成子串。
- 现在检查生成的子字符串是否有效-:
- 一旦我们发现之前没有遇到过生成的子串的字符,将 count 增加1 。
- 我们可以使用一个大小为max_chars的访问过的数组来查找当前字符之前是否遇到过。
- 如果 count 等于 hash_map 的大小,则生成的子串有效
- 如果它是有效的子字符串,则将其与已生成的最小长度子字符串进行比较。
- 伪代码:
maphash_map;
for ( i=0 to str.length())
hash_map[str[i]]++;//finding all distinct characters of string
minimum_size=INT_MAX
Distinct_chars=hash_map.size()
for(i=0 to str.length())
count=0;
sub_str="";
visited[256]={0};
for(j=i to n)
sub_str+=str[j]
if(visited[str[j]]==0)
count++
visited[str[j]]=1;
if(count==Distinct_chars)
end loop
if(sub_str.length()
- 执行:
CPP
// C++ program to find the smallest
// window containing all characters
// of a pattern.
#include
using namespace std;
const int MAX_CHARS = 256;
// Function to find smallest window containing
// all distinct characters
string findSubString(string str)
{
int n = str.length();
// Count all distinct characters.
int dist_count = 0;
unordered_map hash_map;
for (int i = 0; i < n; i++) {
hash_map[str[i]]++;
}
dist_count = hash_map.size();
int size = INT_MAX;
string res;
// Now follow the algorithm discussed in below
for (int i = 0; i < n; i++) {
int count = 0;
int visited[256] = { 0 };
string sub_str = "";
for (int j = i; j < n; j++) {
if (visited[str[j]] == 0) {
count++;
visited[str[j]] = 1;
}
sub_str += str[j];
if (count == dist_count)
break;
}
if (sub_str.length() < size && count == dist_count)
{
res = sub_str;
size=res.length();
}
}
return res;
}
// Driver Code
int main()
{
string str = "aabcbcdbca";
cout << "Smallest window containing all distinct"
" characters is: "
<< findSubString(str);
return 0;
}
Java
import java.io.*;
import java.util.*;
// Java program to find the smallest
// window containing all characters
// of a pattern.
class GFG
{
// Function to find smallest window containing
// all distinct characters
public static String findSubString(String str)
{
int n = str.length();
// Count all distinct characters.
int dist_count = 0;
HashMap mp = new HashMap<>();
for (int i = 0; i < n; i++)
{
if (mp.containsKey(str.charAt(i)))
{
Integer a = mp.get(str.charAt(i));
mp.put(str.charAt(i),a+1);
}
else
{
mp.put(str.charAt(i), 1);
}
}
dist_count = mp.size();
int size = Integer.MAX_VALUE;
String res = "";
// Now follow the algorithm discussed in below
for (int i = 0; i < n; i++)
{
int count = 0;
int visited[] = new int[256];
for(int j = 0; j < 256; j++)
visited[j] = 0;
String sub_str = "";
for (int j = i; j < n; j++)
{
if (visited[str.charAt(j)] == 0)
{
count++;
visited[str.charAt(j)] = 1;
}
sub_str += str.charAt(j);
if (count == dist_count)
break;
}
if (sub_str.length() < size && count == dist_count)
{
res = sub_str;
size=res.length();
}
}
return res;
}
// Driver code
public static void main (String[] args)
{
String str = "aabcbcdbca";
System.out.println("Smallest window containing all distinct"+
" characters is: "+ findSubString(str)) ;
}
}
// This code is contributed by Manu Pathria
C++
// C++ program to find the smallest
// window containing all characters
// of a pattern.
#include
using namespace std;
const int MAX_CHARS = 256;
// Function to find smallest window containing
// all distinct characters
string findSubString(string str)
{
int n = str.length();
// if string is empty or having one char
if (n <= 1)
return str;
// Count all distinct characters.
int dist_count = 0;
bool visited[MAX_CHARS] = { false };
for (int i = 0; i < n; i++) {
if (visited[str[i]] == false) {
visited[str[i]] = true;
dist_count++;
}
}
// Now follow the algorithm discussed in below
// post. We basically maintain a window of characters
// that contains all characters of given string.
int start = 0, start_index = -1, min_len = INT_MAX;
int count = 0;
int curr_count[MAX_CHARS] = { 0 };
for (int j = 0; j < n; j++) {
// Count occurrence of characters of string
curr_count[str[j]]++;
// If any distinct character matched,
// then increment count
if (curr_count[str[j]] == 1)
count++;
// if all the characters are matched
if (count == dist_count) {
// Try to minimize the window i.e., check if
// any character is occurring more no. of times
// than its occurrence in pattern, if yes
// then remove it from starting and also remove
// the useless characters.
while (curr_count[str[start]] > 1) {
if (curr_count[str[start]] > 1)
curr_count[str[start]]--;
start++;
}
// Update window size
int len_window = j - start + 1;
if (min_len > len_window) {
min_len = len_window;
start_index = start;
}
}
}
// Return substring starting from start_index
// and length min_len
return str.substr(start_index, min_len);
}
// Driver code
int main()
{
string str = "aabcbcdbca";
cout << "Smallest window containing all distinct"
" characters is: "
<< findSubString(str);
return 0;
}
Java
// Java program to find the smallest window containing
// all characters of a pattern.
import java.util.Arrays;
public class GFG {
static final int MAX_CHARS = 256;
// Function to find smallest window containing
// all distinct characters
static String findSubString(String str)
{
int n = str.length();
// if string is empty or having one char
if (n <= 1)
return str;
// Count all distinct characters.
int dist_count = 0;
boolean[] visited = new boolean[MAX_CHARS];
Arrays.fill(visited, false);
for (int i = 0; i < n; i++) {
if (visited[str.charAt(i)] == false) {
visited[str.charAt(i)] = true;
dist_count++;
}
}
// Now follow the algorithm discussed in below
// post. We basically maintain a window of
// characters that contains all characters of given
// string.
int start = 0, start_index = -1;
int min_len = Integer.MAX_VALUE;
int count = 0;
int[] curr_count = new int[MAX_CHARS];
for (int j = 0; j < n; j++) {
// Count occurrence of characters of string
curr_count[str.charAt(j)]++;
// If any distinct character matched,
// then increment count
if (curr_count[str.charAt(j)] == 1)
count++;
// if all the characters are matched
if (count == dist_count) {
// Try to minimize the window i.e., check if
// any character is occurring more no. of
// times than its occurrence in pattern, if
// yes then remove it from starting and also
// remove the useless characters.
while (curr_count[str.charAt(start)] > 1) {
if (curr_count[str.charAt(start)] > 1)
curr_count[str.charAt(start)]--;
start++;
}
// Update window size
int len_window = j - start + 1;
if (min_len > len_window) {
min_len = len_window;
start_index = start;
}
}
}
// Return substring starting from start_index
// and length min_len
return str.substring(start_index,
start_index + min_len);
}
// Driver code
public static void main(String args[])
{
String str = "aabcbcdbca";
System.out.println(
"Smallest window containing all distinct"
+ " characters is: " + findSubString(str));
}
}
// This code is contributed by Sumit Ghosh
Python
# Python program to find the smallest
# window containing
# all characters of a pattern
from collections import defaultdict
MAX_CHARS = 256
# Function to find smallest window
# containing all distinct characters
def findSubString(strr):
n = len(strr)
# if string is empty or having one char
if n <= 1:
return strr
# Count all distinct characters.
dist_count = len(set([x for x in strr]))
curr_count = defaultdict(lambda: 0)
count = 0
start = 0
min_len = n
# Now follow the algorithm discussed in below
# post. We basically maintain a window of characters
# that contains all characters of given string.
for j in range(n):
curr_count[strr[j]] += 1
# If any distinct character matched,
# then increment count
if curr_count[strr[j]] == 1:
count += 1
# Try to minimize the window i.e., check if
# any character is occurring more no. of times
# than its occurrence in pattern, if yes
# then remove it from starting and also remove
# the useless characters.
if count == dist_count:
while curr_count[strr[start]] > 1:
if curr_count[strr[start]] > 1:
curr_count[strr[start]] -= 1
start += 1
# Update window size
len_window = j - start + 1
if min_len > len_window:
min_len = len_window
start_index = start
# Return substring starting from start_index
# and length min_len """
return str(strr[start_index: start_index +
min_len])
# Driver code
if __name__ == '__main__':
print("Smallest window containing "
"all distinct characters is: {}".format(
findSubString("aabcbcdbca")))
# This code is contributed by
# Subhrajit
C#
// C# program to find the smallest window containing
// all characters of a pattern.
using System;
class GFG {
static int MAX_CHARS = 256;
// Function to find smallest window containing
// all distinct characters
static string findSubString(string str)
{
int n = str.Length;
// if string is empty or having one char
if (n <= 1)
return str;
// Count all distinct characters.
int dist_count = 0;
bool[] visited = new bool[MAX_CHARS];
for (int i = 0; i < n; i++) {
if (visited[str[i]] == false) {
visited[str[i]] = true;
dist_count++;
}
}
// Now follow the algorithm discussed in below
// post. We basically maintain a window of
// characters that contains all characters of given
// string.
int start = 0, start_index = -1,
min_len = int.MaxValue;
int count = 0;
int[] curr_count = new int[MAX_CHARS];
for (int j = 0; j < n; j++) {
// Count occurrence of characters of string
curr_count[str[j]]++;
// If any distinct character matched,
// then increment count
if (curr_count[str[j]] == 1)
count++;
// if all the characters are matched
if (count == dist_count) {
// Try to minimize the window i.e., check if
// any character is occurring more no. of
// times than its occurrence in pattern, if
// yes then remove it from starting and also
// remove the useless characters.
while (curr_count[str[start]] > 1) {
if (curr_count[str[start]] > 1)
curr_count[str[start]]--;
start++;
}
// Update window size
int len_window = j - start + 1;
if (min_len > len_window) {
min_len = len_window;
start_index = start;
}
}
}
// Return substring starting from start_index
// and length min_len
return str.Substring(start_index, min_len);
}
// Driver code
public static void Main(String[] args)
{
string str = "aabcbcdbca";
Console.WriteLine(
"Smallest window containing all distinct"
+ " characters is: " + findSubString(str));
}
}
// This code contributed by Rajput-Ji
输出
Smallest window containing all distinct characters is: dbca
- 复杂度分析:
- 时间复杂度: O(N^2)。
这个时间需要生成长度为“N”的字符串的所有可能的子字符串。 - 空间复杂度: O(N)。
由于已使用大小为 N 的hash_map 。
- 时间复杂度: O(N^2)。
方法二:这里我们使用了滑动窗口技术来解决。该技术展示了如何将少数问题中的嵌套 for 循环转换为单个 for 循环,从而降低时间复杂度。
- 方法:基本上一个字符窗口是通过使用两个指针来维护的,即start和end 。这些开始和结束指针可分别用于缩小和增加窗口的大小。每当窗口包含给定字符串 的所有字符时,窗口从左侧缩小以删除多余的字符,然后将其长度与迄今为止找到的最小窗口进行比较。
如果在当前窗口中,不能删除更多字符,那么我们开始使用结尾增加窗口的大小,直到字符串中存在的所有不同字符也在窗口中。最后,找到每个窗口的最小尺寸。
- 算法 :
- 维护一个包含最大可能字符(256 个字符)的数组(已访问) ,一旦我们在字符串找到任何字符,就在数组中标记该索引(这是为了计算字符串所有不同的字符)。
- 取两个指针开始和结束,这将标记窗口的开始和结束。
- 取一个counter=0将用于计算窗口中不同的字符。
- 现在开始阅读给定的字符串的字符,如果我们遇到尚未访问尚未1,计数器增加一个字符。
- 如果计数器等于不同字符总数,则尝试缩小窗口。
- 为了缩小窗口 -:
- 如果起始指针处的字符频率大于 1,则增加指针,因为它是多余的。
- 现在将当前窗口的长度与最小窗口长度进行比较。
- 执行:
C++
// C++ program to find the smallest
// window containing all characters
// of a pattern.
#include
using namespace std;
const int MAX_CHARS = 256;
// Function to find smallest window containing
// all distinct characters
string findSubString(string str)
{
int n = str.length();
// if string is empty or having one char
if (n <= 1)
return str;
// Count all distinct characters.
int dist_count = 0;
bool visited[MAX_CHARS] = { false };
for (int i = 0; i < n; i++) {
if (visited[str[i]] == false) {
visited[str[i]] = true;
dist_count++;
}
}
// Now follow the algorithm discussed in below
// post. We basically maintain a window of characters
// that contains all characters of given string.
int start = 0, start_index = -1, min_len = INT_MAX;
int count = 0;
int curr_count[MAX_CHARS] = { 0 };
for (int j = 0; j < n; j++) {
// Count occurrence of characters of string
curr_count[str[j]]++;
// If any distinct character matched,
// then increment count
if (curr_count[str[j]] == 1)
count++;
// if all the characters are matched
if (count == dist_count) {
// Try to minimize the window i.e., check if
// any character is occurring more no. of times
// than its occurrence in pattern, if yes
// then remove it from starting and also remove
// the useless characters.
while (curr_count[str[start]] > 1) {
if (curr_count[str[start]] > 1)
curr_count[str[start]]--;
start++;
}
// Update window size
int len_window = j - start + 1;
if (min_len > len_window) {
min_len = len_window;
start_index = start;
}
}
}
// Return substring starting from start_index
// and length min_len
return str.substr(start_index, min_len);
}
// Driver code
int main()
{
string str = "aabcbcdbca";
cout << "Smallest window containing all distinct"
" characters is: "
<< findSubString(str);
return 0;
}
Java
// Java program to find the smallest window containing
// all characters of a pattern.
import java.util.Arrays;
public class GFG {
static final int MAX_CHARS = 256;
// Function to find smallest window containing
// all distinct characters
static String findSubString(String str)
{
int n = str.length();
// if string is empty or having one char
if (n <= 1)
return str;
// Count all distinct characters.
int dist_count = 0;
boolean[] visited = new boolean[MAX_CHARS];
Arrays.fill(visited, false);
for (int i = 0; i < n; i++) {
if (visited[str.charAt(i)] == false) {
visited[str.charAt(i)] = true;
dist_count++;
}
}
// Now follow the algorithm discussed in below
// post. We basically maintain a window of
// characters that contains all characters of given
// string.
int start = 0, start_index = -1;
int min_len = Integer.MAX_VALUE;
int count = 0;
int[] curr_count = new int[MAX_CHARS];
for (int j = 0; j < n; j++) {
// Count occurrence of characters of string
curr_count[str.charAt(j)]++;
// If any distinct character matched,
// then increment count
if (curr_count[str.charAt(j)] == 1)
count++;
// if all the characters are matched
if (count == dist_count) {
// Try to minimize the window i.e., check if
// any character is occurring more no. of
// times than its occurrence in pattern, if
// yes then remove it from starting and also
// remove the useless characters.
while (curr_count[str.charAt(start)] > 1) {
if (curr_count[str.charAt(start)] > 1)
curr_count[str.charAt(start)]--;
start++;
}
// Update window size
int len_window = j - start + 1;
if (min_len > len_window) {
min_len = len_window;
start_index = start;
}
}
}
// Return substring starting from start_index
// and length min_len
return str.substring(start_index,
start_index + min_len);
}
// Driver code
public static void main(String args[])
{
String str = "aabcbcdbca";
System.out.println(
"Smallest window containing all distinct"
+ " characters is: " + findSubString(str));
}
}
// This code is contributed by Sumit Ghosh
Python
# Python program to find the smallest
# window containing
# all characters of a pattern
from collections import defaultdict
MAX_CHARS = 256
# Function to find smallest window
# containing all distinct characters
def findSubString(strr):
n = len(strr)
# if string is empty or having one char
if n <= 1:
return strr
# Count all distinct characters.
dist_count = len(set([x for x in strr]))
curr_count = defaultdict(lambda: 0)
count = 0
start = 0
min_len = n
# Now follow the algorithm discussed in below
# post. We basically maintain a window of characters
# that contains all characters of given string.
for j in range(n):
curr_count[strr[j]] += 1
# If any distinct character matched,
# then increment count
if curr_count[strr[j]] == 1:
count += 1
# Try to minimize the window i.e., check if
# any character is occurring more no. of times
# than its occurrence in pattern, if yes
# then remove it from starting and also remove
# the useless characters.
if count == dist_count:
while curr_count[strr[start]] > 1:
if curr_count[strr[start]] > 1:
curr_count[strr[start]] -= 1
start += 1
# Update window size
len_window = j - start + 1
if min_len > len_window:
min_len = len_window
start_index = start
# Return substring starting from start_index
# and length min_len """
return str(strr[start_index: start_index +
min_len])
# Driver code
if __name__ == '__main__':
print("Smallest window containing "
"all distinct characters is: {}".format(
findSubString("aabcbcdbca")))
# This code is contributed by
# Subhrajit
C#
// C# program to find the smallest window containing
// all characters of a pattern.
using System;
class GFG {
static int MAX_CHARS = 256;
// Function to find smallest window containing
// all distinct characters
static string findSubString(string str)
{
int n = str.Length;
// if string is empty or having one char
if (n <= 1)
return str;
// Count all distinct characters.
int dist_count = 0;
bool[] visited = new bool[MAX_CHARS];
for (int i = 0; i < n; i++) {
if (visited[str[i]] == false) {
visited[str[i]] = true;
dist_count++;
}
}
// Now follow the algorithm discussed in below
// post. We basically maintain a window of
// characters that contains all characters of given
// string.
int start = 0, start_index = -1,
min_len = int.MaxValue;
int count = 0;
int[] curr_count = new int[MAX_CHARS];
for (int j = 0; j < n; j++) {
// Count occurrence of characters of string
curr_count[str[j]]++;
// If any distinct character matched,
// then increment count
if (curr_count[str[j]] == 1)
count++;
// if all the characters are matched
if (count == dist_count) {
// Try to minimize the window i.e., check if
// any character is occurring more no. of
// times than its occurrence in pattern, if
// yes then remove it from starting and also
// remove the useless characters.
while (curr_count[str[start]] > 1) {
if (curr_count[str[start]] > 1)
curr_count[str[start]]--;
start++;
}
// Update window size
int len_window = j - start + 1;
if (min_len > len_window) {
min_len = len_window;
start_index = start;
}
}
}
// Return substring starting from start_index
// and length min_len
return str.Substring(start_index, min_len);
}
// Driver code
public static void Main(String[] args)
{
string str = "aabcbcdbca";
Console.WriteLine(
"Smallest window containing all distinct"
+ " characters is: " + findSubString(str));
}
}
// This code contributed by Rajput-Ji
输出
Smallest window containing all distinct characters is: dbca
- 复杂度分析:
- 时间复杂度: O(N)。
由于字符串仅使用两个指针遍历一次。 - 空间复杂度: O(N)。
使用大小为 N 的hash_map
- 时间复杂度: O(N)。
相关文章:
- 由最大不同字符组成的最小子字符串的长度
- https://www.geeksforgeeks.org/find-the-smallest-window-in-a-string- contains-all-characters-of-another-string/
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。