简体   繁体   English

在C中找到列表中增长最长的子序列

[英]Find the longest increasing subsequence of a list in C

I'm having problems trying to find the elements that form the Longest Increasing Subsequence of a given list. 我在尝试找到构成给定列表的最长增加子序列的元素时遇到问题。

I have the algorithm to find the value of a given item of the list, and I understand the method it uses, I just don't know what to add and where to add it so that I have the numbers that compose the LIS 我有算法来查找列表中给定项的值,我理解它使用的方法,我只是不知道要添加什么以及在哪里添加它以便我有组成LIS的数字

Here is what I'm doing now: 这是我现在正在做的事情:

for (A[0] = N[0], i=lis=1; i<n; i++) {
    int *l = lower_bound(A, A+lis, N[i]);
    lis = max(lis, (l-A)+1);
    *l = N[i];
}

A is an array that stores the partial LIS, but at some point it changes because there may be a different solution. A是存储部分LIS的数组,但在某些时候它会发生变化,因为可能存在不同的解决方案。 N is the array of elements. N是元素数组。

How can I get from here to finding the longest increasing subsequence of N ? 我怎样才能从这里找到N最长的后续序列?

You can use two additional array to find the LIS. 您可以使用另外两个阵列来查找LIS。 For example, if your source is put in an array A 例如,如果您的源放在数组A中

1  8  4  12  6  6  1

and we have an array B to store the elements of A which are more likely to be elements of LIS. 我们有一个数组B来存储A的元素,这些元素更可能是LIS的元素。 More precisely, B will be maintained as an LIS at position i . 更确切地说, B将在位置i处作为LIS维护。 Plus an array idx to record the positions. 加上一个数组idx来记录位置。

We begin from A[0] , place A[0] at B[0]. 我们从A [0]开始,将A [0]置于B [0]。 Since A[0] is appended at position 0 in B , idx[0] = 0. 由于A [0]附加在B中的位置0,因此idx [0] = 0。

      [0]  1   2   3   4   5   6

 A  |  1   8   4  12   6   6   1
 B  | (1)
idx |  0

Then for position 1, since element in B is smaller than A[1], A[1] is appended to B. idx[1] records the position in B which is 1. 然后对于位置1,由于B中的元素小于A [1],A [1]附加到B.idx [1]记录B中的位置,即1。

       0  [1]  2   3   4   5   6

 A  |  1   8   4  12   6   6   1
 B  |  1  (8)
idx |  0   1

For position 2, A[2], or 4, is more likely to be an element of LIS compared to elements in B in order to maintain B as an LIS. 对于位置2,与B中的元素相比,A [2]或4更可能是LIS的元素,以便将B维持为LIS。 So find the element in B which is the smallest one no less than 4 and replace, which is 8. idx[2] is set to the position where 8 is replaced in B . 因此,找到B中最小的元素不小于4并替换,即8。将idx [2]设置为B中替换8的位置。 I think you can use your searching algorithm to find such an element. 我想你可以用你的搜索算法来找到这样一个元素。

       0   1  [2]  3   4   5   6

 A  |  1   8   4  12   6   6   1
 B  |  1  (4)
idx |  0   1   1

So continue this manner, we gradually set up idx . 所以继续这种方式,我们逐步建立idx

position 3
       0   1   2  [3]  4   5   6

 A  |  1   8   4  12   6   6   1
 B  |  1   4 (12)
idx |  0   1   1   2

position 4
       0   1   2   3  [4]  5   6

 A  |  1   8   4  12   6   6   1
 B  |  1   4  (6)
idx |  0   1   1   2   2

position 5
       0   1   2   3   4  [5]  6

 A  |  1   8   4  12   6   6   1
 B  |  1   4  (6)
idx |  0   1   1   2   2   2

position 6
       0   1   2   3   4   5  [6]

 A  |  1   8   4  12   6   6   1
 B  | (1)  4   6
idx |  0   1   1   2   2   2   0

We have idx recorded positions, now we scan idx backwards and will find out the LIS. 我们有idx记录位置,现在我们向后扫描idx并找出LIS。

       0   1   2   3   4   5   6

 A  |  1   8   4  12   6   6   1
idx |  0   1   1   2   2  (2)  0    | 6

       0   1   2   3   4   5   6

 A  |  1   8   4  12   6   6   1
idx |  0   1  (1)  2   2   2   0    | 4  6

       0   1   2   3   4   5   6

 A  |  1   8   4  12   6   6   1
idx | (0)  1   1   2   2   2   0    | 1  4  6

Hence, the output LIS is {1, 4, 6} 因此,输出LIS是{1,4,6}

The code and A = {1, 8, 4, 12, 6, 6, 1} as source 代码和A = {1,8,4,12,6,6,1}作为源

#include <stdio.h>
#include <stdlib.h>

#define INT_INF 10000

int search_replace(int *lis, int left, int right, int key) {
        int mid;

        for (mid = (left+right)/2; left <= right; mid = (left+right)/2) {
                if (lis[mid] > key) {
                        right = mid - 1;
                } else if (lis[mid] == key) {
                        return mid;
                } else if (mid+1 <= right && lis[mid+1] >= key) {
                        lis[mid+1] = key;
                        return mid+1;
                } else {
                        left = mid + 1;
                }
        }
        if (mid == left) {
                lis[mid] = key;
                return mid;
        }
        lis[mid+1] = key;
        return mid+1;
}

int main(void) {
        int i, tmp, size = 7, lis_length = -1; 
        int *answer;
        int A[7] = {1,8,4,12,6,6,1},
            LIS[7],
            index[7] = {0};

        LIS[0] = A[0];
        for (i = 1; i < size; ++i) {
                LIS[i] = INT_INF;
        }

        for (i = 1; i < size; ++i) {
                index[i] = search_replace(LIS, 0, i, A[i]);
                if (lis_length < index[i]) {
                        lis_length = index[i];
                }
        }

        answer = (int*) malloc((lis_length+1) * sizeof(int));
        for (i = size-1, tmp = lis_length; i >= 0; --i) {
                if (index[i] == tmp) {
                        answer[tmp] = A[i];
                        --tmp;
                }
        }

        printf("LIS: ");
        for (i = 0; i < lis_length+1; ++i) {
                printf("%d ", answer[i]);
        }
        printf("\n");

        return 0;
}

And the output of the code 和代码的输出

LIS: 1 4 6

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

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