查看原文
其他

来offer独家习题讲解 | Next larger number in a sequence

2017-02-28 乔老师 来Offer网

如果你正在找工作,以下文章对你有帮助:

来Offer孙老师专题 | 如何应对2017FLAG校招freeze

来offer独家 | 2017各大公司招聘实况更新, 谷歌新生名额已满!

我们是如何将300学生带进Google/Facebook的

课程 | 为了一个Offer, 你只需要一门课程

经典习题 | Maximum Subarray Sum Problem


题目描述

Given a sequence of integers, for each number, find the index of the next higher number, which is on the right side of the current number.


给一个含有n个整型数字的数组input,对于其中每一个数字,找到其右边第一个比它大的数的位置(index),如果不存在符合要求的数,则用-1表示。


例如:

Input: [3, 2, 1, 4, 1, 9]

Output: [3, 3, 3, 5, 5, -1]



解题思路

暴力解法往往会被很多同学忽视,而实际上它有着极为重要的作用:


从工程的角度上来讲,有一个解决方案永远都好于没有解决方案,而工程师首先需要能够有一种方法来解决问题。


从算法设计的角度上来讲,知其然更要知其所以然,所有的算法都是对暴力解法的层层优化,用一种更有效率的方法来解决问题。


在这个过程中能够体现出的观察力,分析能力才是解决问题的法宝,也是成为一个高质量的工程师能力和核心竞争力最好的体现。



首先,当我们看到这道题,我们至少应该得到一个最暴力最原始的解法。暂且称之为Naive解法。


这个最暴力的解法就是:对于每一个数组中的数,都过一遍这个数组,把我们所要找的数找到。


Solution 1: Naive解法

算法:利用两层循环。针对数组中每一个数字,以其右边作为起始位置,向后搜寻第一个比它大的数。


代码如下:


该种解法的最坏情况发生在:


当数组中的数是完全递减的时候。这样就需要n*(n-1)/2次比较。所以,Naive解法的时间复杂度是O(n^2),额外空间复杂度是O(1)


通过观察和分析找到已有解决方案中效率不高的步骤来进行优化。


观察的关键在于找到原有方案中效率不高的部分,一般来讲可以分为两大类:


不必要的计算

重复的计算


在这个过程中,利用观察例子来找到规律是必不可少的步骤,而用例子来帮助理解和解释问题也是最有效的方法。


我们可以通过观察例子进一步考虑如何优化时间复杂度:在基本解法中,每一个数字都被多次比较。


例如:在示例的input中,3要和2比,再和1比,然后和4比较才能得知4是3的下一个较大的数;2也需要先和1比较,再和4比较才能得到它对应的结果。


实际上,如果我们知道了2比3要小,当2和1比较时,得知1比2要小的时候,我们并不需要再将3与1进行比较了。这样的比较其实是多余的。基于这一点,我们可以进一步考虑如何优化Naive方法。


很显然,如果我们可以提前比较3与2之后,又比较了2与1,那么3和1就不需要再比较了。


从中,我们可以发现一个规律,[3, 2, 1]是一个递减的数组,当一个新的数字到达,它比当前的数要小的话,那么它一定不是当前数之前数字的结果。


我们可以借用一个stack维持一个非递增数列从而实现这样算法,移除多余的比较。基于此,我们可以得到如下解法:


Solution 2: 优化数据结构选择

额外的数据结构—stack: 利用一个stack去记录所有非递增的数列。存储这些数的index。

算法: 从左向右扫描input数组。


分成两个cases来处理:


Case 1: 如果当前栈为空或者新扫描到的数字比当前栈顶的数字要小,就把新到的数字加到栈中。


Case 2: 如果新扫描到的数字比当前栈顶要大,我们就开始从栈中pop出数字,并把pop出来的数字的对应结果记为当前数的index。


终止条件:扫描完所有的数字。栈中还剩余的数字为没有下一个较大数的数字。


代码如下:


针对数组中的每一个数,其最多入栈出栈一次。此种方法的时间复杂度是O(n)。


使用了一个额外的stack,最坏的情况是所有的数字都被压入栈。此种方法的空间复杂度也是O(n)。


自主的继续发现问题和解决问题,永远不满足于现有的解决方案是我们应有的态度。


对现有方案效率的分析可以帮助我们继续寻求更优的方法,层层推进继续尝试其它的突破口。


在面试中,如果能给出上述方法,一般来说,可以达到面试官的要求。


