牛骨文教育服务平台(让学习变的简单)
博文笔记

2014-百度 阿里 华为笔试题

创建时间:2013-10-12 投稿人: 浏览次数:4370
    1. 8月15日,百度2道面试题:
      1、来自《编程之美》的概率题:一个桶里面有白球、黑球各100个,现在按下述规则取球:的
          i 、每次从通里面拿出来两个球;
          ii、如果取出的是两个同色的求,就再放入一个黑球;
          ii、如果取出的是两个异色的求,就再放入一个白球。
      问:最后桶里面只剩下一个黑球的概率是多少?
      2、算法题:给你一个自然数N,求[6,N]之内的所有素数中,两两之和为偶数的那些偶数。
    2. 9月5日,华为2014校园招聘的机试题目
      通过键盘输入一串小写字母(a~z)组成的字符串。请编写一个字符串压缩程序,将字符串中连续出席的重复字母进行压缩,并输出压缩后的字符串。
      压缩规则:
          1、仅压缩连续重复出现的字符。比如字符串"abcbc"由于无连续重复字符,压缩后的字符串还是"abcbc"。
          2、压缩字段的格式为"字符重复的次数+字符"。例如:字符串"xxxyyyyyyz"压缩后就成为"3x6yz"。
      要求实现函数: 
           void stringZip(const char *pInputStr, long lInputLen, char *pOutputStr);
          输入pInputStr:  输入字符串lInputLen:  输入字符串长度
          输出 pOutputStr: 输出字符串,空间已经开辟好,与输入字符串等长;
      注意:只需要完成该函数功能算法,中间不需要有任何IO的输入输出
      示例 
          输入:“cccddecc”   输出:“3c2de2c”
          输入:“adef”     输出:“adef”
          输入:“pppppppp” 输出:“8p”
    3. 9月6日,网新恒天2014校园招聘笔试编程题
      已知memcpy的函数为: void* memcpy(void *dest , const void* src , size_t count)其中dest是目的指针,src是源指针。不调用c++/c的memcpy库函数,请编写memcpy。
      点评:老题,参考答案如下
      1. //copyright@July 2013/9/24  
      2. void* memcpy(void *dst, const void *src, size_t count)      
      3. {      
      4.     //安全检查  
      5.     assert( (dst != NULL) && (src != NULL) );      
      6.   
      7.     unsigned char *pdst = (unsigned char *)dst;      
      8.     const unsigned char *psrc = (const unsigned char *)src;      
      9.   
      10.     //防止内存重复  
      11.     assert(!(psrc<=pdst && pdst<psrc+count));      
      12.     assert(!(pdst<=psrc && psrc<pdst+count));      
      13.   
      14.     while(count--)      
      15.     {      
      16.         *pdst = *psrc;      
      17.         pdst++;      
      18.         psrc++;      
      19.     }      
      20.     return dst;      
      21. }    
    4. 9月9日,迅雷2014校招笔试编程题:
      已知集合A和B的元素分别用不含头结点的单链表存储,函数difference()用于求解集合A与B的差集,并将结果保存在集合A的单链表中。例如,若集合A={5,10,20,15,25,30},集合B={5,15,35,25},完成计算后A={10,20,30}。
      链表结点的结构类型定义如下:
      1. struct node    
      2. {    
      3.     int elem;    
      4.     node* next;    
      5. };    
      请完成函数void difference(node** LA , node* LB)
      点评:参考答案或更多题目请参见:http://blog.csdn.net/hackbuteer1/article/details/11482103。
    5. 9月10日,美团网2014校招研发笔试哈尔滨站
      1、链表翻转。给出一个链表和一个数k,比如链表1→2→3→4→5→6,k=2,则翻转后2→1→4→3→6→5,若k=3,翻转后3→2→1→6→5→4,若k=4,翻转后4→3→2→1→5→6,用程序实现
      点评:类似编程艺术第1章左旋转字符串,见:http://blog.csdn.net/v_JULY_v/article/details/6322882。
      2、一个m*n的矩阵,从左到右从上到下都是递增的,给一个数elem,求是否在矩阵中,给出思路和代码
      点评:杨氏矩阵查找,见编程艺术第23章:http://blog.csdn.net/v_july_v/article/details/7085669。
    6. 9月14日,阿里巴巴2014校招笔试哈尔滨站
      1、宿舍内5个同学一起玩对战游戏。每场比赛有一些人作为红方,另一些人作为蓝方。请问至少需要多少场比赛,才能使任意两个人之间有一场红方对蓝方和蓝方对红方的比赛?答案为4场,参考如下图,作者doc_sgl:

      点评:其余题目请参见:http://blog.csdn.net/doc_sgl/article/details/11695671。
      2、一个有10亿条记录的文本文件,已按照关键字排好序存储。请设计算法,可以快速的从文件中查找指字关键字的记录。
    7. 9月14日,阿里巴巴-系统工程师-北京站
    8. 9月16日,创新工场2014校招笔试题

      点评:上面第3题还是杨氏矩阵查找,见编程艺术第23章:http://blog.csdn.net/v_july_v/article/details/7085669。既然这么多公司都喜欢考杨氏矩阵查找,那么再给出杨氏矩阵查找一题的扩展:给定 n×n 的实数矩阵,每行和每列都是递增的,求这 n^2 个数的中位数,分析详见:http://zhiqiang.org/blog/science/computer-science/median-algorithm-of-ordered-matrix.html。
    9. 9月21日,百度2014校招-济南站

    10. 9月21日,腾讯2014软件开发校招-简答题-广州

      点评:这里有一关于上面2题的题解:http://blog.csdn.net/thebestdavid/article/details/12056293,可以参考。
    11. 9月22日,人人校招笔试题

      点评:上述第1题寻找满足条件的两个数,见编程艺术第5章:http://blog.csdn.net/v_JULY_v/article/details/6419466;上述第2题见编程艺术第21章:http://blog.csdn.net/v_july_v/article/details/6890054。
    12. 9月22日,阿里巴巴北邮站



      点评:这里有一朋友关于上述3题的题解:http://blog.csdn.net/thebestdavid/article/details/11975809,大家可以参考。
    13. 9月23日,网易电商部-社招面试
      HashMap与HashTable区别
      点评:HashMap基于Hashtable实现,不同之处在于HashMap是非同步的,并且允许null,即null value和null key,Hashtable则不允许null,详见:http://oznyang.iteye.com/blog/30690。此外,记住一点:hashmap/hashset等凡是带有hash字眼的均基于hashtable实现,没带hash字眼的如set/map均是基于红黑树实现,前者无序,后者有序,详见此文第一部分:http://blog.csdn.net/v_july_v/article/details/7382693。
    14. 9月24日,去哪儿网2014校招西安站笔试题
      给定一个200MB的文本文件,里面存的是IP地址到真实地址信息的映射信息,例如:211.200.101.100北京
      然后给你6亿个IP地址,请设计算法快速的打印出所对应的真实地址信息。
    15. 9月25日,阿里巴巴二面
      指针/数组区别,决策树训练原理,SVM原理,网络协议,堆排序,字符串转换成整数,设计一款拼音输入法等等..
      点评:字符串转换成整数看似简单,实则很多坑,要写好并不容易,具体分析和实现见编程艺术第30章:http://blog.csdn.net/v_july_v/article/details/9024123;决策树见:http://blog.csdn.net/v_july_v/article/details/7577684;SVM原理见:http://blog.csdn.net/v_july_v/article/details/7624837。
      总结:此次面试的这位同学面的还是堆排/快排/atoi等典型问题,实际上:①面试看基础算法编程能力,和准备是否充分;②不论结果如何,跟4年前高考一样,高考和面试都只是人生路上的其中一站。你的真正核心竞争力不是进哪所名校哪所名企,而是存在你骨子里的上进心或热爱钻研技术的态度。
    16. 9月28日,微软2014校招笔试题最后一道

      点评:上题形式上类似编程艺术第35章完美洗牌算法http://blog.csdn.net/v_july_v/article/details/10212493#t8,但因给定的是链表,所以相对来说,简单了不少;微软2014校招其它题目见:http://blog.csdn.net/xiaoerlyl/article/details/12126807。
    17. 9月28日,百度2014校招-武汉站-系统分析师

    18. 10月2日,暴风影音2014校招笔试
      1、合并两个已经排序的单链表为一个排序的单链表,相同内容只保留一个
      如:单链表a:1->2->3->4
      单链表b:3->4->5
      输出:1->2->3->4->5
      2、编写程序,在原字符串中把尾部m个字符移动到字符串的头部,要求:长度为n字符串操作时间复杂度为O(n),时间复杂度为O(1)。
      如:原字符串为”Ilovebaofeng”,m=7,输出结果:”baofengIlove”。
      点评:还是类似编程艺术第1章左旋字符串:http://blog.csdn.net/v_JULY_v/article/details/6322882。
      3、暴风影音的片源服务器上保存着两个文件a和b,各存放50亿条URL,每条URL占用64字节,内存限制是4G,让你找出a,b文件共同的URL。要求:算法设计。
      点评:上述第3题等海量数据处理面试题,请参见此文第第一部分第6题:http://blog.csdn.net/v_july_v/article/details/7382693。
    19. 关于linux内核的几个面试问题:
      1、Linux中主要有哪几种内核锁?
      2、Linux中的用户模式和内核模式是什么含意?
      3、用户进程间通信主要哪几种方式?
      4、有哪几种内存分配函数?
    20.  微软一面:输入两个数,相加求和,二进制输出。


    1. 9月11日, 京东:
    2. 谈谈你对面向对象编程的认识
    3. 8月20日,金山面试,题目如下:
          数据库1中存放着a类数据,数据库2中存放着以天为单位划分的表30张(比如table_20110909,table_20110910,table_20110911),总共是一个月的数据。表1中的a类数据中有一个字段userid来唯一判别用户身份,表2中的30张表(每张表结构相同)也有一个字段userid来唯一识别用户身份。如何判定a类数据库的多少用户在数据库2中出现过?
      来源:http://topic.csdn.net/u/20120820/23/C6B16CCF-EE15-47C0-9B15-77497291F2B9.html。
    4. 百度实习笔试题(2012.5.6)
       1、一个单词单词字母交换,可得另一个单词,如army->mary,成为兄弟单词。提供一个单词,在字典中找到它的兄弟。描述数据结构和查询过程。评点:同去年9月份的一道题,见此文第3题:http://blog.csdn.net/v_july_v/article/details/6803368。
      2、线程和进程区别和联系。什么是“线程安全”
      3、C和C++怎样分配和释放内存,区别是什么
      4、算法题1
      一个url指向的页面里面有另一个url,最终有一个url指向之前出现过的url或空,这两种情形都定义为null。这样构成一个单链表。给两条这样单链表,判断里面是否存在同样的url。url以亿级计,资源不足以hash。
      5、算法题2
      数组al[0,mid-1] 和 al[mid,num-1],都分别有序。将其merge成有序数组al[0,num-1],要求空间复杂度O(1)
      6、系统设计题
      百度搜索框的suggestion,比如输入“北京”,搜索框下面会以北京为前缀,展示“北京爱情故事”、“北京公交”、“北京医院”等等搜索词,输入“结构之”,会提示“结构之法”,“结构之法 算法之道”等搜索词。
      请问,如何设计此系统,使得空间和时间复杂度尽量低。

      评点:①直接上Trie树「Trie树的介绍见:从Trie树(字典树)谈到后缀树」 +  TOP K「hashmap+堆,hashmap+堆 统计出如10个近似的热词,也就是说,只存与关键词近似的比如10个热词,详细方法可参看此文第2个题的讲解:http://blog.csdn.net/v_july_v/article/details/7382693」? 
      ②or Double-array trie tree?同时,StackOverflow上也有两个讨论帖子:http://stackoverflow.com/questions/2901831/algorithm-for-autocomplete,http://stackoverflow.com/questions/1783652/what-is-the-best-autocomplete-suggest-algorithm-datastructure-c-c。
      ③此外,这里有一篇关于“拼写错误检查”问题的介绍,或许对你有所启示:http://blog.afterthedeadline.com/2010/01/29/how-i-trie-to-make-spelling-suggestions/。。
    5. 人搜笔试1. 快排每次以第一个作为主元,问时间复杂度是多少?(O(N*logN))
        2. T(N) = N + T(N/2)+T(2N), 问T(N)的时间复杂度是多少? 点评:O(N*logN) or O(N)?
        3. 从(0,1)中平均随机出几次才能使得和超过1?(e)
        4.编程题:
       一棵树的节点定义格式如下:
       struct Node{
          Node* parent;
          Node* firstChild; // 孩子节点
          Node* sibling; // 兄弟节点 
      }
      要求非递归遍历该树。
      思路:采用队列存储,来遍历节点。
        5. 算法题:
      有N个节点,每两个节点相邻,每个节点只与2个节点相邻,因此,N个顶点有N-1条边。每一条边上都有权值wi,定义节点i到节点i+1的边为wi。
      求:不相邻的权值和最大的边的集合。
    6. 人搜面试,所投职位:搜索研发工程师:面试题回忆 
           1、删除字符串开始及末尾的空白符,并且把数组中间的多个空格(如果有)符转化为1个。
           2、求数组(元素可为正数、负数、0)的最大子序列和。 
           3、链表相邻元素翻转,如a->b->c->d->e->f-g,翻转后变为:b->a->d->c->f->e->g 
           4、链表克隆。链表的结构为: 
           typedef struct list { 
               int data; //数据字段 
           list *middle; //指向链表中某任意位置元素(可指向自己)的指针 
           list *next;//指向链表下一元素 
           } list; 
           5、100万条数据的数据库查询速度优化问题,解决关键点是:根据主表元素特点,把主表拆分并新建副表,并且利用存储过程保证主副表的数据一致性。(不用写代码) 
           6、求正整数n所有可能的和式的组合(如;4=1+1+1+1、1+1+2、1+3、2+1+1、2+2)。点评:这里有一参考答案:http://blog.csdn.net/wumuzi520/article/details/8046350。
           7、求旋转数组的最小元素(把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1) 
           8、找出两个单链表里交叉的第一个元素 
           9、字符串移动(字符串为*号和26个字母的任意组合,把*号都移动到最左侧,把字母移到最右侧并保持相对顺序不变),要求时间和空间复杂度最小 
           10、时间复杂度为O(1),怎么找出一个栈里的最大元素   
           11、线程、进程区别 
           12、static在C和C++里各代表什么含义 
           13、const在C/C++里什么意思 
           14、常用linux命令 
           15、解释Select/Poll模型 
    7. 网易有道二面:
      判断一个数字序列是BST后序遍历的结果,现场写代码。
      来源:http://blog.csdn.net/hopeztm/article/category/1201028;
    8. 8月30日,网易有道面试题
      var tt = "aa";
      function test()
      {
        alert(tt);
        var tt = "dd";
        alert(tt);
      }
      test();  
    9. 8月31日,百度面试题:不使用随机数的洗牌算法,详情:http://topic.csdn.net/u/20120831/10/C837A419-DFD4-4326-897C-669909BD2086.html;
    10. 9月6日,阿里笔试题:平面上有很多点,点与点之间有可能有连线,求这个图里环的数目。
    11. 9月7日,一道华为上机题:
      题目描述: 选秀节目打分,分为专家评委和大众评委,score[] 数组里面存储每个评委打的分数,judge_type[] 里存储与 score[] 数组对应的评委类别,judge_type == 1,表示专家评委,judge_type == 2,表示大众评委,n表示评委总数。打分规则如下:专家评委和大众评委的分数先分别取一个平均分(平均分取整),然后,总分 = 专家评委平均分 * 0.6 + 大众评委 * 0.4,总分取整。如果没有大众评委,则 总分 = 专家评委平均分,总分取整。函数最终返回选手得分。
      函数接口 int cal_score(int score[], int judge_type[], int n)  
       上机题目需要将函数验证,但是题目中默认专家评委的个数不能为零,但是如何将这种专家数目为0的情形排除出去。
      来源:http://topic.csdn.net/u/20120907/15/c30eead8-9e49-41c2-bd11-c277030ad17a.html;
    12. 9月8日,腾讯面试题:
      假设两个字符串中所含有的字符和个数都相同我们就叫这两个字符串匹配,
       比如:abcda和adabc,由于出现的字符个数都是相同,只是顺序不同,
       所以这两个字符串是匹配的。要求高效!
      又是跟上述第3题中简单题一的兄弟节点类似的一道题,我想,你们能想到的,这篇blog里:http://blog.csdn.net/v_JULY_v/article/details/6347454都已经有了。
    13. 阿里云,搜索引擎中5亿个url怎么高效存储;
    1. 一道C++笔试题,求矩形交集的面积:
      在一个平面坐标系上,有两个矩形,它们的边分别平行于X和Y轴。
      其中,矩形A已知, ax1(左边), ax2(右边), ay1(top的纵坐标), ay2(bottom纵坐标). 矩形B,类似,就是 bx1, bx2, by1, by2。这些值都是整数就OK了。
      要求是,如果矩形没有交集,返回-1, 有交集,返回交集的面积。
      int area(rect const& a, rect const& b)
      {
        ...
      }
      点评:
      healer_kx:
      补齐代码,最好是简洁的,别用库。你可以写你的辅助函数,宏定义,代码风格也很重要。
      ri_aje:
    1. struct rect  
    2. {  
    3.  // axis alignment assumed  
    4.  // bottom left is (x[0],y[0]), top right is (x[1],y[1])  
    5.  double x [2];  
    6.  double y [2];  
    7. };  
    8.   
    9. template <typename T> T const& min (T const& x, T const& y) { return x<y ? x : y; }  
    10. template <typename T> T const& max (T const& x, T const& y) { return x>y ? x : y; }  
    11.   
    12. // return type changed to handle non-integer rects  
    13. double area (rect const& a, rect const& b)  
    14. {  
    15.  // perfectly adjacent rects are considered having an intersection of 0 area  
    16.  double const dx = min(a.x[1],b.x[1]) - max(a.x[0],b.x[0]);  
    17.  double const dy = min(a.y[1],b.y[1]) - max(a.y[0],b.y[0]);  
    18.  return dx>=0&&dy>=0 ? dx*dy : -1;  
    19. }  
    1. 下面是一个简短的证明。
      对于平行于坐标轴的矩形 r,假设其左下角点坐标为 (rx0,ry0),右上角点坐标为 (rx1,ry1),那么由 r 定义的无限有界点集为:{(x,y)|x in [rx0,rx1] && y in [ry0,ry1]}。
      根据交集的定义,则任意二维点 (x,y) 在矩形 a,b 的交集内等价于
      {(x,y)|(x,y) in a 并且 (x,y) in b} <==>
      {(x,y)|x in [ax0,ax1] && x in [bx0,bx1] 并且 y in [ay0,ay1] && y in [by0,by1]} <==>
      {(x,y)|x in [max(ax0,bx0),min(ax1,bx1)] 并且 y in [max(ay0,by0),min(ay1,by1)]}
      因此,交集矩形的边长分别为 min(ax1,bx1)-max(ax0,bx0) 和 min(ay1,by1)-max(ay0,by0)。注意当交集为空时(a,b 不相交),则经此法计算出来的交集边长为负值,此事实可用于验证 a,b 的相交性。
      鉴于笛卡尔积各个维度上的不相关性,此方法可扩展到任意有限维线性空间,比如,三维空间中平行于坐标轴的长方体的交集体积可以用类似的方法计算。
      来源:http://topic.csdn.net/u/20120913/18/bc669d60-b70a-4008-be65-7c342789b925.html。
    2. 2012年创新工场校园招聘最后一道笔试题:工场很忙
          创新工场每年会组织同学与项目的双选会,假设现在有M个项目,编号从1到M,另有N名同学,编号从1到N,每名同学能选择最多三个、最少一个感兴趣的项目。选定之后,HR会安排项目负责人和相应感兴趣的同学一对一面谈,每次面谈持续半小时。由于大家平时都很忙,所以咱们要尽量节约时间,请你按照以下的条件设计算法,帮助HR安排面试。
      1)同学很忙。项目负责人一次只能与一名同学面谈,而同学会在自己第一个面试开始时达到工场,最后一个面试结束后离开工场,如果参加一个项目组的面试后不能立即参加下一个项目组的面试,就必须在工场等待。所以请尽可能让同学的面试集中在某一时间段,减少同学在工场等待的时间。
      2)项目负责人很忙。众所周知,创业团队的负责人会有很多事情要做,所以他们希望能够将自己参与的面试集中在某一段时间内,请在保证1)的情况下,使得项目负责人等待的时间最少。
      3)HR很忙。从第一轮面试开始以后,所有HR都必须等到最后一轮面试结束,所以需要在保证1)和2)的同时,也能尽快解放掉所有的HR,即让第一轮面试到最后一轮面试之间持续的时间最短。
      输入(以文件方式输入,文件名为iw,例如iw.in):
          第1行...第n行:同学的编号 项目的编号
          样例(数据间用空格隔开,两个0表示输入结束):           
      1 1
      1 2
      1 3
      2 1
      3 1
      3 2
      0 0             
          表示M=3,N=3,编号为1的同学选择了项目1,2和3,编号为2的同学选择了项目1,编号为3的同学选了项目1和2
      输出(以文件方式输出,文件名为iw,例如iw.out):
          第1行:编号为1的项目依次面试新同学的编号序列
          第2行:编号为2的项目依次面试新同学的编号序列
          ...
          第n行:编号为n的项目依次面试新同学的编号序列
          样例(数据间用空格隔开,0表示没有面试):
      1 3 2
      3 1 0
      0 0 1
          表示编号为1的项目在第一轮面试编号为1的同学,第二轮面试编号为3的同学,第三轮面试编号为2的同学
          编号为2的项目在第一轮面试编号为3的同学,第二轮面试编号为1的同学,第二轮不用面试
          编号为3的项目在第一轮和第二轮都不用面试,第三轮面试编号为1的同学
      链接:http://t.qq.com/p/t/108332110988802;
    3. 4**9 的笔试题,比较简单:
      1.求链表的倒数第二个节点
      2.有一个整数数组,求数组中第二大的数

    4. 阿里巴巴二道题 第一道:
      对于给定的整数集合S,求出最大的d,使得a+b+c=d。a,b,c,d互不相同,且都属于S。集合的元素个数小于等于2000个,元素的取值范围在[-2^28,2^28 - 1],假定可用内存空间为100MB,硬盘使用空间无限大,试分析时间和空间复杂度,找出最快的解决方法。
      点评:
      @绿色夹克衫:两两相加转为多项式乘法,比如(1 2 4 6) + (2 3 4 5) => (x + x^2 + x^4 + x^6)*(x^2 + x^3 + x^4 + x^5) 。更多思路请见这:http://www.51nod.com/answer/index.html#!answerId=569。 阿里巴巴第二道(研发类)
      笔试题1,原题大致描述有一大批数据,百万级别的。数据项内容是:用户ID、科目ABC各自的成绩。其中用户ID为0~1000万之间,且是连续的,可以唯一标识一条记录。科目ABC成绩均在0~100之间。有两块磁盘,空间大小均为512M,内存空间64M。
      1) 为实现快速查询某用户ID对应的各科成绩,问磁盘文件及内存该如何组织;
      2) 改变题目条件,ID为0~10亿之间,且不连续。问磁盘文件及内存该如何组织;
      3) 在问题2的基础上,增加一个需求。在查询各科成绩的同时,获取该用户的排名,问磁盘文件及内存该如何组织。
      笔试题2:代码实现计算字符串的相似度。
      点评:和计算两字符串的最长公共子序列相似。
      设Ai为字符串A(a1a2a3 … am)的前i个字符(即为a1,a2,a3 … ai)
      设Bj为字符串B(b1b2b3 … bn)的前j个字符(即为b1,b2,b3 … bj)
      设 L(i , j)为使两个字符串和Ai和Bj相等的最小操作次数。
      当ai等于bj时 显然L(i, j)=L(i-1, j-1)
      当ai不等于bj时
        若将它们修改为相等,则对两个字符串至少还要操作L(i-1, j-1)次
        若删除ai或在Bj后添加ai,则对两个字符串至少还要操作L(i-1, j)次
        若删除bj或在Ai后添加bj,则对两个字符串至少还要操作L(i, j-1)次
        此时L(i, j)=min( L(i-1, j-1), L(i-1, j), L(i, j-1) )  + 1
      显然,L(i, 0)=i,L(0, j)=j, 再利用上述的递推公式,可以直接计算出L(i, j)值。具体代码请见这:http://blog.csdn.net/flyinghearts/article/details/5605996。 
    1. 9月14日,小米笔试,给一个浮点数序列,取最大乘积子序列的值,例如 -2.5,4,0,3,0.5,8,-1,则取出的最大乘积子序列为3,0.5,8。
      点评:
      解法一、
           或许,读者初看此题,自然会想到最大乘积子序列问题类似于最大子数组和问题:http://blog.csdn.net/v_JULY_v/article/details/6444021,然实则具体处理起来诸多不同,为什么呢,因为乘积子序列中有正有负也还可能有0。
          既如此,我们可以把问题简化成这样:数组中找一个子序列,使得它的乘积最大;同时找一个子序列,使得它的乘积最小(负数的情况)。因为虽然我们只要一个最大积,但由于负数的存在,我们同时找这两个乘积做起来反而方便。也就是说,不但记录最大乘积,也要记录最小乘积。So,
      我们让maxCurrent表示当前最大乘积的candidate,
      minCurrent反之,表示当前最小乘积的candidate。
      (用candidate这个词是因为只是可能成为新一轮的最大/最小乘积),
      而maxProduct则记录到目前为止所有最大乘积candidates的最大值。
          由于空集的乘积定义为1,在搜索数组前,maxCurrent,minCurrent,maxProduct都赋为1。
      假设在任何时刻你已经有了maxCurrent和minCurrent这两个最大/最小乘积的candidates,新读入数组的元素x(i)后,新的最大乘积candidate只可能是maxCurrent或者minCurrent与x(i)的乘积中的较大者,如果x(i)<0导致maxCurrent<minCurrent,需要交换这两个candidates的值。
          当任何时候maxCurrent<1,由于1(空集)是比maxCurrent更好的candidate,所以更新maxCurrent为1,类似的可以更新minCurrent。任何时候maxCurrent如果比最好的maxProduct大,更新maxProduct。
          具体代码如下:
    1. template <typename Comparable>  
    2. Comparable maxprod( const vector<Comparable>&v)  
    3. {  
    4.     int i;  
    5.     Comparable maxProduct = 1;  
    6.     Comparable minProduct = 1;  
    7.     Comparable maxCurrent = 1;  
    8.     Comparable minCurrent = 1;  
    9.     //Comparable t;  
    10.   
    11.     for( i=0; i< v.size() ;i++)  
    12.     {  
    13.         maxCurrent *= v[i];  
    14.         minCurrent *= v[i];  
    15.         if(maxCurrent > maxProduct)   
    16.             maxProduct = maxCurrent;  
    17.         if(minCurrent > maxProduct)  
    18.             maxProduct = minCurrent;  
    19.         if(maxCurrent < minProduct)  
    20.             minProduct = maxCurrent;  
    21.         if(minCurrent < minProduct)  
    22.             minProduct = minCurrent;  
    23.         if(minCurrent > maxCurrent)  
    24.             swap(maxCurrent,minCurrent);  
    25.         if(maxCurrent<1)  
    26.             maxCurrent = 1;  
    27.         //if(minCurrent>1)  
    28.         //    minCurrent =1;  
    29.     }  
    30.     return maxProduct;   
    31. }  
    1. 解法二、
          本题除了上述类似最大子数组和的解法,也可以直接用动态规划求解(其实,上述的解法一本质上也是动态规划,只是解题所表现出来的具体形式与接下来的解法二不同罢了。这个不同就在于下面的解法二会写出动态规划问题中经典常见的状态转移方程,而解法一是直接求解)。具体解法如下:
          假设数组为a[],直接利用动归来求解,考虑到可能存在负数的情况,我们用Max[i]来表示以a[i]结尾的最大连续子序列的乘积值,用Min[i]表示以a[i]结尾的最小的连续子序列的乘积值,那么状态转移方程为:
             Max[i]=max{a[i], Max[i-1]*a[i], Min[i-1]*a[i]};
             Min[i]=min{a[i], Max[i-1]*a[i], Min[i-1]*a[i]};
          初始状态为Max[1]=Min[1]=a[1]。代码如下:
    1. /* 
    2.  给定一个整数数组,有正有负数,0,正数组成,数组下标从1算起 
    3.  求最大连续子序列乘积,并输出这个序列,如果最大子序列乘积为负数,那么就输出-1 
    4.  用Max[i]表示以a[i]结尾乘积最大的连续子序列 
  • 声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。