请教一道面试算法题

核动力蜗牛Killua 2013-01-09 04:56:34
题目描述如下:有一个数组array,给定任意一个位置n,求从n往前算第一个比array[n]小的数。例如[1,5,2,4,3,6,4,5,3,1],n=4,结果2;n=6,结果3。要求算法复杂度O(n)。
...全文
1409 37 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
37 条回复
切换为时间正序
请发表友善的回复…
发表回复
youyou1912 2013-04-15
  • 打赏
  • 举报
回复
前面给出了思路. 我具体说一下吧: 构造一个map[], map[i]的值表示第i个元素左边第一个比他小的值的index. -1表示没有. 准备一个栈, 栈元素为index [1,5,2,4,3,6,4,5,3,1], 从左往右遍历, 遇到1, 把index塞到栈里面stack={0}, map[0]=-1, 游标往右, 遇到5, 查看栈顶(index=0), value[0]是否比5小, 是的, 则map[2]=0. 同时把5的index塞到栈里面stack={0,1}, 游标往右, 遇到2, 和栈顶比较, 小于5, 则pop出5, 继续查看栈, 知道遇到小的. 遇到了map[3]=0, 然后同样把当前index塞进栈stack={0,2}. 如此反复.
  • 打赏
  • 举报
回复
我的目的就是求出整个list,遍历O(n),查询O(1)。不然就没什么难度了
花花花湖 2013-03-14
  • 打赏
  • 举报
回复
我觉得应该是预处理O(n),要不然也太简单了。
sjhcsdn 2013-03-10
  • 打赏
  • 举报
回复
var x= (from key in array
      where key<array[n]
         select key).First();
bfdeh 2013-03-08
  • 打赏
  • 举报
回复
LZ赶紧出来说明情况~
绿色夹克衫 2013-03-08
  • 打赏
  • 举报
回复
就是个单调队列吧,总代价O(n)的。平摊是O(1)的。
skillart 2013-03-08
  • 打赏
  • 举报
回复
我也想说难道我理解错了
Hony杨 2013-02-27
  • 打赏
  • 举报
回复
脑子不好使了,只想到了o(nlgn)的算法,用线段树来做,每个元素的添加和查询分别是o(lgn)。
Hony杨 2013-02-27
  • 打赏
  • 举报
