【转】常见面试题思想方法整理

66

2012-3-30 19:03:39 主要是 看到 双指针遍历 跟我最近遇到的类似,如链表循环判定有无和 判断相遇的位置,所以就转载了。 关于双指针遍历,作者的 问题,我还没有思考

最近一直在找工,博客都没怎么更新了,觉得也该总结和思考些东西了,于是便有了这篇文章。谈到面试题,其实它有很多种,有偏技术的(腾讯,淘宝问得多);有偏算法,逻辑和数学的(微软,谷歌,百度,阿里云等问得多)。

我喜欢后者,最近也做了很多这方面的题目,围观了很多关注算法和面试题的博客,比如(july童鞋)。对于很多精妙的题目,常常在想这些出题的童鞋是怎么想到的,因为这些题目确实能够很深入的考察出一个面试者的逻辑,算法和思维功底。本文章主要是总结自己在做这些面试题和了解相应解法的过程中思考的一些东西,感觉这些东西在很多题目中都出现过,非常值得抽象出来专门理解。

一 双指针遍历

所谓双指针,是利用两个指针对一个有序数组进行遍历,查找出符合要求的数据集合。相信大家都接触到了这种思维模式的解题方法,只是没有注意到罢了。下面举几个例子吧。

例1:给定一个数组a[n],求数组中是否存在两个数的和等于给定值sum并输出?

这个问题很常见,我当年在面试微软实习生的时候就被问到了此题,解决方法有很多种,这里我就不赘述,我讲的是用双指针遍历法的。首先数组不一定有序,对数组排序是必须的。那么便来到了这样一个场景:对有序数组如何遍历来求得符合要求的数据集合?双指针的解决方法如下:定义两个指针(i 和 j),分别指向数组头和尾,那么会出现如下三种情况:

  • 如果a[i]+a[j] == sum,那么很显然,只要输出这两个数,并把指针i+1和j-1指向下一个数即可。(这里不输出重复的组合)
  • 如果a[i]+a[j] > sum,说明当前遍历的数值偏大,所以可以把j-1以减小和的值,在继续比较。
  • 如果a[i]+a[j] < sum,说明当前遍历的数值偏小,同样为了加大和可以把i+1。

总的时间复杂度取决于排序即O(nlogn)。

例2:这题来自编程之美2.21只考加法的面试题,原题大致意思是写一个程序,对于一个32位整数,输出它所有可能的连续自然数之和的算式,要求是这些连续自然数之和要等于原数。例如3 = 2+1; 9 = 4+5,9 = 2+3+4等。

这题有两种解法,其中一种便是双指针法,还有一种比较巧妙,是我同学在面试阿里云计算的时候想到的,利用了数学方法,简单来说是求出一个公式来。这里只说双指针的解法。

这里需要一个转化,把求n中所有可能的连续自然数之和归约为在数组{1,2,3,...,n}中找所有连续子序列和等于n的问题。这里同样也是这样一个场景:对有序数组如何遍历来求得符合要求的数据集合?这时的双指针可以不是一头一尾了,而是两个都指向头部,这样可以以高效的顺序遍历我们要找的所有集合。初始设i=j=1,这里同样会出现三种情况:

  • sum[i,j] == sum, 直接输出i到j的值,并把i+1,j+1,因为只是i+1肯定是不等的,因为和小了,同样j+1只会使和变大,所以两个都要往前加(注意这里指针不用考虑减小,因为这在以前就考虑过了)
  • sum[i,j] < sum,说明偏小,那么提高j来使得和变大才有可能相等
  • sum[i,j] > sum,说明偏大,那么提高i来使得和变小才有可能相等

这样,代码就出来了:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

<span style="font-size: 16px;">//计算连续和为n的所有子序列

void GetAnswer(int n)

{

int i=1;

int j=1;

while(i<=n/2 && j <= n)

{

int sum = (j+i)*(j-i+1)/2;

if(sum == n)

{

for(int k=i; k <= j; k++)

cout<<k<<" ";

cout<<endl;

j++;

i++;

}

else if(sum < n)

{//sum[i..j]<n,只能提高j以增大sum

j++;

}

else//sum[i..j]>n,只能提高i以减小sum

i++;

}

}

</span>

