今天遇一面试题,大家讨论讨论?

wind1373290 2009-07-14 08:16:39
今天面试遇到一道题目,有个地方不知道是什么意思,大家来说说:
题目:
有一个数组A,数组是int类型的,如下结构
A[0..,i-1,i,...n]
要求:
找出递增长度最长的子序列在数组中的下标
例如:2 2 2 2 1 2 -1 2 -2 2
它的递增子序列就是1 2,-1 2,-2 2由于他们的递增子序列相同,所以返回4,当然你也可以返回6或8
假设数组A是一个几兆的数据。
分析
找出所有的递减对数,例如2 1,2 -1,2 -2,在这些对数中后一个数的下标放到一个数组B中,这里的下标是4,6,8
于是整个数组理论上分成了2222|12|-12|-22几段
用另一个数组C记录每段中出现相等的个数,第一段是4,第二段0,第三段0
于是遍历数组B和C,得出每段的长度为B[i]-B[i-1]-C[i],第一段有点特殊

以上只是我的思路,仅供参考
问题
假设数组A是一个几兆的数据,如果是几兆数据该怎么办?
有没有更好的算法?
算法怎么优化?
...全文
152 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
绿色夹克衫 2009-07-16
  • 打赏
  • 举报
回复
如果是求连续的递增序列,应该比较简单,按照7楼的方法,O(n)就能求解,
如果不是连续的,LZ搜索一下“最长递增子序列”,网上资料很多,讲解的也都比较详细,各种算法的实现都有。
showjim 2009-07-15
  • 打赏
  • 举报
回复
最多扫一遍,结束条件应该根据当前最长序列变化.
tanwan 2009-07-15
  • 打赏
  • 举报
回复
连续的直接一次扫描吧,不连续的DP
wind1373290 2009-07-15
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 xiaoyu821120 的回复:]
LZ的题意不是很明确,递增的子序列是连续还是不连续的,连续的话扫一遍就可以解决了.
[/Quote]
上面是连续的?什么是不连续的?
  • 打赏
  • 举报
回复
O(n)
xiaoyu821120 2009-07-15
  • 打赏
  • 举报
回复
LZ的题意不是很明确,递增的子序列是连续还是不连续的,连续的话扫一遍就可以解决了.
lstool 2009-07-15
  • 打赏
  • 举报
回复
MARK
ShowMan 2009-07-15
  • 打赏
  • 举报
回复
是的啊, 遍历一次难道记录不下来,干嘛把简单的想复杂呢?
fire_woods 2009-07-15
  • 打赏
  • 举报
回复
O(n),遍历一遍就能完成.
morilasi 2009-07-15
  • 打赏
  • 举报
回复

#include <iostream>
using namespace std;

int arr[100];

int
main(void)
{
int i=0;
int len;
int subscript;
int globalmax,suffixmax;
while(cin>>arr[i++]);
len=i;

globalmax=suffixmax=1;

for(i=1;i!=len;i++)
{
if(arr[i]>arr[i-1])
{
suffixmax++;
}
if(arr[i]<=arr[i-1])
{
if(globalmax<suffixmax)
{
globalmax=suffixmax;
subscript=i;
}
suffixmax=1;
}
}
cout<<globalmax<<endl;
cout<<subscript-globalmax<<endl;
}

globalmax是最长递增子序列的长度。
subscript-globalmax是第一个最长递增子序列开始处的下标
wind1373290 2009-07-15
  • 打赏
  • 举报
回复
谢谢大家
morilasi 2009-07-15
  • 打赏
  • 举报
回复
最长递增子序列问题?有O(N)的算法。我写写看
千与 2009-07-15
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 shirdrn 的回复:]
引用 19 楼 wind1373290 的回复:
引用 17 楼 shirdrn 的回复:
如果数据量非常小,一个字符串有可以承受的时间内扫描完成,直接串行扫描一遍即可;
如果数据量很大,可以考虑分治后,执行并行计算:这里生成分割点是难点,可以考虑使用二分法,然后前向或者后向扫描,找到分割点,多线程处理分治后的每个子串,效率会有很大的提高。


