给定两个字符串S和T ,任务是从S中查找最小长度的前缀,该前缀由字符串T的所有字符组成。如果S不包含字符串T的所有字符,则打印-1 。
例子:
Input: S = “MarvoloGaunt”, T = “Tom”
Output: 12
Explanation:
The 12 length prefix “MarvoloGaunt” contains all the characters of “Tom”
Input: S = “TheWorld”, T = “Dio”
Output: -1
Explanation:
The string “TheWorld” does not contain the character ‘i’ from the string “Dio”.
天真的方法:
解决问题的最简单方法是迭代字符串S ,比较前缀和T中每个字母的频率,如果找到所需的前缀,则返回遍历的长度。否则,返回-1。
时间复杂度: O(N 2 )
辅助空间: O(1)
高效方法:
要优化上述方法,请按照以下步骤操作:
- 将T的频率存储在字典dictCount中。
- 将计数大于0的唯一字母数存储为nUnique 。
- 对[0,N]进行迭代,并获得S的第i个索引字符ch 。
- 从dictCount减少ch的计数(如果存在)。如果该计数变为0,则将nUnique减小1。
- 如果nUnique达到0,则返回到此为止遍历的长度。
- 在完成S的遍历之后,如果nUnique仍然超过0,则打印-1 。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
int getPrefixLength(string srcStr,
string targetStr)
{
// Base Case - if T is empty,
// it matches 0 length prefix
if (targetStr.length() == 0)
return 0;
// Convert strings to lower
// case for uniformity
transform(srcStr.begin(),
srcStr.end(),
srcStr.begin(), ::tolower);
transform(targetStr.begin(),
targetStr.end(),
targetStr.begin(), ::tolower);
map dictCount;
int nUnique = 0;
// Update dictCount to the
// letter count of T
for(char ch: targetStr)
{
// If new character is found,
// initialize its entry,
// and increase nUnique
if (dictCount.find(ch) ==
dictCount.end())
{
nUnique += 1;
dictCount[ch] = 0;
}
// Increase count of ch
dictCount[ch] += 1;
}
// Iterate from 0 to N
for(int i = 0; i < srcStr.length(); i++)
{
// i-th character
char ch = srcStr[i];
// Skip if ch not in targetStr
if (dictCount.find(ch) ==
dictCount.end())
continue;
// Decrease Count
dictCount[ch] -= 1;
// If the count of ch reaches 0,
// we do not need more ch,
// and can decrease nUnique
if (dictCount[ch] == 0)
nUnique -= 1;
// If nUnique reaches 0,
// we have found required prefix
if (nUnique == 0)
return (i + 1);
}
// Otherwise
return -1;
}
// Driver code
int main()
{
string S = "MarvoloGaunt";
string T = "Tom";
cout << getPrefixLength(S, T);
return 0;
}
// This code is contributed by divyeshrabadiya07
Java
// Java program for the above approach
import java.util.*;
public class Main
{
public static int getPrefixLength(String srcStr, String targetStr)
{
// Base Case - if T is empty,
// it matches 0 length prefix
if (targetStr.length() == 0)
return 0;
// Convert strings to lower
// case for uniformity
srcStr = srcStr.toLowerCase();
targetStr = targetStr.toLowerCase();
HashMap dictCount = new HashMap<>();
int nUnique = 0;
// Update dictCount to the
// letter count of T
for(char ch : targetStr.toCharArray())
{
// If new character is found,
// initialize its entry,
// and increase nUnique
if (dictCount.containsKey(ch) != true)
{
nUnique += 1;
dictCount.put(ch, 0);
}
// Increase count of ch
dictCount.replace(ch, dictCount.get(ch) + 1);
}
// Iterate from 0 to N
for(int i = 0; i < srcStr.length(); i++)
{
// i-th character
char ch = srcStr.charAt(i);
// Skip if ch not in targetStr
if (dictCount.containsKey(ch) != true)
continue;
// Decrease Count
dictCount.replace(ch, dictCount.get(ch) - 1);
// If the count of ch reaches 0,
// we do not need more ch,
// and can decrease nUnique
if (dictCount.get(ch) == 0)
nUnique -= 1;
// If nUnique reaches 0,
// we have found required prefix
if (nUnique == 0)
return (i + 1);
}
// Otherwise
return -1;
}
// Driver code
public static void main(String[] args) {
String S = "MarvoloGaunt";
String T = "Tom";
System.out.println(getPrefixLength(S, T));
}
}
// This code is contributed by divyesh072019
Python3
# Python3 program for the above approach
def getPrefixLength(srcStr, targetStr):
# Base Case - if T is empty,
# it matches 0 length prefix
if(len(targetStr) == 0):
return 0
# Convert strings to lower
# case for uniformity
srcStr = srcStr.lower()
targetStr = targetStr.lower()
dictCount = dict([])
nUnique = 0
# Update dictCount to the
# letter count of T
for ch in targetStr:
# If new character is found,
# initialize its entry,
# and increase nUnique
if(ch not in dictCount):
nUnique += 1
dictCount[ch] = 0
# Increase count of ch
dictCount[ch] += 1
# Iterate from 0 to N
for i in range(len(srcStr)):
# i-th character
ch = srcStr[i]
# Skip if ch not in targetStr
if(ch not in dictCount):
continue
# Decrease Count
dictCount[ch] -= 1
# If the count of ch reaches 0,
# we do not need more ch,
# and can decrease nUnique
if(dictCount[ch] == 0):
nUnique -= 1
# If nUnique reaches 0,
# we have found required prefix
if(nUnique == 0):
return (i + 1)
# Otherwise
return -1
# Driver Code
if __name__ == "__main__":
S = "MarvoloGaunt"
T = "Tom"
print(getPrefixLength(S, T))
C#
// C# program for the above approach
using System.Collections.Generic;
using System;
class GFG{
static int getPrefixLength(string srcStr,
string targetStr)
{
// Base Case - if T is empty,
// it matches 0 length prefix
if (targetStr.Length == 0)
return 0;
// Convert strings to lower
// case for uniformity
srcStr = srcStr.ToLower();
targetStr = targetStr.ToLower();
Dictionary dictCount = new Dictionary();
int nUnique = 0;
// Update dictCount to the
// letter count of T
foreach(var ch in targetStr)
{
// If new character is found,
// initialize its entry,
// and increase nUnique
if (dictCount.ContainsKey(ch) != true)
{
nUnique += 1;
dictCount[ch] = 0;
}
// Increase count of ch
dictCount[ch] += 1;
}
// Iterate from 0 to N
for(int i = 0; i < srcStr.Length; i++)
{
// i-th character
char ch = srcStr[i];
// Skip if ch not in targetStr
if (dictCount.ContainsKey(ch) != true)
continue;
// Decrease Count
dictCount[ch] -= 1;
// If the count of ch reaches 0,
// we do not need more ch,
// and can decrease nUnique
if (dictCount[ch] == 0)
nUnique -= 1;
// If nUnique reaches 0,
// we have found required prefix
if (nUnique == 0)
return (i + 1);
}
// Otherwise
return -1;
}
// Driver code
public static void Main()
{
string S = "MarvoloGaunt";
string T = "Tom";
Console.Write(getPrefixLength(S, T));
}
}
// This code is contributed by Stream_Cipher
输出:
12
时间复杂度: O(N)
辅助空间: O(1)