繁体   English   中英

*第一个*最长的增加子序列

[英]*First* Longest Increasing Subsequence

最长的子序列是众所周知的问题,我有一个耐心算法的解决方案。

问题是,我的解决方案给了我“最长的增长序列”,而不是出现的第一个最长的增长序列。

区别在于序列中的一些成员在第一个中的数字较大(但序列长度完全相同)。

获得第一个序列比预期的要困难得多,因为具有最佳序列并不容易转化为具有第一序列。

我想过做我的算法,然后找到长度为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

基本上,只要第一个最长的序列与最长的序列相同,我的代码就可以工作。 但是当你有一堆相同长度的最长序列时,它会抓住最好的序列而不是第一个序列。

代码不言自明。 (添加了评论,如果您需要额外的东西,请告诉我)。

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]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM