算法引论中的一道题

zhengjiaxiang135 2009-07-17 10:16:59
加精
最近在看Udi Manber的《算法引论》这本书,不过有道题没思路,贴在这请大家帮忙解决哈!!

考虑由下列数所组成的表。你的工作是删去尽可能少的数使得留下来的数以升序排列。例如除了前两个数以外删去所有的数就会得到一个升序序列,删去除第一个、第三个、第六个、第八个数以外的其他数也将得到一个升序序列(可以比前面少删除一些数)。
9 44 32 12 7 42 34 92 35 37 41 8 20 27 83 64 61 28 39 93 29 17 13 14 55
21 66 72 23 73 99 1 2 88 77 3 65 83 84 62 5 11 74 68 76 78 67 75 69 70 22
71 24 25 26


大家帮忙看看,给点思路哈!!
...全文
4909 145 打赏 收藏 转发到动态 举报
写回复
用AI写文章
145 条回复
切换为时间正序
请发表友善的回复…
发表回复
sunlitpalm 2012-07-18
  • 打赏
  • 举报
回复
楼上几位大侠的代码在我的机子上运行都在毫秒级,大约2-5毫秒的样子。
2012年的新机子还没09年的猛,泪奔了~~
tangyaohong 2011-11-02
  • 打赏
  • 举报
回复
二叉排序树的思想好像有些漏洞,因为最长又子树还要加上上一层中是双亲,且将子树的根作为又子孙的点,那样就不会落掉了
jdtxse 2010-05-16
  • 打赏
  • 举报
回复
学习了
xixi300 2009-11-26
  • 打赏
  • 举报
回复
好帖子
LPR_Pro 2009-09-05
  • 打赏
  • 举报
回复
ding
piqio379 2009-09-04
  • 打赏
  • 举报
回复
[Quote=引用 105 楼 xinxin12375 的回复:]
很明显是求最长不下降子序列,动规中的经典问题,网上代码一大堆,请LZ给分!
[/Quote]
up
lbjfeng 2009-08-25
  • 打赏
  • 举报
回复
挺晕
zsxcn 2009-08-25
  • 打赏
  • 举报
回复
mark
hardbeyond 2009-08-24
  • 打赏
  • 举报
回复
up
qiuzhenguang 2009-08-22
  • 打赏
  • 举报
回复
学习学习.
spirit_sheng 2009-08-18
  • 打赏
  • 举报
回复
动态规划 可解决此问题
「已注销」 2009-08-15
  • 打赏
  • 举报
回复
最长公共序列么!
「已注销」 2009-08-15
  • 打赏
  • 举报
回复
#include <iostream>
#include <algorithm>

int const SIZE = 55;

void lcs_len( int row[], int column[], int len[][SIZE] )
{
len[0][0] = row[0] == column[0] ? 1 : 0;

for( int i = 1; i < SIZE; ++ i )
{
len[i][0] = row[i] == column[0] ? 1 : len[i-1][0];
}

for( int j = 1; j < SIZE; ++ j )
{
len[0][j] = row[0] == column[j] ? 1 : len[0][j-1];
}


for( int i = 1; i < SIZE; ++ i )
{
for( int j = 1; j < SIZE; ++ j )
{
if( row[i] == column[j] )
{
len[i][j] = len[i-1][j-1] + 1;
}
else
{
len[i][j] = len[i-1][j] > len[i][j-1] ? len[i-1][j] : len[i][j-1];
}
}
}
}


