改进最长递增åºåˆ—算法

时间:2014-01-20 09:58:15

标签: performance algorithm lis

从SPOJ, here is the problem statement. 我开始使用普通的DP解决方案,但这需è¦n ^ 2次,并且必然会超过时间é™åˆ¶ã€‚

我é‡åˆ°äº†é—®é¢˜çš„nlogn解决方案和 here is the solution for that 。

如果我们åªéœ€è¦æ‰¾åˆ°æœ€é•¿å¢žé•¿å­åºåˆ—的长度,或者如果你必须找到其中一个åºåˆ—,那么解决方案效果很好。但是如果你必须找到属于一个åºåˆ—或å¦ä¸€ä¸ªåºåˆ—的所有元素,我会åšä¸€äº›å­˜å‚¨å’Œå…¶ä»–的东西,我已ç»è¾¾åˆ° this solution.

现在这已ç»å¾—到了SPOJ引擎的预期,但是当我查看其他已接å—的解决方案时,我的程åºéœ€è¦èŠ±è´¹48å€çš„时间,而其他人则需è¦ä½Žè‡³.04。

我想知é“,如果å¯èƒ½ï¼Œæœ‰äººå¯ä»¥å‘Šè¯‰æˆ‘如何改进我的解决方案?

我在我的解决方案中所åšçš„是,在输出数组中,我ä¸ä»…存储当å‰æ•°å­—,而且存储整个列表,而在父节点中,我维护所有数字的父节点,因为æ¯ä¸ªæ•°å­—都æˆä¸ºä¸€éƒ¨åˆ†è¾“出数组。

最åŽä¸€ä¸ªæ•°ç»„åªä¸è¿‡æ˜¯å­˜å‚¨å¸ƒå°”值的最终整数数组,该数组是å¦å±žäºŽLIS。

由于

PS它说到ideone.com的链接必须附带代ç ï¼Œå› æ­¤åœ¨è¿™é‡Œç²˜è´´ä»£ç ã€‚

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

int count;

struct node{
    int value;
    struct node* next;
};

int constructFinal(int *final,struct node **parent,struct node **output,int value){
    if(final[value - 1] == 1)
        return 0;
    final[value - 1] = 1;
    count++;
    struct node* temp;
    temp = parent[value-1];
    while(temp!= NULL){
        constructFinal(final,parent,output,temp->value);
        temp = temp->next;
    }
}

int findIndex(int currentElement,struct node** output,int lower,int upper){
    if(lower >= upper)
        return lower;
    int mid =lower + ( upper - lower )/2;
    if(output[mid]->value < currentElement)
        return findIndex(currentElement,output,mid+1,upper);
    else if(output[mid]->value > currentElement)
        return findIndex(currentElement,output,lower,mid);
}   

int main(){
    int numOfInp,sizeOfInp,i,currentElement,sizeOfOut,indexBinary,indexAdded;
    struct node *temp,*tempIter;
    numOfInp=1;
    while(numOfInp--){
        scanf("%d",&sizeOfInp);
        struct node **output; // if I initialise normal initialisation, I may not get the data as 0 by default, hence callocing
        struct node **parent;
        int *input;
        input = (int *)calloc(sizeOfInp,sizeof(int));
        for(i=0 ; i< sizeOfInp ; i++)
            scanf("%d",&input[i]);

        parent = (struct node**)calloc(sizeOfInp, sizeof(struct node*));

        output = (struct node**)calloc(sizeOfInp, sizeof(struct node*));
        sizeOfOut = 0;
        for(i=0;i<sizeOfInp;i++){
            indexBinary = -1;
            currentElement = input[i];
            if(sizeOfOut == 0){
                output[sizeOfOut] = (struct node*)calloc(1,sizeof(struct node));
                output[sizeOfOut]->value = currentElement;
                indexAdded = sizeOfOut;
                sizeOfOut++;
            }
            else{
                if(currentElement > output[sizeOfOut-1]->value){
                    output[sizeOfOut] = (struct node*)calloc(1,sizeof(struct node));
                    output[sizeOfOut]->value = currentElement;
                    indexAdded = sizeOfOut;
                    sizeOfOut++;
                }
                else{
                    indexBinary = findIndex(currentElement,output,0,sizeOfOut-1);
                    temp = (struct node*)calloc(1,sizeof(struct node));
                    temp->next = output[indexBinary];
                    output[indexBinary] = temp;
                    output[indexBinary]->value = currentElement;
                    indexAdded = indexBinary;
                }
            }

            //parent[currentElement-1] = (struct node*)calloc(sizeof(struct node));
            if(indexAdded > 0){
                tempIter = output[indexAdded-1];
                while(tempIter != 0 && tempIter->value < currentElement){               //for all the elements in the previous bucket
                    temp = (struct node*)calloc(1,sizeof(struct node)); //add the values to parent
                    temp->next = parent[currentElement-1];
                    parent[currentElement-1] = temp;
                    parent[currentElement-1]->value = tempIter ->value;
                    tempIter = tempIter->next;
                }
            }
            else{
                parent[currentElement-1] = NULL;    // these are the elements in the first bucket of output
            }
        }

        int *final;
        final = (int*)calloc(sizeOfInp,sizeof(int));
        temp = output[sizeOfOut -1];
        count=0;
        while(temp != NULL){
            constructFinal(final,parent,output,temp->value);
            temp=temp->next;
        }
        printf("%d\n",count);
        for(i=0;i<sizeOfInp;i++)
            if(final[i]==1)
                printf("%d ",i+1);
        printf("\n");
        free(output);
        free(parent);

    }
    return 0;
}

1 个答案:

答案 0 :(得分:1)

一个建议(å¯èƒ½åªä¼šå¸®åŠ©å°‘é‡ï¼‰å¯ä»¥é¿å…多次调用calloc。

您å¯ä»¥é€šè¿‡é¢„先分é…最大大å°çš„å•ä¸ªæ•°ç»„并跟踪其中已分é…的元素数æ¥å®žçŽ°æ­¤ç›®çš„。

将递归函数调用更改为å•ä¸ªè¿­ä»£å‡½æ•°ä¹Ÿå¯èƒ½æœ‰æ‰€å¸®åŠ©ï¼Œå› ä¸ºè¿™å¯ä»¥é¿å…调用函数的开销。