但是,我们能不能进一步思考,并提出一个解法,把空间复杂度也给优化了呢?


让我们回顾一下Naive解法,我们会发现,Naive解法并没有利用已经找好了的数字。如何利用已经计算过的结果是如何优化空间复杂度的关键。


我们可以试图从这一点入手,尝试使用已经得到的信息。对于每一个i]。我们可以尝试从紧邻其右边的第一个数input[j], j = i+数input[i],假使对于所有input[j], j>i,我们已经找到答案。


我们所要做的是找到当前数input[i]所对应的答案output开始查找,如果这个数字比当前数字大,很显然当前数字的答案已经找到。


如果input[j]小于input[i],并且input[j]并没有next larger number,很显然input[i]也不会有next larger number。


如果input[j]小于input[i],但是input[j]存在next larger number,则说明index在j与output[j]之间的数小于input[j],很显然这些数也会小于input[i],那么这些数字一定会小于input[i],我们不需要考虑这些数,直接跳到j=output[j]进行下一轮判断。


从后往前对input数组进行扫描,通过这样的一种算法,我们就可以利用已经找到的结果,从而减少时间复杂度。


Solution 3

算法:从后往前扫描,针对每一个数(index记为 i )。Initialization: j = i + 1


Case 1: 如果input[j] > input[i],则output[i] = j.


Case 2: 如果input[j] <= input[i],则:

Case 2.1:如果output[j] = -1,则output[i] = -1。

Case 2.2:否则,j = output[j]。重新开始判断。


终止条件:扫描完所有input数组。


代码如下:


从上述代码可以看到,针对每一个数字,操作j = output[j]至多计算一次。同时外围的循环i也是一轮遍历。所以该算法是一个线性算法,时间复杂度亦为O(n)。


同时,由于该算法并没有使用额外的存储空间,我们可以认为其空间复杂度是O(1)。


在对基础数据结构和算法扎实的理解的基础上,通过大量的练习,思考和总结才能真正开拓思路和提高系统的分析能力。


对大家的小建议是:


不要急于尝试思维跳跃来寻求最佳解决方案,欲速而不达。


重视基本解法,从最基本的解法出发,通过多个例子来加强自己的观察能力和找到优化突破口的能力。


永远不要放弃尝试,对于现有方案时间和空间复杂度的分析是层层推进的起点。



求职,你只需要一门课程

来Offer 2017年春季班2期

3月20号正式开课



Who We Are

来Offer网 (www.laioffer.com) 由清华大学计算机系在硅谷顶级科技公司(Google, Facebook,Uber)Director & Manager级别校友组成的职业培训机构。成员中有国际信息学奥赛International Olympiad in Informatics (IOI)中国国家队教练,Facebook 最早期的中国工程师经理和中国大陆招聘工程师负责人, 高考省理科状元,Stanford, CMU, Harvard, USC 等校CS Ph.D.组成。


What We Do

用最顶尖的师资力量带出高水平的学生:让强者更强,拿到一线大公司的Offer, 让转专业的同学迅速系统提高,拿到SponsorH1B的正规公司的Offer. 拿Offer不仅仅靠算法,而是系统素质的展现,包括英语表达沟通能力,Coding质量,多线程,System Design, OO Design,以及对美国职场最基本的理解。我们不仅仅是算法培训机构,而是一个培训同学们高成功率拿到Offer的职业培训机构。


  • FLAG 级别 Manager Level班主任负责制,有问题直接语音问答;每班配备10+名主讲老师,精心为同学们课后答疑和 1对1 code review.

  • 独立Online Coding训练系统 code.laioffer.com (300+最新大公司真题只对内部学员开放)

  • Google/Facebook engineer 上机课手把手教你编程

  • 每月一次跟踪考试, 老师1对1修改coding

  • 英文口语/书面的提高

  • 一线大公司Director/Manager level的老师, 内部推荐+面试综合技术提高

  • Internship level 3个月完成的实战project (可选课程)

  • 免费重复听,直到找到工作


高成功率

高成功率是我们唯一的标准: 2013年成立以来我们已经帮助数百名同学拿到Offer,成功率稳定在 80%。 其中Google, Facebook, Uber, Box, Microsoft, Yahoo, Amazon, Indeed, Hulu, IBM 等大中型公司超过半数。真名实姓Offer榜请见www.laioffer.com


欢迎发送简历至info@laioffer.com报名

我们将在24小时内联系您

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存