Roh*_*ain 6 java language-agnostic string algorithm
好的,这是一个面试问题.不,这不是这个问题的重复.
鉴于3串- ,str1,:str2str3
str1 = "spqrstrupvqw"
str2 = "sprt"
str3 = "q"
Run Code Online (Sandbox Code Playgroud)
我们要找到最小窗口str1,其中包含str2任何顺序的所有字符,但不包含任何字符str3.在这种情况下,答案是:"strup".
我想出了这段代码:
static String minimumWindow(String str1, String str2, String str3) {
class Window implements Comparable<Window> {
int start;
int end;
public Window(int start, int end) {
this.start = start;
this.end = end;
}
public int getEnd() {
return end;
}
public int getStart() {
return start;
}
public int compareTo(Window o) {
int thisDiff = end - start;
int thatDiff = o.end - o.start;
return Integer.compare(thisDiff, thatDiff);
}
@Override
public String toString() {
return "[" + start + " : " + end + "]";
}
}
// Create Sets of characters for "contains()" check
Set<Character> str2Chars = new HashSet<>();
for (char ch: str2.toCharArray()) {
str2Chars.add(ch);
}
Set<Character> str3Chars = new HashSet<>();
for (char ch: str3.toCharArray()) {
str3Chars.add(ch);
}
// This will store all valid window which doesn't contain characters
// from str3.
Set<Window> set = new TreeSet<>();
int begin = -1;
// This loops gets each pair of index, such that substring from
// [start, end) in each window doesn't contain any characters from str3
for (int i = 0; i < str1.length(); i++) {
if (str3Chars.contains(str1.charAt(i))) {
set.add(new Window(begin, i));
begin = i + 1;
}
}
int minLength = Integer.MAX_VALUE;
String minString = "";
// Iterate over the windows to find minimum length string containing all
// characters from str2
for (Window window: set) {
if ((window.getEnd() - 1 - window.getStart()) < str2.length()) {
continue;
}
for (int i = window.getStart(); i < window.getEnd(); i++) {
if (str2Chars.contains(str1.charAt(i))) {
// Got first character in this window that is in str2
// Start iterating from end to get last character
// [start, end) substring will be the minimum length
// string in this window
for (int j = window.getEnd() - 1; j > i; j--) {
if (str2Chars.contains(str1.charAt(j))) {
String s = str1.substring(i, j + 1);
Set<Character> sChars = new HashSet<>();
for (char ch: s.toCharArray()) {
sChars.add(ch);
}
// If this substring contains all characters from str2,
// then only it is valid window.
if (sChars.containsAll(str2Chars)) {
int len = sChars.size();
if (len < minLength) {
minLength = len;
minString = s;
}
}
}
}
}
}
}
// There are cases when some trailing and leading characters are
// repeated somewhere in the middle. We don't need to include them in the
// minLength.
// In the given example, the actual string would come as - "rstrup", but we
// remove the first "r" safely.
StringBuilder strBuilder = new StringBuilder(minString);
while (strBuilder.length() > 1 && strBuilder.substring(1).contains("" + strBuilder.charAt(0))) {
strBuilder.deleteCharAt(0);
}
while (strBuilder.length() > 1 && strBuilder.substring(0, strBuilder.length() - 1).contains("" + strBuilder.charAt(strBuilder.length() - 1))) {
strBuilder.deleteCharAt(strBuilder.length() - 1);
}
return strBuilder.toString();
}
Run Code Online (Sandbox Code Playgroud)
但它并不适用于所有测试用例.它确实适用于此问题中给出的示例.但是当我提交代码时,它失败了2个测试用例.不,我不知道它失败的测试用例.
即使在尝试了各种样本输入之后,我也找不到它失败的测试用例.有人可以看看代码有什么问题吗?如果有人可以提供更好的算法(仅使用伪代码),我将非常感激.我知道这不是优化的解决方案.
str1 = "spqrstrupvqw"
str2 = "sprt"
str3 = "q"
Run Code Online (Sandbox Code Playgroud)
str1我们正在寻找包含所有str2字符(假设有序)并且不包含 .. 中的字符的最小子字符串str3。
i = 1 .. str1.length
cursor = 1 .. str2.length
Run Code Online (Sandbox Code Playgroud)
解决方案必须采用以下形式:
str2.first X X .. X X str2.last
Run Code Online (Sandbox Code Playgroud)
因此,为了检查该子字符串,我们使用光标悬停在 上str2,但我们也有避免字符的约束str3,所以我们有:
if str3.contain(str1[i])
cursor = 1
else
if str1[i] == str2[cursor]
cursor++
Run Code Online (Sandbox Code Playgroud)
目标检查是:
if cursor > str2.length
return solution
else
if i >= str1.length
return not-found
Run Code Online (Sandbox Code Playgroud)
为了优化,您可以跳到下一个预测,即:
look-ahead = { str2[cursor] or { X | X in str3 }}
Run Code Online (Sandbox Code Playgroud)
如果str2未订购:
i = 1 .. str1.length
lookup = { X | X in str2 }
Run Code Online (Sandbox Code Playgroud)
解决方案必须采用以下形式:
str2[x] X X .. X X str2[x]
Run Code Online (Sandbox Code Playgroud)
因此,为了检查该子字符串,我们使用检查列表str2,但我们也有避免字符的约束str3,所以我们有:
if str3.contain(str1[i])
lookup = { X | X in str2 }
else
if lookup.contain(str1[i])
lookup.remove(str1[i])
Run Code Online (Sandbox Code Playgroud)
目标检查是:
if lookup is empty
return solution
else
if i >= str1.length
return not-found
Run Code Online (Sandbox Code Playgroud)
为了优化,您可以跳到下一个预测,即:
look-ahead = {{ X | X in lookup } or { X | X in str3 }}
Run Code Online (Sandbox Code Playgroud)
代码
class Solution
{
private static ArrayList<Character> getCharList (String str)
{
return Arrays.asList(str.getCharArray());
}
private static void findFirst (String a, String b, String c)
{
int cursor = 0;
int start = -1;
int end = -1;
ArrayList<Character> stream = getCharList(a);
ArrayList<Character> lookup = getCharList(b);
ArrayList<Character> avoid = getCharList(c);
for(Character ch : stream)
{
if (avoid.contains(ch))
{
lookup = getCharList(b);
start = -1;
end = -1;
}
else
{
if (lookup.contains(ch))
{
lookup.remove(ch)
if (start == -1) start = cursor;
end = cursor;
}
}
if (lookup.isEmpty())
break;
cursor++;
}
if (lookup.isEmpty())
{
System.out.println(" found at ("+start+":"+end+") ");
}
else
{
System.out.println(" not found ");
}
}
}
Run Code Online (Sandbox Code Playgroud)