int main()
{
int RawData[SIZE] =
{
9, 44, 32, 12, 7, 42, 34, 92, 35, 37, 41, 8, 20, 27, 83, 64, 61, 28, 39, 93, 29, 17, 13, 14, 55, 21, 66,
72, 23, 73, 99, 1, 2, 88, 77, 3, 65, 83, 84, 62, 5, 11, 74, 68, 76, 78, 67, 75, 69, 70, 22, 71, 24, 25, 26
};

int SortedData[SIZE];

std::copy( RawData, RawData + SIZE, SortedData );
std::sort( SortedData, SortedData + SIZE );


int LengthTable[SIZE][SIZE];

lcs_len( RawData, SortedData, LengthTable );

int SubSequence[SIZE];

for( int k = LengthTable[SIZE-1][SIZE-1] - 1, i = SIZE-1, j = SIZE-1; k >= 0; )
{
if( LengthTable[i][j] == LengthTable[i-1][j] )
{
-- i;
}
else if( LengthTable[i][j] == LengthTable[i][j-1] )
{
-- j;
}
else
{
SubSequence[k] = RawData[i];
-- k;
-- i;
-- j;
}
}

for( int i = 0; i < LengthTable[SIZE-1][SIZE-1]; ++ i )
{
std::cout << SubSequence[i] << " ";
}

std::cout << std::endl << std::endl;
system( "pause" );

return 0;
}
  • 打赏
  • 举报
回复
不认为这种方法行

[Quote=引用 2 楼 zhaolinger2 的回复:]
做排序二叉树,得到树的层数,然后用数组的数的个数减去这个层数就能得到要删去的最小数目。
[/Quote]
fireseed 2009-08-04
  • 打赏
  • 举报
回复
[Quote=引用 123 楼 linren 的回复:]
引用 122 楼 fireseed 的回复:

121楼的CTimer类不错,直接拿来用了^_^
C++从经验上来说是应该不会比C更快的……
C/C++ code#include<stdio.h>#include<stdlib.h>#include<string.h>#include<windows.h>#defineSIZE 55chara[SIZE]={9,44,32,12,7,42,34,92,35,37,41,8,20,27,83,64,61,28,39,93,29,17,13,14,55,21,…
[/Quote]


终于有人认识到那个CTimer是很好用的了,五年了啊~~哭!!

呵呵,可能是我的机子比你的快吧~~这样比也没什么意义了,不过都是很棒的算法!
linren 2009-08-04
  • 打赏
  • 举报
回复
(上接126楼)

【测试结果】
use time: 0.020673 ms
max len: 13
7, 8, 20, 27, 28, 29, 55, 66, 72, 73, 77, 83, 84,
Press any key to continue
linren 2009-08-04
  • 打赏
  • 举报
回复
【程序】
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

#define SIZE 55
char a[SIZE]={
9,44,32,12,7,42,34,92,35,37,41,8,20,
27,83,64,61,28,39,93,29,17,13,14,55,
21,66,72,23,73,99,1,2,88,77,3,65,83,
84,62,5,11,74,68,76,78,67,75,69,70,
22,71,24,25,26};

class CTimer
{
public:
__forceinline CTimer( void ) {
QueryPerformanceFrequency( (PLARGE_INTEGER)&m_nFreq );
QueryPerformanceCounter( (PLARGE_INTEGER)&m_nStart );
}
__forceinline void Reset( void ) {
QueryPerformanceCounter( (PLARGE_INTEGER)&m_nStart );
}
__forceinline double Stop( void ) {
QueryPerformanceCounter( (PLARGE_INTEGER)&m_nCur );
return double( m_nCur - m_nStart ) / double( m_nFreq );
}
__forceinline bool SelfTest( void ){
return ( 0 != QueryPerformanceFrequency( (PLARGE_INTEGER)&m_nFreq ) );
}
private:
__int64 m_nCur;
__int64 m_nFreq;
__int64 m_nStart;
};

int main(){
int *lis;
int *r;
int i,j,k,t,x,y;
int len=SIZE;
CTimer tmr;

lis=(int*)malloc(sizeof(int)*len);

for(i=0;i<len;i++){
lis[i]=1;
for(j=0;j<i;j++) if(a[i]>a[j]&&lis[j]+1>lis[i]) lis[i]=lis[j]+1;
}
k=0;
for(i=0;i<len;i++){
if(lis[i]>k){
k=lis[i];j=i;
}
}
r=(int*)malloc(sizeof(int)*k);
t=1;x=j;r[k-1]=a[j];y=k-2;
for(i=j-1;i>=0;i--){
if(lis[i]==k-t&&a[i]<a[x]){
r[y--]=a[i];t++;x=i;
}
}

printf("use time: %f ms\n",tmr.Stop() * 1000.0);
printf("max len: %d\n",k);
for(i=0;i<k;i++) printf("%d, ",r[i]);printf("\n");
free(r);free(lis);

return 0;
}