如何分治呢?



比如:-1 9 18 0 -4 9 23 8 0 1 6 10 12 9 0 -5 9 7,二分分割…
[/Quote]
纠正一下,右侧长度为5
千与 2009-07-15
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 wind1373290 的回复:]
引用 17 楼 shirdrn 的回复:
如果数据量非常小,一个字符串有可以承受的时间内扫描完成,直接串行扫描一遍即可;
如果数据量很大,可以考虑分治后,执行并行计算:这里生成分割点是难点,可以考虑使用二分法,然后前向或者后向扫描,找到分割点,多线程处理分治后的每个子串,效率会有很大的提高。


如何分治呢?
[/Quote]

比如:-1 9 18 0 -4 9 23 8 0 1 6 10 12 9 0 -5 9 7,二分分割如下:
-1 9 18 0 -4 9 23 8 0 | 1 6 10 12 9 0 -5 9 7
发现左半部分8>0,并且0>1,将分割点左移一个:
-1 9 18 0 -4 9 23 8 | 0 1 6 10 12 9 0 -5 9 7
现在两部分都是相同的任务,可以并行求解,分别求得两部分的解,求解后在合并这两部分的解:
左侧: -1 9 18 0 -4 9 23 8,返回数据:长度3,索引0和4;
右侧: 0 1 6 10 12 9 0 -5 9 7,返回数据:长度4,局部索引0;
合并过程:
1、左侧长度为3,右侧为4,左侧舍去
2、处理右侧:左侧最大索引 + 右侧局部索引 = 7 + 0 = 7

可以根据实际情况设置分割的数量。

一般,用多线程就能解决,没有必要搞分布。
wind1373290 2009-07-15
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 shirdrn 的回复:]
如果数据量非常小,一个字符串有可以承受的时间内扫描完成,直接串行扫描一遍即可;
如果数据量很大,可以考虑分治后,执行并行计算:这里生成分割点是难点,可以考虑使用二分法,然后前向或者后向扫描,找到分割点,多线程处理分治后的每个子串,效率会有很大的提高。
[/Quote]
如何分治呢?
showjim 2009-07-15
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 shirdrn 的回复:]
如果数据量非常小,一个字符串有可以承受的时间内扫描完成,直接串行扫描一遍即可;
如果数据量很大,可以考虑分治后,执行并行计算:这里生成分割点是难点,可以考虑使用二分法,然后前向或者后向扫描,找到分割点,多线程处理分治后的每个子串,效率会有很大的提高。
[/Quote]
多核多线程确实可行,代码稍微复杂一点.
千与 2009-07-15
  • 打赏
  • 举报
回复
如果数据量非常小,一个字符串有可以承受的时间内扫描完成,直接串行扫描一遍即可;
如果数据量很大,可以考虑分治后,执行并行计算:这里生成分割点是难点,可以考虑使用二分法,然后前向或者后向扫描,找到分割点,多线程处理分治后的每个子串,效率会有很大的提高。
derek02 2009-07-14
  • 打赏
  • 举报
回复
mark
allen303allen 2009-07-14
  • 打赏
  • 举报
回复
楼上的都想的太简单了吧,不过思路应该就是二叉查找树。但最优解不一定都是右孩子的情况,因为左孩子也大于它的 作为右孩子的父亲节点 的父亲节点。
shine_paul 2009-07-14
  • 打赏
  • 举报
回复
用二叉查找树,大于结点的值就成为其右孩子,小于等于结点的数就成为其左孩子。建立链接点的时候自身属性包含一个数值(记录自己本身右孩子的个数)
我自己瞎想的~~呵呵
等待大牛~~
加载更多回复(1)

33,008

社区成员

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

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