这里的思想本质上与上面例题1是相同的,这也是我抽象出这种思维模型的原因,当遇到有序数组或者归约到有序数组时,利用双指针遍历的方法是求得我们需要的数据集合的一种相对比较高效的方法。

二 排除以减少解空间大小

相信这种方法大家都听过,但是实际使用的时候却时常忘了去考虑这种思维模式,我这里举的都是很巧妙的例子,也是我遇到的,感觉绝对值得把这种思考方法总结出来。

例1 此种解法很值得一说的题目来自编程之美2.3 寻找发帖水王,大致意思是:

某论坛有一个“水王”,经常发帖,据说该“水王”发帖数目超过了帖子总数的一半,那么如何在id发帖列表中快速的查找到这一“水王”?

这道题非常好的体现了排除法的非凡效果,如果直接去求这个水王,方法也不少,例如按发帖数排序,但是这至少是O(nlogn)时间复杂度,实际上最好的算法却是尽可能的去减少解空间,把不可能的去除掉,留下的自然是要求的的解。对于这道题,就是每次去除两个不同id的发帖,由于默认水王发帖超过一半,那么去除任何两个不同id后仍然是超过一半的,why?可以这样想,开始满足的公式是 x>y/2,那么减去两个不同id后,最坏情况,这两个不同id中有一个是水王的id,则(x-1)/(y-2) > (y/2-1)/(y-2) > 1/2,即仍然是大于二分之一的, 所以可以不断的这样做直到最终剩下水王id为止。编程之美上给出了一个非常精妙的程序,这里不赘述。

相同的例子还有这里。

实际上这类思想的应用场景可以认为如果看到要求的东西占总体数量一半以上情况的时候,可以考虑排除法。当然还有其他情况,例如正面求解屡试不行的时候,也可以考虑这样的方法。

三 蓄水池抽样求概率模型

想起这个是因为多次碰到类似概率题要用到它,例如10月16号百度北京的笔试题中有它,然后同学面试阿里云被问到的题目中有它,我发现不仅仅是当不知道n多大的时候,即便有时候知道n多大,也可以使用这个模型,详细的关于模型的知识可以查看wiki也看以看我这篇文章。

我同学在面试阿里云的时候被问到这样一个概率的问题:

给你一个n个长度的链表,以及一个函数,这个函数50%的概率返回0,50%的概率则返回1,问如何用这些条件从这n个链表中随机的抽取k个节点。

利用蓄水池抽样可以有这样一个解法,首先,这个函数可以产生0和1,那么我们可以通过构造多个二进制位(调用多次这个函数)并只取其中某些情况来构造任意概率,例如假设我要构造1/4,那么我调用两次这个函数,如果出现00,我认为发生,如果不是则不发生;又假设要构造3/5,我调用三次这个函数,并假定3种出现为无效出现,例如000,001,010。如果出现这种则再次调用函数生成,同时我们指定某三种为出现,其余不出现,这样可以构造一个生成概率3/5的生成器。有了这个,我们利用蓄水池抽样思想,先指定前k个节点为所求,并把指针指向第k+1个节点,此时以k/(k+1)决定是否与前k个选定的节点替换,替换时随机选择,并以此类推直至结尾。最后剩余的节点即为所求。

总的来说,我觉得这三个思想都是经常可以利用的,有些问题没有见过这些思想是挺难在面试时当场想出来的,相反如果通过面试题提取出某些抽象可复用的思想,那么以后任何变形的面试题,都可以归约至这些解法从而解决,相信那个时候面试官一定会对你刮目相看。

转载于:https://www.cnblogs.com/titer1/archive/2012/03/30/2425824.html