【说明】
123楼的程序其实不需要map……
zb_fly 2009-08-04
  • 打赏
  • 举报
回复
应该用动态规划的方法做。
linren 2009-08-04
  • 打赏
  • 举报
回复
(上接123楼)
程序中的这部分:
for(i=0;i<len;i++){
lis[i]=1;
for(j=0;j<i;j++){
if(a[i]>a[j]&&lis[j]+1>lis[i]){
lis[i]=lis[j]+1;
}
}
}

时间复杂度很大……
所以把判断k的值和找一个最优解的工作放在外面是比较好的
两个加起来也只是2n的复杂度……
linren 2009-08-04
  • 打赏
  • 举报
回复
[Quote=引用 122 楼 fireseed 的回复:]
【运行结果】
Spend 0.0173206ms
13 Numbers: 7 8 20 27 28 39 55 66 72 73 77 83 84
请按任意键继续. . . [/Quote]

121楼的CTimer类不错,直接拿来用了^_^
C++从经验上来说是应该不会比C更快的……
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

#define SIZE 55
char a[SIZE]={
9,44,32,12,7,42,34,92,35,37,41,8,20,
27,83,64,61,28,39,93,29,17,13,14,55,
21,66,72,23,73,99,1,2,88,77,3,65,83,
84,62,5,11,74,68,76,78,67,75,69,70,
22,71,24,25,26};

class CTimer
{
public:
__forceinline CTimer( void ) {
QueryPerformanceFrequency( (PLARGE_INTEGER)&m_nFreq );
QueryPerformanceCounter( (PLARGE_INTEGER)&m_nStart );
}
__forceinline void Reset( void ) {
QueryPerformanceCounter( (PLARGE_INTEGER)&m_nStart );
}
__forceinline double Stop( void ) {
QueryPerformanceCounter( (PLARGE_INTEGER)&m_nCur );
return double( m_nCur - m_nStart ) / double( m_nFreq );
}
__forceinline bool SelfTest( void ){
return ( 0 != QueryPerformanceFrequency( (PLARGE_INTEGER)&m_nFreq ) );
}
private:
__int64 m_nCur;
__int64 m_nFreq;
__int64 m_nStart;
};

int main(){
int *lis;
char *map;
int *r;
int i,j,k,t,x;
int len;
CTimer tmr;

len=SIZE;
lis=(int*)malloc(sizeof(int)*len);
map=(char*)malloc(sizeof(char)*len);
memset(lis,0,sizeof(int)*len);
memset(map,0,sizeof(char)*len);

for(i=0;i<len;i++){
lis[i]=1;
for(j=0;j<i;j++){
if(a[i]>a[j]&&lis[j]+1>lis[i]){
lis[i]=lis[j]+1;
}
}
}
k=0;
for(i=0;i<len;i++){
if(lis[i]>k){
k=lis[i];j=i;
}
}
r=(int*)malloc(sizeof(int)*k);
t=1;x=j;map[j]=1;
for(i=j-1;i>=0;i--){
if(lis[i]==k-t&&a[i]<a[x]){
map[i]=1;t++;x=i;
}
}
j=0;
for(i=0;i<len;i++) if(map[i]==1) r[j++]=a[i];

printf("use time: %f ms\n",tmr.Stop() * 1000.0);
printf("max len: %d\n",k);
for(i=0;i<k;i++) printf("%d, ",r[i]);printf("\n");
free(r);free(map);free(lis);

return 0;
}

【测试结果】
use time: 0.022908 ms
max len: 13
7, 8, 20, 27, 28, 29, 55, 66, 72, 73, 77, 83, 84,
Press any key to continue

【121楼测试结果】
Spend 0.320711ms
13 Numbers: 7 8 20 27 28 39 55 66 72 73 77 83 84
Press any key to continue
加载更多回复(123)

33,007

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