JavaScriptで最も長い非共通部分列(LUS)を見つける方法
文字列の配列を受け取り、その中から最長非共通部分列(Longest Uncommon Subsequence)を見つけるJavaScript関数を作成する必要があります。
ここで「最長非共通部分列」とは、配列内のいずれか1つの文字列の部分列でありながら、他のどの文字列の部分列としても現れない、最長の部分列のことを指します。
この関数は、そのような最長非共通部分列の長さを返す必要があります。
問題の例
例えば、入力配列が次のようになっているとします。
const arr = ["aba", "cdc", "eae"];
この場合、出力は 3 になります。「aba」「cdc」「eae」は互いに他方の部分列ではないため、最も長い非共通部分列の長さは、これらの文字列のうち最も長いものの長さである3となるからです。
解き方のポイント
この問題を解く際の基本的な考え方は以下の通りです。
- 各文字列が配列内に出現する回数を記録します。
- すべての文字列が互いに異なり、どの文字列も他の文字列の部分列になっていない場合、答えは単純に最も長い文字列の長さになります。
- 一方、ある文字列が別の文字列の部分列として含まれる場合は、その文字列は「非共通」ではないため候補から除外し、残った文字列の中で最も長いものの長さを求めます。
コード例
この問題に対する実装コードは次のようになります。
const arr = ["aba", "cdc", "eae"];
const findUncommonLength = (array = []) => {
const seen = {};
const arr = [];
let max = -1;
let index = -1;
for(let i = 0; i < array.length; i++){
seen[array[i]] = (seen[array[i]] || 0) + 1;
if(seen[array[i]] > 1){
if(max < array[i].length){
max = array[i].length;
index = i;
}
}
};
if(index === -1) {
array.forEach(el => {
if(el.length > max) max = el.length;
});
return max;
};
for(let i = 0; i < array.length; i++){
if(seen[array[i]] === 1) arr.push(array[i]);
};
max = -1;
for(let i = arr.length - 1; i >= 0; i--){
let l = arr[i];
let d = 0;
for(let j = 0; j < array[index].length; j++){
if(array[index][j] === l[d]){
d++;
}
}
if(d === l.length){
let temp = arr[i];
arr[i] = arr[arr.length - 1];
arr[arr.length - 1] = temp;
arr.pop();
}
};
arr.forEach(el => {
if(el.length > max) max = el.length;
});
return max;
};
console.log(findUncommonLength(arr));コードの解説
まず、オブジェクト seen を使って各文字列の出現回数を数えています。重複する文字列が存在しない場合(index === -1 の場合)は、配列内で最も長い文字列の長さをそのまま返します。
重複が存在する場合は、一度だけ出現している文字列だけを新しい配列 arr に集めます。その後、各文字列が基準となる文字列の部分列になっているかを2ポインタ的な走査で判定し、部分列になっている要素を配列から取り除きます。最後に残った文字列の中で最大の長さを返すことで、最長非共通部分列の長さが得られます。
出力結果
上記のコードを実行すると、コンソールには次のように表示されます。
3
-
JavaScriptで文字列内の最長連続文字とその出現回数を検索する方法
問題文字列を受け取り、その中で最も長く連続して現れる文字とその連続回数を返すJavaScript関数を作成する必要があります。戻り値は必ず2つの要素を持つ配列とします。1つ目の要素:文字列内で最も多く連続して登場する文字2つ目の要素:その文字が連続して登場した回数解決のアプローチこの問題は、文字列を先頭から1文字ずつ走査し、隣接する文字同士を比較することで解決できます。同じ文字が続いている間はカウントを増やし、異なる文字が出現した時点でカウントをリセットします。その際、これまでに記録した最大連続回数を上回っていれば、その文字と回数を結果として保存していきます。コード例以下が実際のコードです。c
-
JavaScriptで配列のネストされた集合の最長の長さを見つけて返す方法
問題数値の配列 arr を第一引数(かつ唯一の引数)として受け取るJavaScript関数を作成する必要があります。長さ N の配列 arr には、0 から N-1 までのすべての整数がちょうど1回ずつ含まれています。この関数では、次のルールに従って構成される集合 S の最長の長さを見つけ、その結果を返す必要があります。ここで、S[i] = {A[i], A[A[i]], A[A[A[i]]], ...} と定義されます。具体的には、S の最初の要素としてインデックス i の要素 A[i] を選択することから始め、次の要素は A[A[i]]、その次は A[A[A[i]]]… というように順に辿