私は動的プログラミングの基礎を学んでいて、配列内の最長増加部分列を見つけるという問題に行き着きました。DP ソリューションを調べる前に、自分でコーディングすることにし、次のアルゴリズムを思いつきました。完全なコードは、こちら にあります。
アイデアは、リスト配列を作成して増加するすべてのサブシーケンスを格納し、各サブシーケンスの対応する最大値を格納して比較を高速化することです。
private void findLIS(int[] inputArr) {
List[] listOfSubs = new ArrayList[inputArr.length]; //Max different subsequences in an array would be N
//To store the max value of each of the subsequences found yet
List<Integer> maxValList = new ArrayList<Integer>();
listOfSubs[0] = new ArrayList<Integer>();
listOfSubs[0].add(inputArr[0]); //Add the first element of the array to the list
maxValList.add(inputArr[0]);
for (int i=1;i<inputArr.length;i++) {
boolean flag = false;
int iter=0;
//Compare inputArr[i] with the maxVal of each subsequence
for (int j=0; j<maxValList.size(); j++) {
if (inputArr[i]>maxValList.get(j)) {
maxValList.set(j, inputArr[i]); //Update the maxVal in the corresponding position in the list
listOfSubs[j].add(inputArr[i]);
flag = true;
}
iter = j;
}
//If inputArr[i] is not greater than any previous values add it to a new list
if (!flag) {
maxValList.add(inputArr[i]);
listOfSubs[iter+1] = new ArrayList<Integer>();
listOfSubs[iter+1].add(inputArr[i]);
}
}
//Finding the maximum length subsequence among all the subsequences
int max=0, iter=0, index=0;
for (List<Integer> lst : listOfSubs) {
if (lst!=null && lst.size() > max) {
max = lst.size();
index=iter;
}
iter++;
}
//Print the longest increasing subsequence found
System.out.println("The Longest Increasing Subsequence is of length " + listOfSubs[index].size() +
" and is as follows:");
for (int i=0;i<listOfSubs[index].size();i++) {
System.out.print(listOfSubs[index].get(i) + " ");
}
}
コードは O(n^2) 時間で実行され、小規模/中規模の入力に対して完全に機能します。ただし、一部のオンライン プラクティス ポータル ( HackerRankなど) に対してコードを実行しようとすると、TLE (Time Limit Exceeded Errors) と Wrong Answer の両方が表示されます。効率的なソリューションは DP O(nlogn) ソリューションであるため、TLE エラーは理解していますが、このアルゴリズムによって生成される間違った回答について混乱しています。このような場合の入力は大きすぎる (~10000) ため、解決策がどこでうまくいかないかを手動で確認することはできません。
完全なコードとデータ セットの 1 つへの出力は、ここにあります。正解は、HackerRank によって報告された 195 である必要があります。