我正在尝试用Java编写这样的算法。我正在测试String输入" abaab"。假设字符串输入为小写是安全的。
我无法检查我的算法出错的地方(它只输出" a"对于此输入而不是" ab"和" abaab&#34任何想法?
static void SmallestAndLargestSubstring(String input) {
char[] vowels = { 'a', 'e', 'i', 'o', 'u' };
char[] cons = { 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x',
'y', 'z' };
char[] charArray = input.toLowerCase().toCharArray();
int startIndex = 0;
int shortEndIndex = 0;
int longEndIndex = 0;
int large = longEndIndex - startIndex;
int small = shortEndIndex - startIndex;
ArrayList<Integer> start = new ArrayList<Integer>();
ArrayList<Integer> end = new ArrayList<Integer>();
outerloop: for (int i = 0; i < charArray.length; i++) {
for (int z = 0; z < vowels.length; z++) {
if (charArray[i] == vowels[z]) {
startIndex = i;
start.add(startIndex);
if (longEndIndex - startIndex > large) {
large = longEndIndex - startIndex;
}
if(longEndIndex - startIndex <= large){
shortEndIndex=start.get(start.size()-1);
}
if (shortEndIndex - startIndex < small) {
small = shortEndIndex - startIndex;
}
if(shortEndIndex - startIndex >=small){
shortEndIndex=start.get(start.size()-1);
}
continue outerloop;
}
}
for (int j = 0; j < cons.length; j++) {
if (charArray[i] == cons[j]) {
longEndIndex = i;
shortEndIndex = i;
end.add(longEndIndex);
if (longEndIndex - startIndex > large) {
large = longEndIndex - startIndex;
}if(longEndIndex - startIndex <= large){
longEndIndex=end.get(end.size()-1);
}
if (shortEndIndex - startIndex < small) {
small = shortEndIndex - startIndex;
}
if(shortEndIndex - startIndex >=small) {
shortEndIndex=end.get(end.size()-1);
}
continue outerloop;
}
}
}
System.out.println(input.substring(startIndex, shortEndIndex));
System.out.println(input.substring(startIndex, longEndIndex));
}
答案 0 :(得分:2)
这是我的解决方案:最长的子串总是从第一个元音开始,以最后一个辅音结束。 对于最短的,每次我读一个辅音时,我都会看到前一个元音的距离,看它是否更好。 在你读至少一个元音之前,你什么都做不了。
static void SmallestAndLargestSubstring(String input) {
char[] vowels = { 'a', 'e', 'i', 'o', 'u' };
char[] cons = { 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x',
'y', 'z' };
char[] charArray = input.toLowerCase().toCharArray();
int longStartIndex=0;
int shortStartIndex=0;
int shortEndIndex=0;
int longEndIndex=0;
boolean findVowel = false;
int bestStart = 0;
int bestEnd = 0;
int shortest =Integer.MAX_VALUE;
for (int i = 0; i < charArray.length; i++) {
for (int z = 0; z < vowels.length; z++) {
if (charArray[i] == vowels[z]) {
if (!findVowel){
// if this is the first vowel we see
longStartIndex = i;
shortStartIndex=i;
findVowel = true;
}
else {
shortStartIndex = i;
}
}
}
for (int j = 0; j < cons.length; j++) {
if (charArray[i] == cons[j]) {
if (findVowel){
// if we have seen any vowel, this consonant is useless
longEndIndex = i; // this one is always than the previous for the largest
shortEndIndex = i; // we have to check if this one is better or not
if (shortEndIndex-shortStartIndex<shortest){
bestStart = shortStartIndex;
bestEnd = shortEndIndex;
shortest = shortEndIndex-shortStartIndex;
}
}
}
}
}
System.out.println(input.substring(bestStart, bestEnd+1));
System.out.println(input.substring(longStartIndex, longEndIndex+1));
}
答案 1 :(得分:2)
我偶然发现了这个问题,寻找同样的问题。
对于字符串uauubbiox
,接受的答案中的程序输出:
ub
uauubbiox
这是错误的(正确答案是auub
和uubbiox
。)即使对于OP的问题,该程序也会给出错误的答案(abaab
而不是{{1} }。
解决此问题的正确方法是使用suffix arrays。这是一个伪代码,我相信它将为该问题产生正确的输出:
baab
让我们为测试字符串尝试一下。测试字符串的后缀数组为:
given string s as input
sa = suffix_array(s)
savf = the first string in sa which starts with a vowel
smallest substring = savf.substring(0, index of first consonant)
savl = the last string in sa which starts with a vowel
smallest substring = savf.substring(0, index of lastconsonant)
以元音开头的最小词典字符串是:
0 auubbiox
1 bbiox
2 biox
3 iox
4 ox
5 uauubbiox
6 ubbiox
7 uubbiox
我们只需要在此字符串中找到以辅音结尾的最小前缀。那就是上面字符串第3位的auubbiox
。因此,按字母顺序在字典上最小并以辅音结尾的最小字符串是:
b
对于其他字符串,请查看以元音开头的后缀数组中最大的字符串。那是索引7处的字符串:
auub
由于我们需要最大的字符串,因此我们应该选择以辅音结尾的最长的前缀。在这种情况下,这就是上面的整个字符串。因此,按字典顺序,以元音开头并以辅音结尾的最大字符串是:
uubbiox
可以在O(n)中计算字符串的后缀数组。 Wikipedia文章讨论了一些构造它的方法。互联网上也有一些聪明的技术,使创建代码相对容易进行编码和实现。我喜欢this one,它为后缀数组提供了非常简单明了且易于理解的技术,并具有O(nlog ^ 2(n))可接受的(在大多数情况下)时间复杂度
答案 2 :(得分:-1)
我觉得你的实施过于复杂。你想要抓住一些事情:
1)从元音到辅音的最小子串:这将是2个字符长或0个字符长。
2)从元音到辅音的最长子串:这是从第一个元音到最后一个辅音的距离,假设元音在辅音之前出现 - 否则长度为0。
以下是没有子字符串错误检查的示例实现:
import java.util.*;
public class cons {
public static void main(String...args)
{
String str = "abaab";
char[] vowels = { 'a', 'e', 'i', 'o', 'u' };
char[] cons = { 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x',
'y', 'z' };
int firstVowel = -1,lastConsonant = -1;
int consVowel = -1;
ArrayList<Character> vowel, con;
//I use lists for the .contains() method.
con = new ArrayList<Character>();
vowel = new ArrayList<Character>();
for (Character c : vowels)
vowel.add(c);
for (Character c : cons)
con.add(c);
//Algorithm starts here
for(int i = 0; i < str.length() - 1; i++)
{
//position i is a vowel
if (vowel.contains(str.charAt(i)))
{
//if first vowel isn't set, set it
if (firstVowel == -1)
firstVowel = i;
if (!vowel.contains(str.charAt(i+1)))
{
consVowel = i;
lastConsonant = i+1;
}
} else { //Otherwise it's a consonant.
lastConsonant = i; //set last consonant
}
}
System.out.println(str.substring(firstVowel,lastConsonant));
System.out.println(str.substring(consVowel, consVowel+2));
}
}