回复
昏~ 我错了!谢谢你的例子。
引用 24 楼 hugett 的回复:
引用 23 楼 HuiyuYang_fish 的回复:不可能有o(n)的算法。 这个题目就是一个 最长上升子序列 算法,如果我们假设有o(n)的算法,那么LIS也有o(n)的算法。 证明:首先,我们可以通过o(n)的算法计算出每个元素往前第一个比较它小的元素位置,那么我们按第n元素开始得到一个子序列,令此子序列下标为a0,a1,..ai,..aj,..a(m-……
flydream0 2013-02-27
  • 打赏
  • 举报
回复
引用 14 楼 hugett 的回复:
如果是每次查询O(n),那就太简单了。。 如果是O(n)打表,O(1)查询,那我实在没想到,求高手解答。。
O(n)打表是指往指数据初始化么?如果是,那么O(1)应该可以实现吧,说下我的思路: 提示:其实大家注意到没,这里是往左第一个比当前小的数,为什么是往左还不是往右呢? 在往数据里写入数据时,其实每写一个数,其实就已经可以知道这个数左边第一个比当前数最小的位置了,应该可以建立一张映射表,把当前数的位置n与其左边第一个比它小的数的位置(或值)记录下来,这个位置叫map_pos,那么查询时就变成通过n的到对应的map_pos了,算法是O(1),这张映射表叫做位图。 接下来关键问题就转变为在写入数组一个数时,如何在其写入位置的左边找到第一个比它小的数,且算法为O(n),这个就可以用扫描的方式了吧?找到这个数后将当前n和其对应的map_pos写入位图,OK,搞定! 不知这样是否符合题意?
usc_su 2013-02-27
  • 打赏
  • 举报
回复
楼主应该记错了 o(n) brute force就是o(n) 没意义的
Hony杨 2013-02-27
  • 打赏
  • 举报
回复
单调栈解决此题,LIS变形的数据结构:http://www.cppblog.com/izualzhy/archive/2012/08/25/188226.aspx
引用 17 楼 zxz100322 的回复:
意思应该是O(n)的预处理+O(1)的查询吧 利用单调栈,从前往后扫描一遍就是O(n)了
dracularking 2013-02-27
  • 打赏
  • 举报
回复
n=6時,結果應該是4吧
hugett 2013-02-27
  • 打赏
  • 举报
回复
引用 23 楼 HuiyuYang_fish 的回复:
不可能有o(n)的算法。 这个题目就是一个 最长上升子序列 算法,如果我们假设有o(n)的算法,那么LIS也有o(n)的算法。 证明:首先,我们可以通过o(n)的算法计算出每个元素往前第一个比较它小的元素位置,那么我们按第n元素开始得到一个子序列,令此子序列下标为a0,a1,..ai,..aj,..a(m-1),长度为m,很容易知道,array[ai] < array[aj] <= a……
你这样找出的可能不是LIS的。。例如{3,4,1,5}。。
Hony杨 2013-02-26
  • 打赏
  • 举报
回复
不可能有o(n)的算法。 这个题目就是一个 最长上升子序列 算法,如果我们假设有o(n)的算法,那么LIS也有o(n)的算法。 证明:首先,我们可以通过o(n)的算法计算出每个元素往前第一个比较它小的元素位置,那么我们按第n元素开始得到一个子序列,令此子序列下标为a0,a1,..ai,..aj,..a(m-1),长度为m,很容易知道,array[ai] < array[aj] <= array[ak](i<k<j),因此此子序列无法在被扩展,为最长子序列且为升序。 由上面的证明得到LIS(最长上升子序列)的算法复杂度为o(n)。
wk984841826ing 2013-02-26
  • 打赏
  • 举报
回复
引用 21 楼 hugett 的回复:
C/C++ code?12345678910111213141516171819#include <stdio.h> int ans[10];int a[10]={1,5,2,4,3,6,4,5,3,1};int q[10];int nq; int main(){ nq=0; for(int i=0;i<10;++i){ while(nq &am……
貌似结果不完全正确,,,到底n=1时代表数组的1号位元素还是2号位元素???求解
hugett 2013-02-18
  • 打赏
  • 举报
回复

#include <stdio.h>

int ans[10];
int a[10]={1,5,2,4,3,6,4,5,3,1};
int q[10];
int nq;

int main(){
    nq=0;
    for(int i=0;i<10;++i){
        while(nq && q[nq]>=a[i]) --nq;
        ans[i] = nq ? q[nq] : -1;
        q[++nq] = a[i];
    }
    int n;
    while(scanf("%d",&n)==1) printf("%d\n",ans[n]);

    return 0;
}
fire_woods 2013-02-18
  • 打赏
  • 举报
回复
创建一个记录表A, 其中的第n个元素的值 代表比array[n]小且在n前面的第一个数的位置. 比如用楼主的例子, A[4]=3, A[6]=5. 要搜索只要O(1), 即array[A[n]]即可, 假设找不到返回-1, 则另array[0] = -1, 找不到的A[x]=-1即可. 现在说构造A. 假设构造第n个数, 令x=n-1 1. 如果array[n]>array[x], 则A[n]=x; 2. 否则x=A[x], 到1 时间复杂度比较复杂, 应该是O(n), 至少平均是O(n)
dracularking 2013-02-08
  • 打赏
  • 举报
回复
楼主消失了
angel6709 2013-02-06
  • 打赏
  • 举报
回复
本身就是o(n)
加载更多回复(17)

33,028

社区成员

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

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