数据结构 笔记:最长不下降序列

本文详细介绍了如何求解数据结构中的最长不下降序列问题,通过将数列转化为图模型,利用有向边表示元素间的关系,并提出以每个顶点作为起始点寻找局部最多顶点路径的方法,最终确定全局最长不下降序列。文中还提供了搜索局部最顶点路径的算法思路和关键数据结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

不下降序列问题

设由n个数组成的数列,记为:a[1]、a[2]、……、a[n],若存在i1 < i2 <... im 满足:

a[i1] <= a[i2] <= .... <= a[im] , 则称为长度为m的不下降序列。

则:

》 3,18,23,24是一个长度为4的不下降序列

》 3,7,10,12,16,24是一个长度为6的不下降序列

问题:

如何求最长不下降序列?如何求所有不下降序列?

 问题建模

-使用数列中的元素和元素间的关系建立图模型

·图中顶点的附加数据值为对应的数据元素值

·图中的边按照如下方式建立

~当数列中的某个元素与后序元素存在不下降关系时

》从该元素对应的顶点到后序元素对应的顶点村子一条有向边

》边的权值固定为1

建模示例:1,3,4,2,5

解决思路

-以每一个顶点作为起始顶点寻找局部最多顶点路径

·V0 →p0,V1 →p1,V2 →p2,...

-寻找全局最多顶点的路径

·Pm = max{P0,P1,……,Pn-1}

局部最多顶点路径的求解思路

-获取当前顶点v的邻接顶点{aj0,aj1,...}

-以各个邻接顶点为起点求解最多顶点路径{Paj0,Paj1,...}

-Pv = max{Paj0,Paj1,....} + 1

原材料

-Array<int> count;

·count[i]表示以i起始的最多顶点路径上的顶点数

-Array<int> path;

·path[i]表示以i起始的最多顶点路径上经过的第一个顶点

-Array<bool> mark;

·如果i起始的最多顶点路径已找到,则:mark[i]为true

寻找局部顶点数最多的路径

-定义功能:search_max_path(v,count,path,mark)

·以v作为起始顶点寻找最多顶点路径

·count记录经过的最多顶点数

·path记录最多顶点路径上经过的第一个顶点

·mark记录最多顶点路径是否已经找到

最长不下降序列求解流程

#include "LinkList.h"
#include "Graph.h"
#include <QDebug>


int search_max_path(Graph<int,int>& g,int v,Array<int>& count,Array<LinkList<int>*>& path,Array<bool>& mark)
{
    int ret = 0;
    SharedPointer<Array <int> > aj = g.getAdjacent(v);

    for(int i = 0;i < aj->length();i++)
    {
        int num = 0;

        if( !mark[(*aj)[i]])
        {
            num = search_max_path(g,(*aj)[i],count,path,mark);
        }
        else
        {
            num = count[(*aj)[i]];
        }

        if(ret < num)
        {
            ret = num;
        }
    }

    for(int i = 0;i < aj->length();i++)
    {
        if(ret == count[(*aj)[i]])
        {
            path[v]->insert((*aj)[i]);
        }
    }

    ret++;

    count[v] = ret;
    mark[v] = true;

    return ret;
}

SharedPointer<Graph<int,int> > create_graph(int* a,int len)
{
    ListGraph<int,int>* ret = new ListGraph<int,int>(len);

    for(int i = 0;i< len;i++)
    {
        ret->setVertex(i,a[i]);
    }

    for(int i = 0;i<len;i++)
    {
        for(int j = i+1;j<len;j++)
        {
            if(a[i] < a[j])
            {
                ret->setEdge(i,j,1);
            }
        }
    }
    return ret;
}

void init_array(Array<int>& count,Array<LinkList<int>*>& path,Array<bool>& mark)
{
    for(int i =0;i<count.length();i++)
    {
        count[i] = 0;
    }

    for(int i = 0;i<path.length();i++)
    {
        path[i] = new LinkList<int>();
    }

    for(int i =0;i<mark.length();i++)
    {
        mark[i] = false;
    }
}

void print_path(Graph<int,int>& g,int v,Array<LinkList<int>* >& path,LinkList<int>& cp)
{
    cp.insert(v);

    if(path[v]->length() > 0)
    {
        for(path[v]->move(0);!path[v]->end();path[v]->next())
        {
            print_path(g,path[v]->current(),path,cp);
        }
    }
    else
    {
        cout << "Element: " ;

        for(cp.move(0);!cp.end();cp.next())
        {
            cout << g.getVertex(cp.current())<< " ";
        }
        cout << endl;
    }
    cp.remove(cp.length()-1);
}

void print_max_path(Graph<int,int>& g,Array<int>& count,Array<LinkList<int>*>& path)
{
    int max = 0;
    LinkList<int> cp;
    for(int i = 0;i<count.length();i++)
    {
        if(max< count[i])
        {
            max = count[i];
        }
    }

    cout << "Len: " << max << endl;
    for(int i = 0;i<count.length();i++)
    {
        if(max == count[i])
        {
            print_path(g,i,path,cp);
        }
    }
}

void search_max_path(Graph<int,int>& g,Array<int>& count,Array<LinkList<int>*>& path,Array<bool>& mark)
{
    for(int i = 0;i<g.vCount();i++)
    {
        if(!mark[i])
        {
            search_max_path(g,i,count,path,mark);
        }
    }
}

void solution(int* a,int len)
{
    DynamicArray<int> count(len);
    DynamicArray<LinkList<int>*> path(len);
    DynamicArray<bool> mark(len);
    SharedPointer<Graph<int,int>> g;

    g = create_graph(a,len);
    init_array(count,path,mark);
    search_max_path(*g,count,path,mark);
    print_max_path(*g,count,path);
}

int main()
{
    int a[] = {2,1,3,5,4};

    solution(a,sizeof(a)/sizeof(*a));

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值