ヘルシング:
最長増加部分列はよく知られた問題であり、私は忍耐アルゴリズムとソリューションを持っています。
問題は、私の解決策が私に「ベスト最長増加するシーケンス」の代わりに与え、あるまず表示されていることを最長増加するシーケンスを。
相違点は、配列のメンバーのいくつかは、最初に大きな数である(ただし、系列長が正確に同じである)ことです。
最初のシーケンスを取得する最良の配列を持つことは簡単に最初の配列を有するに変換されないため、非常に難しい予想以上であることが判明回しています。
私は確かにどのように長さNの最初のシーケンスを見つけ、その後、私のアルゴリズムを行うのと思ったが、いませんでした。
だから、どうやって見つけるだろうまず乱数整数のシーケンスから最長増加部分列を?
私のコードスニペット:
public static void main (String[] args) throws java.lang.Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int inputInt;
int[] intArr;
try {
String input = br.readLine().trim();
inputInt = Integer.parseInt(input);
String inputArr = br.readLine().trim();
intArr = Arrays.stream(inputArr.split(" ")).mapToInt(Integer::parseInt).toArray();
} catch (NumberFormatException e) {
System.out.println("Could not parse integers.");
return;
}
if(inputInt != intArr.length) {
System.out.println("Invalid number of arguments.");
return;
}
ArrayList<ArrayList<Integer>> sequences = new ArrayList<ArrayList<Integer>>();
int sequenceCount = 1;
sequences.add(new ArrayList<Integer>());
sequences.get(0).add(0);
for(int i = 1; i < intArr.length; i++) {
for(int j = 0; j < sequenceCount; j++) {
if(intArr[i] <= intArr[sequences.get(j).get(sequences.get(j).size() - 1)]) {
sequences.get(j).remove(sequences.get(j).size() - 1);
sequences.get(j).add(i);
break;
} else if (j + 1 == sequenceCount) {
sequences.add(new ArrayList<Integer>(sequences.get(j)));
sequences.get(j + 1).add(i);
sequenceCount++;
break; //increasing sequenceCount causes infinite loop
} else if(intArr[i] < intArr[sequences.get(j + 1).get(sequences.get(j + 1).size() - 1)]) {
sequences.set(j+ 1, new ArrayList<Integer>(sequences.get(j)));
sequences.get(j+ 1).add(i);
break;
}
}
}
int bestSequenceLength = sequenceCount;
ArrayList<Integer> bestIndexes = new ArrayList<Integer>(sequences.get(bestSequenceLength - 1));
//build bestSequence, then after it I'm supposed to find the first one instead
int[] bestSequence = Arrays.stream(bestIndexes.toArray()).mapToInt(x -> intArr[(int) x]).toArray();
StringBuilder output = new StringBuilder("");
for(Integer x : bestSequence) {
output.append(x + " ");
}
System.out.println(output.toString().trim());
}
私は再び元の配列にアクセスすることの準備のために代わりにインデックスを格納しています。それは、その逆よりも値をインデックスから行く方が簡単ですので。
例:
3 6 1 2 8
私のコードを返します:1 2 8
最初のシーケンスは次のとおりです。3 6 8
もう一つの例:
1 5 2 3
私のコードは正常に返されます:1 2 3
基本的に、私のコードは限り最初の最長シーケンスが最高の最長のシーケンスと同じであるとして動作します。あなたは、同じ長さの最長シーケンスの束を持っている場合しかし、それは最高のものではない最初のものをつかみます。
vivek_23:
コードは自明です。(持っているあなたが何かを余分に必要な場合は私に知らせて、コメントを追加しました)。
public class Solution {
public static void main(String[] args) {
int[] arr = {3,6,1,2,8};
System.out.println(solve(arr).toString());
}
private static List<Integer> solve(int[] arr){
int[][] data = new int[arr.length][2];
int max_length = 0;
// first location for previous element index (for backtracing to print list) and second for longest series length for the element
for(int i=0;i<arr.length;++i){
data[i][0] = -1; //none should point to anything at first
data[i][1] = 1;
for(int j=i-1;j>=0;--j){
if(arr[i] > arr[j]){
if(data[i][1] <= data[j][1] + 1){ // <= instead of < because we are aiming for the first longest sequence
data[i][1] = data[j][1] + 1;
data[i][0] = j;
}
}
}
max_length = Math.max(max_length,data[i][1]);
}
List<Integer> ans = new ArrayList<>();
for(int i=0;i<arr.length;++i){
if(data[i][1] == max_length){
int curr = i;
while(curr != -1){
ans.add(arr[curr]);
curr = data[curr][0];
}
break;
}
}
Collections.reverse(ans);// since there were added in reverse order in the above while loop
return ans;
}
}
出力:
[3, 6, 8]