文字を繰り返さずに最長の部分文字列を見つける
1. 概要
このチュートリアルでは、Javaを使用して一意の文字の最も長い部分文字列を見つける方法を比較します。 たとえば、「CODINGISAWESOME」の一意の文字の最長部分文字列は「NGISAWE」です。
2. ブルートフォースアプローチ
素朴なアプローチから始めましょう。 まず、we can examine each substring whether it contains unique characters:
String getUniqueCharacterSubstringBruteForce(String input) {
String output = "";
for (int start = 0; start < input.length(); start++) {
Set visited = new HashSet<>();
int end = start;
for (; end < input.length(); end++) {
char currChar = input.charAt(end);
if (visited.contains(currChar)) {
break;
} else {
visited.add(currChar);
}
}
if (output.length() < end - start + 1) {
output = input.substring(start, end);
}
}
return output;
}
n*(n+1)/2の可能な部分文字列があるため、the time complexity of this approach is O(n^2).
3. 最適化されたアプローチ
それでは、最適化されたアプローチを見てみましょう。 文字列の左から右への走査を開始し、以下を追跡します。
-
startおよびendインデックスを使用した、繰り返されない文字を含む現在の部分文字列
-
最長の非反復部分文字列output
-
すでにvisitedの文字のルックアップテーブル
String getUniqueCharacterSubstring(String input) {
Map visited = new HashMap<>();
String output = "";
for (int start = 0, end = 0; end < input.length(); end++) {
char currChar = input.charAt(end);
if (visited.containsKey(currChar)) {
start = Math.max(visited.get(currChar)+1, start);
}
if (output.length() < end - start + 1) {
output = input.substring(start, end + 1);
}
visited.put(currChar, end);
}
return output;
}
新しいキャラクターごとに、すでに訪れたキャラクターで探します。 キャラクターが既にアクセスされており、非繰り返しキャラクターを含む現在のサブストリングの一部である場合、スタートインデックスを更新します。 それ以外の場合は、文字列をトラバースし続けます。
文字列を1回だけトラバースしているため、the time complexity will be linear, or O(n).
このアプローチは、sliding window patternとも呼ばれます。
4. テスト
最後に、実装を徹底的にテストして、機能することを確認しましょう。
@Test
void givenString_whenGetUniqueCharacterSubstringCalled_thenResultFoundAsExpected() {
assertEquals("", getUniqueCharacterSubstring(""));
assertEquals("A", getUniqueCharacterSubstring("A"));
assertEquals("ABCDEF", getUniqueCharacterSubstring("AABCDEF"));
assertEquals("ABCDEF", getUniqueCharacterSubstring("ABCDEFF"));
assertEquals("NGISAWE", getUniqueCharacterSubstring("CODINGISAWESOME"));
assertEquals("be coding", getUniqueCharacterSubstring("always be coding"));
}
ここでは、test boundary conditions as well as the more typical use casesを試してみます。
5. 結論
このチュートリアルでは、スライディングウィンドウ手法を使用して、繰り返されない文字を含む最長の部分文字列を見つける方法を学習しました。
そして、いつものように、ソースコードはover on GitHubで利用できます。