【转】常见面试题思想方法整理--- 原来果然有双指针遍历相关推荐

  1. 常见面试题思想方法整理

    最近一直在找工,博客都没怎么更新了,觉得也该总结和思考些东西了,于是便有了这篇文章.谈到面试题,其实它有很多种,有偏技术的(腾讯,淘宝问得多):有偏算法,逻辑和数学的(微软,谷歌,百度,阿里云等问得多 ...

  2. mysql常见面试题及答案_MySQL常见面试题与答案整理

    1.MySQL 中有哪几种锁? 1.表级锁: 开销小, 加锁快: 不会出现死锁: 锁定粒度大, 发生锁冲突的概率最高, 并发度最低. 2.行级锁: 开销大, 加锁慢: 会出现死锁: 锁定粒度最小, 发 ...

  3. java程序员面试常见面试题及答案整理

    JAVA相关基础知识 1.面向对象的特征有哪些方面  1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分 ...

  4. ibatis spring框架升级到5.x_Java SSM框架常见面试题,良心整理,

    点击上方蓝色字体,选择"置顶公众号" 优质文章,第一时间送达 文末有送书活动 文末有送书活动 文末有送书活动 一.Spring面试题 1.Spring 在ssm中起什么作用? Sp ...

  5. 2021年- 精心整理的 SpringBoot 常见面试题-【附详细答案】

    目录 1. Spring Boot 自动配置原理是什么? 2. SpringBoot配置-profile 3. SpringBoot中有哪些常用注解 4. Spring Boot.Spring MVC ...

  6. 面:常见面试题整理(操作系统)

    常见面试题整理(操作系统) 常见面试题整理(操作系统) 2018年03月08日 20:47:11 逃离地球的小小呆 阅读数:20782 (一)请分别简单说一说进程和线程以及它们的区别. 进程是具有一定 ...

  7. 常见面试题整理--操作系统篇(每位开发者必备)

    这两日整理了很多编程方面的资料:教学视频.书籍资源以及实战项目全部放在了百度网盘里,资源的目录以及获取方式都放在了文末的图上,你可以直接翻至文末查看. 有过面试经历的人都知道操作系统是面试官必问的几大 ...

  8. 常见面试题整理--数据库篇(每位开发者必备

    常见面试题整理--数据库篇(每位开发者必备) 转载自:https://zhuanlan.zhihu.com/p/23713529        知乎专栏 继续前面有关于的Python面试的两篇内容:P ...

  9. Java常见面试题整理(一)

    Java常见面试题整理 字符串 抽象类与接口 集合 多线程 锁 IO流 网络编程 字符串 主要包括String.StringBuffer和StringBuilder基本概念 String相关知识 St ...

  10. 2021年JAVA 精心整理的常见面试题-附详细答案【持续更新~~】

    先罗列本篇文章包含的Java 常见面试的主题: 一.Java基础面试题 二.Java 集合框架 三.Linux常用指令 四.MySQL基础面试 多线程与多进程面试 常见设计模式 JVM 底层 关注我们 ...

最新文章

  1. *44.程序的链接方式
  2. vue深究第一弹:computed与watch的异同
  3. python 字符串 编码 解码_Python 字符串编解码研究
  4. 常见笔试面试问题点(转载)
  5. StringMVC 中如何做数据校验
  6. JavaScript中带有示例的Math.max()方法
  7. 如何利用Python播放和录制声音
  8. 安卓系统双屏异显_Android实现双屏异显
  9. 计蒜客挑战难题:A+B+C问题
  10. Microsoft Dynamics CRM 2013 的权限管理与分配 (二)
  11. 2021-08-10 C3P0连接池
  12. 树莓派做微信公众号服务器,树莓派与微信公众号对接(python)
  13. qt.qpa.xcb: could not connect to display解决
  14. 研发项目该如何管理?
  15. java 计算毫秒差值,关于时间的操作(Java版)——获取给定时间与目前系统时间的差值(以毫秒为单位)...
  16. 16. 二元随机变量,离散型随机变量分布律
  17. 小米(社招)测试开发面经-小米手机管家
  18. 读书笔记----《平凡的世界》第三篇
  19. 达摩院年终预测出炉:AI for Science 高居榜首
  20. asp.net入门书籍

热门文章

  1. pytorch加载自己的数据集图片格式
  2. 计算机视觉标准数据集整理—PASCAL VOC数据集
  3. python实现判断给定列表是否存在重复元素,且索引差小于k
  4. 2021-07-05 页面的生命周期
  5. html怎么让背景颜色百分比,jquery – CSS设置背景颜色只是表行宽度的一个百分比...
  6. truffle部署到测试网rinkeby
  7. python 读取网页并分词
  8. java ajax框架_ajax框架之 zk -demo1
  9. 基于SSM的家具商城系统
  10. h3c服务器设置u盘引导,H3C FlexServer R390服务器装系统前的准备工作