自欺欺人的故事 | 四火的唠叨



自欺欺人的故事 | 四火的唠叨

不要看不起在生产线上干活,俺正经干过一个月,你对人生有很多体会。俺的一个朋友,一个非常大的跨国公司在中国的销售主管,大学毕业后第一份工作在宝洁,从一个偏远的城市蹬三轮买洗衣服做起。他讲有一次差点把他当盲流给抓了。我倒建议现在大学生毕业,下基层一年。

若是想强调"体验"和"经历"在人生中的重要价值,这番话的初衷自然是好的。比如这样的回复:

还是去一线做个两三年的好,想想现在很多所谓顾问根本没下过车间,却给工作几十年一步步走上来的主管做咨询,有时想想都害怕,只有理论就是空谈,譬如马克思害了多少人,空谈误事啊,切记!

我们见到太多的务虚主义者,太多的所谓咨询师和流程专家,企图用他们的理论来解决各种软件问题。最后无疑是害人害己,敏捷本身没有问题,但是它的名声已经被这票人彻底搞臭了。现在谁还敢轻易提敏捷?

但是,看着下面这些人的回复,我却产生了另一种担心:

老师说的非常对,��出社会的孩子,应该从最基层做起,这对以后的工作都有巨大的意义!李嘉诚最年轻的时候也是从基层买塑料花开始的!

等等。我并不是仅仅针对这一条微博想发发牢骚,而是我看到太多这样的情景:

有的长者会教育程序员,在那个苦闷的年代,物质条件极其缺乏,需要什么东西都必须自己去做,而不是现在开源的东西、现成的东西那么多,代码还可以到处抄――请忍受你不喜欢的工作,请耐着性子去做那些没有意思的事,你会从中得到锻炼的。

于是年轻人程序员一根筋地找了一份辛苦的软件工作,不仅辛苦,还违背自己的人生观价值观,做着毫无技术含量的体力劳动,没有被尊重,只被当做劳动力,却又没有勇气或不适合重新选择,只能自我安慰道:

"我现在需要的是经历,有了这样的苦逼的岁月,才有牛逼的未来。"

这无疑是极好的,如果你是一只愿意暂时蛰伏,而期望在未来冲破云霄的不死鸟的话。这是一种将悲观和困境换做动力的方式。

可是对于许多人来说,真的如此吗?

据我所知,有许多学生在学校的时候就被灌输这样的思想:"大学毕业生找不到工作,有一份工作就不错了",导致相当数量的孩子放弃了自我追求,放弃了兴趣的选择,看到工作机会也无论好坏、不做选择就一哄而上,迅速签下劳动合同。接着过上了一种不如意,不得不在逆境中继续浑噩的生活。

别忘了,逆境除了磨练人,也会打磨人的棱角,让人失去最初的激情和梦想。那些无比坚韧的孩子最终能等到回报。但是大部分人呢?

自欺欺人而已。

别忘了,环境会改变你的。当你觉得你也许熬过了那些不如意的岁月,你也许不想再经历新的变化了,说着"算了,就这样吧",你的人生轨迹彻底改变了。

我想,每一位年轻人,尤其是在最初几年的工作抉择中,请慎重而为之。未来的你还有别的机会积累那些磨练人意志的体验,但是仅此一次的优秀工作机会会让你未来事业旅途风景大不相同。就如同你的下一份工作很大程度上取决于你前一份工作的类型和质量。选择一份符合自己价值观,和一群你喜欢的人一起工作,这很重要。我回复说:

话虽如此,学软件的你会在毕业拿到一份谷歌工程师offer,一份手工车间工作机会的时候。按照这个标准选择么,太扯了吧。积累这些经验固然无错,但你未必要牺牲优秀的工作机会刻意为之。

当然,如果你是那些钢铁神经的勇士,天生的赢家,请相信金子总会发光的,无需在乎我的看法。


Read full article from 自欺欺人的故事 | 四火的唠叨


黑客:美硅谷公司在保护IS网站_网易科技



黑客:美硅谷公司在保护IS网站_网易科技

11月30日,据《每日邮报》,"匿名者"(Anonymous)称,美国硅谷有家公司正帮助"伊斯兰国"加快并提高网络安全。

为回应巴黎的恐怖袭击,黑客行动主义者开始了针对恐怖组织网络的活动。"匿名者"组织称,美国"云闪"(CloudFlare)公司在保护"伊斯兰国"的网站。

11月16日,"匿名者"发布视频向ISIS宣战

美国云闪公司是跨国科技企业,总部位于旧金山,在英国伦敦亦设有办事处。美国云闪公司以向客户提供网站安全管理、性能优化及相关的技术支持为主要业务。通过基于反向代理的内容传递网络及分布式域名解析服务,美国云闪公司可以帮助受保护站点抵御包括拒绝服务攻击在内的大多数网络攻击,确保该网站长期在线,同时提升网站的性能、访问速度以改善访客体验。

如果美国云闪公司的确向"伊斯兰国"提供帮助,这也就意味着,若"匿名者"尝试上网,破坏"伊斯兰国"的网站,云闪公司的高科技将会阻止匿名者的行为。

"匿名者"在推特上发布博文称,云闪公司为伊斯兰国提供服务

最近一份报告指出,美国云闪公司为40家与恐怖主义相关的网站提供保护,其中有37家网站纯粹进行恐怖主义宣传。

"匿名者"在推特上发布状态称,云闪公司再一次被发现为"伊斯兰国"组织提供保护。令人惭愧。

马修・普林斯是美国云闪公司的联合创始人兼首席执行官,他说"匿名者"的说法完全是捏造事实,并坚持声称云闪公司从未支持恐怖组织。他认为"匿名者"的控告完全是小孩子不符合事实的分析,不用太当真。他还说道:"如果警察来硅谷调查的话,我们也会全力配合。再说,帮助'伊斯兰国'对我们也没有好处,我要考虑得是他们是不是用偷来的信用卡支付,这对我们有害无利。"

谈到云闪公司400万客户时,普林斯称,其中有些人可能的确比较危险。


Read full article from 黑客:美硅谷公司在保护IS网站_网易科技


'The Witcher 3' And 'Fallout 4' Show Us That Single-Player Games Should Live Forever



'The Witcher 3' And 'Fallout 4' Show Us That Single-Player Games Should Live Forever


Read full article from 'The Witcher 3' And 'Fallout 4' Show Us That Single-Player Games Should Live Forever


百度笔试题 | 飘过的小牛



百度笔试题 | 飘过的小牛

简答题(30分)
1.用简单语句描述数据库操作的步骤(10分)

1)连接数据库,并检查连接是否成功;
2)若连接成功,输入数据库操作命令;
3)为保证系统的稳定性,可选择备份数据库原有数据;
4)运行数据库操作命令;
5)关闭数据库连接;

2.写出TCP/IP的四层结构(10分)

1)应用层:用户使用应用程序进行通信;
2)传输层:在遵守协议的基础上,源主机和目的主机进行数据的传输;
3)网际层:在网络中,处理数据的路由和转发,保证数据准确送达;
4)网络接口层:将ip数据报解析为帧,在物理链路上进行透明的比特流传输;

3.什么是MVC结构,并描述各层结构的作用(10分)

MVC模式是三层架构模式,分别为:Model――模型,View――视图,Controller――控制器,MVC模式是软件工程中的一种软件架构模式。
1)模型:程序员编写程序应有的功能(实现算法等)、进行数据库设计和数据库管理;
2)视图:界面设计人员进行图形界面的设计;
3)控制器:负责转发请求,对请求进行处理;
简单来说,就是当你点击某一链接时,控制器会调用相应的模型来完成这次点击执行的操作,然后调用对应的图形界面来显示操作的结果。实现了各个功能模块的分离,降低了耦合性。

二、算法与程序设计题(40分)
1、字母a-z,数字0-9,现需要其中任意3个作为密码,请输出所有可能组合。(伪码CC++JAVA)(10分)
我的思路是将a-z映射为10-35,然后进行dfs遍历所有组合

2、实现字符串反转函数(10分)

这个思路很简单,但是具体实现的时候要考虑程序的鲁棒性。比如,输入的是一个空字符串,或者输入是一个空指针,对于这些情况,我们要分情况讨论。

3、给定字符函数a、插入 b、删除 c、替换
例如字符串A=acegf,字符串B=adef,最少需要2步操作将A转换为B,
即第一步将c替换为d,第二步将g删除;
(1)请问将字符串A=gumbo转换为字符串B=gambol,最少需要几步操作,列出如何操作(2分)
(2)任意字符串A和字符串B,如何计算最小操作次数,计算思路,并给出递归公式(3分)
(3)实现代码(注意代码风格与效率)(15分)

这道题和《编程之美》上的一道题目相同,是经典的字符编辑DP问题。

三、系统设计题(30分)
RSA SecurID安全系统
应用场景:这是一种用户登录验证手段,例如银行登录系统,这个设备显示6位数字,每60秒变一次,再经过服务器认证,通过则允许登录。问如何设计这个系统?
1)系统设计思路?服务器端为何能有效认证动态密码的正确性?
2)如果是千万量级用户,给出系统设计图示或说明,要求子功能模块划分清晰,给出关键的数据结构或数据库表结构。
考虑用户量级的影响和扩展性,用户密码的随机性等,如果设计系统以支持这几个因素.
3)系统算法升级时,服务器端和设备端可能都要有所修改,如何设计系统,能够使得升级过程(包括可能的设备替换或重设)尽量平滑?

这道题属于一个开放型题目,但是对这个问题有过思考的话,应该还是很简单的。因为以前网易就曾出过这种设备,当时还研究了一下。
我当时答的是:
1)这个设备内置:精确的时钟、一个种子文件、一块电池、一个lcd显示屏。
通过对时间和种子文件的组合,得到一个数字,然后再通过二次加密(如采用hash算法),得到一个6位数。验证的方法相似,就是系统保留已经使用的设备的种子文件,通过相同的加密方法来验证密码的正确性。
2)对于随机性因素而言,我主要采用的思想就是预处理机制+多处理机。根据用户所在的省或者市,用对应的处理机单独处理,可以存储用户设备的种子文件,可以在用户提交密码后迅速计算结果,并到结果文件中进行验证。

3)对于系统升级来说,要综合考虑系统和用户的情况。对系统而言,要保证系统在升级时不会出现bug;对用户而言,要保证升级时间尽量短,以免耽误用户的使用。


Read full article from 百度笔试题 | 飘过的小牛


DNS劫持 | 四火的唠叨



DNS劫持 | 四火的唠叨

想谈一谈这个话题是因为最近有一位朋友抱怨他的博客在某些用户某些时候访问的时候,被莫名其妙地加上了广告,他检查来检查去,始终发现不了网站本身有什么问题,后来他才了解到了DNS劫持一说。

DNS劫持

其实这不是一个新概念了,在几年前,中国一些不讲道德的运营商,尤其是地方运营商就开始捕捉用户浏览器的访问记录,然后根据不同用户的访问行为,有选择地往用户访问的网页里面推送广告。因为运营商掌握着DNS主机,所以他们可以为所欲为地强制改写网站HTML页面,采用往返回页面里写入JavaScript等方式,来注入广告:


Read full article from DNS劫持 | 四火的唠叨


关于Jeff Dean的几个搞笑传言 | 四火的唠叨



关于Jeff Dean的几个搞笑传言 | 四火的唠叨

我想许多程序员都对这个名字如雷贯耳,如果你没有听说过,可以扫一眼他的个人履历,你会感到无比惊讶的:

  • Google AdSense(在线上发布广告);
  • Protocol Buffers协议,protobuf,用于把结构数据序列化;
  • Google News;
  • MapReduce;
  • BigTable;
  • Spanner,分布式数据库;
  • DistBelief,分布式的深度学习和并行计算平台;
  • ……

但是,最著名的就是他设计和实现了Map Reduce和Big Table,这两项改变世界的技术。

坊间流传着许多关于Jeff Dean有趣的说法,我挑了一些我觉得有趣的列在下面:

  • 在Google面试的时候,Jeff Dean被问到要求解释一下P=NP的含义。他说,P=0或者是N=1的时候等式成立。然后,在所有面试官大笑完之前,Jeff瞅了一眼Google的公共证书,然后直接在白板上写了相应的私钥。
  • Compilers don't warn Jeff Dean. Jeff Dean warns compilers. 编译器从来不给Jeff警告,Jeff总是警告编译器。
  • 从2000年末开始,Jeff的编码速度增加了40倍,因为他把键盘升级到USB 2.0了。
  • Jeff Dean会在提交代码前编译一遍,仅仅是为了检查编译器和链接器有没有bug。
  • 光在真空中的速度曾经是35英里每小时,不过后来Jeff Dean花了一个周末优化了一下物理学。
  • 当Jeff Dean向以太网发送数据包的时候,从来都不会出现冲突,因为其他包都主动退回到了缓冲区。
  • Jeff对常数时间复杂度很不满意,于是创建出了世界首个O(1/N)的算法。
  • Jeff Dean was forced to invent asynchronous APIs one day when he optimized a function so that it returned before it was invoked. 某天Jeff Dean被迫发明了一个异步API,所以在API被调用前就返回了。
  • 当Jeff Dean设计软件的时候,他是直接写二进制代码的,至于写源文件,只是作为参考文档而已。
  • Jeff Dean曾经用一个简单的printf()调用实现了整个web服务器,其他工程师添加了几千行说明代码但是仍然无法解释到底它是怎么工作的。如今这个程序就是Google搜索的前端页部分。
  • When Jeff Dean fires up the profiler, loops unroll themselves in fear. 当Jeff Dean触发性能剖析器的时候,循环会因为恐惧而自动展开。
  • When Jeff has trouble sleeping, he Mapreduces sheep. 当Jeff睡不着觉的时候,他Mapreduce羊群。
  • 2002年的时候,Google挂了,Jeff Dean就主动站出来手动处理搜索请求,于是搜索质量就翻番了。
  • Jeff Dean穿裤子的时候,一次只能穿一只脚,但是如果他有好多脚的话,你会看到他可以以O(log n)的时间复杂度穿裤子。
  • Jeff Dean消失在/dev/null后,又回来了!
  • Jeff Dean以电子名片的md5摘要来给电话联系方式排序的。

Read full article from 关于Jeff Dean的几个搞笑传言 | 四火的唠叨


换组 | 四火的唠叨



换组 | 四火的唠叨

最近在忙于公司内部换组的事情,在亚马逊等等很多公司都有这样的政策文化,就是,如果你在这一个组工作一年以后,并且绩效不太差的话,都可以自己去寻找觉得喜欢的团队加入。我在当前的这个大组干了两年多了,经历了一些成败和风波,我觉得是时候离开去寻找一个更合我胃口的团队了,增加阅历和体验,当然,也肯定是新的挑战。在思考自己的职业未来的时候,其实是有不少选项的。大约是最近这一年,我越来越感觉到,在Amazon工作,那么多内容里面,最有价值的大概是数据,我寻找的下一站,也是想多参与和大数据更紧密的工作。如果说以前我的工作更像是一个full stack engineer的话,接下去一段时间,我要更多地和数据、计算,以及各色job打交道了。希望自己这部分能够得到增强。

我想起我第一次换工作,实在11年底12年初,正好距离我毕业踏入职场三年半时间,而这以后到现在虽说不换公司,但是也算是比较大的变动,也是三年多的时间。职业生涯有多少个三年?

说到我想要离开现有团队的原因,主要是两个方面,一个是做的东西范畴还是偏小,在一个大风格的大team内部,缺少足够的关注,不容易赢得同行工程师足够的认可。再一个则是确实已经在这个组织中呆了接近三年的时间,也到了一个对新事物渴求的时期,希望自己更多的方面得到成长。另外,H签证没有抽到,因为L签证的关系,跳槽成为了不可能,要不然我也很愿意在适当的时候去尝试那些更不同的新体验。

一开始我寻找下一个团队的目标并不清晰,总共去了解了好些团队,在沟通和了解的过程中,逐渐地有了清晰的目标。真正进行面试的有两批次,总共五个团队。这里的流程一般是,先找感兴趣的小组,然后约见manager,大家互相了解一下需求,一般有一半的情况到这里之后就戛然而止了,剩下一半进入面试环节,一般团队中的工程师会直接和应聘者交流,以3到4轮的居多,每轮半小时到一小时不定。小组经历的面试大致有三种风格,一种是像Amazon对外面试一样,比较严格,几轮,每一轮都有侧重点,比如系统设计和算法等等;第二种是大聊特聊项目组的风格和以往的项目,因为都在同一家公司,交流起来有很多双方都很了解的背景,因此效率很高,彼此能够获得很多信息;第三种则是问很多behavior question的,这种面试我不很喜欢,聊起来话题倒是轻松,但是扯着扯着就要往各路leadship上靠,而且最主要的原因是,不够techinical。面试过程中,我发现我还是更喜欢和工程师打交道,和manager聊起来情况各异,有的比较直率,我可以比较深入地探查风格是不是匹配,比如有的有点oversell他的项目和团队,有的则是个事无巨细的控制狂人,这两者我都有些忌惮。

了解一个团队,不能只听那些兜售的话,作为工程师,一个好办法就是去翻他们的代码,看他们写的wiki,必须非常确定目标小组的技术和项目是我感兴趣的。对于团队气氛,流程以及manager的风格,都是需要了解的内容。后来几次找其中的同事沟通,尽可能多了解情况,心里踏实一些。

想起我刚开始工作的时候,没有这样的自由度,要换组是一件很麻烦的事情,要和领导请示,通常也很少人这么干,大部分人都是"一块砖",哪里需要哪里搬。当然,要是受不了就直接走人了。其实这样的政策,总的来说是一件好事。对员工而言,对公司而言都是。无论是工程师开拓眼界,促进团队之间的良性竞争,还是多一条渠道留住优秀的工程师工作,都有正面的意义。


Read full article from 换组 | 四火的唠叨


手滑的故事 | 四火的唠叨



手滑的故事 | 四火的唠叨

最近看到这篇文章《小伙伴们手滑集》,觉得感慨很多,强烈推荐大家阅读。比如这样的例子:

UPDATE没有WHERE条件

而我则经历过delete没有写where条件的惨剧,这个惨剧是某些case下面代码调用触发的,不是手动执行SQL发生的。

还有臭名昭著的,我没有经历过,但是我有不止一个同事干过这样的事情:

rm -rf

都只是手稍稍地温柔地"滑了一下"而已嘛……

这些事情我觉得一下子很亲切,似乎全世界的软件工程师都是如此得同一。

出的事故多了以后,变得战战兢兢,如履薄冰,尤其是回车键这样的敲击,似乎总是带着颤抖落指。

还有这篇文章《让自家系统瘫痪,这事我也干过》,讲了一个关于使用truncate语句清空数据库数据的故事。及时报告老大,但是领导给了这样一个反馈:

赶紧恢复数据,最迟明天早上必须要解决,不要让用户感觉到。

其实这样的话是非常给程序员压力的,我可以想象当时那种场景。线上数据丢失是如何惊心动魄。

作者给了这位老大一个很高的评价,但是我不这么认为。这件事情最终大事化小、小事化了的做法是很不错的,但是给出时间点压力这样的事情其实对当时火烧眉毛的情况解决并没有帮助。

 

谁都会有手滑的时候,我最大的感受是,在"线上系统维护"这样的事情上,"人"远没有"机器"可靠。

造成的恶劣后果多半为"服务停止"或者"数据丢失"两种,尤其是后者,有时难以挽回,损失惨重。

我经历过的"手滑"惨剧也有一些,当然没有那么恐怖。

  • 比如在杀Hadoop job的时候,有一个重要的线上job还在跑,被我杀掉了,当时吓了一跳,赶紧找熟悉这些job的oncall来看,还好这个job是幂等的,重跑就行了。如果运气不好,干掉一些特殊的job,结果或许就糟糕了。前年年底就有一个组内job的问题因为维护的工程师的操作触发了sev 1(最高级别)的线上问题。
  • 再比如我曾经有过"手滑"把一个造成服务不可访问的问题留到版本中发布出去了,结果测试同学们也没法发现该问题,最后导致线上服务无法使用,被迫连夜赶补丁打上去。
  • 再再比如有不止一次,想把线上log之类的文件给删掉,但是手滑,删错了目录,把一些线上重要数据或者服务文件夹给干掉了……

看那些manager们,还有公司们对工程师们操作线上数据和服务手滑以后的严重后果,基本上有这样几种反应,后三种我都见过,第一种有同事经历过:

  1. 当即批评,事后追责。这时最差的公司和领导。
  2. 对外道歉平息风波,对内查清问题追究操作人员责任,绩效差评。这是中庸的公司和领导。
  3. 对外冷处理,对内以鼓励为主,但是评估问题根因和改进。这种做法就好得多了。
  4. 内外一致,详细分析问题,包括连续问几个why,问题责任主体只定位到团队,不追究个人。这个做法也不错。

我想对于这样的问题,有一个原则就是,我相信责任主体工程师早就懊悔万分了,再责怪他,对解决问题只能起到反面的效果。

 

没有手滑的人生,是不完整的。

没有手滑经历的程序员,是不成熟的。

 

我相信关于这样的问题发生之后的后续改进,不同人会有不同的看法,我先说一说那些最不靠谱的办法:

  • 公开批评和个人责任落实。事实上绝大多数情况下,犯错的同学已经心有余悸,良心惴惴不安了。更大的批评砸头上只能带来消极的结果。最消极的结果就是减少工作产出,正所谓,"不做不错",不让我犯错,我不干活就是了。
  • 把问题的检查写到文档,比如checklist里面去,等到类似场景的时候拿着checklist排查。这也是一种比较不好的做法,也许会好过什么都不做,但是:(1)这样的问题要确保足够的可重复性,否则只会导致这个checklist越来越复杂,直到最后根本无法实行;(2)这始终是个笨办法,工程师被条条框框牵着鼻子走只会让工作氛围和积极性越来越差。
  • 强化"人"的管理和监督流程,这也是一个好不到哪去的办法,比如对线上操作需要得到领导审批,最大的问题在于这会大大降低效率,降低工作热情。而这样的效率降低,很多职位高的人却看不到。

反过来,也有好的实践,大多数实践都能够做到,规避了问题,并且在"不知不觉",或者是没有明显代价的情况下实现的。

比如说,Linux下,建立和使用不同权限用户的习惯,可以很大程度上避免手滑删文件悲剧的发生。

当然,这在有些情况下只是理想状态,多数团队都要做好足够充分的备份和容错,毕竟手滑难以避免,来势凶猛,如何脱身和保全数据并不容易。

 

今天的行文风格有点奇怪,��嗦倒是依旧,只是文字如此稀疏。

最后,我想说,我写这些文字的初衷,仅仅是发发感慨,这样的事情看起来如此之亲切。

尤其是意识到手滑的那一刻,身后那凉飕飕的感觉,肌肉抽搐,浑身颤抖,如鬼抚背,难以忘记……

呃,还是说多了。


Read full article from 手滑的故事 | 四火的唠叨


一点美中医疗的对比 | 四火的唠叨



一点美中医疗的对比 | 四火的唠叨

最近耳道感染,左耳朵又堵又疼,在美国几次就医,本人虽非医学专业出身,但从局外人的角度,想到和国内那些求医的历史,还是有一些比较可言。

首先对于医生的划分,国内基本上就是根据科室来完成,一个医生在一个科室,时间久了,经验丰富,遂成为出名的医生。好处在于医生更能够专精于自己的一亩三分地,专科阅历容易积累。而看看许多国内的专家,有大量的机会见各种各样奇怪的病人,并且手术的机会也会非常多,因此我猜测经验会更加丰富。但不足之处在于,对于病人来说,疾病往往是复杂性全身性的,可能对要挂哪个科室并不清楚,即便到求医中后期,都有可能面临多科室一同合作的情况,这些情形都容易导致耽搁病情。

而美国的医疗体系,医生分为家庭医生和专科医生,家庭医生数量巨大,这些医生又称作全科医生,什么都管,绝大多数问题,到了他们那里,都可以解决掉。真正解决不掉的,再由他们推荐给相应的专科医生处理。优点在于资源可以高效利用,专科医生接管的病人,都不是那种显而易见或者很容易打发的疾病;再一个对于病人而言,很多病人都有自己长期合作的家庭医生,可以说有助于培养熟悉和亲切的医患关系。

其次说说就诊过程。国内基本上都是挂号体系,大部分号都在现场挂,排队等,少部分号通过电话或者网上预约完成。由于人口过多,而且三甲医院和地方小医院医疗水平差异过大,导致大型医院的医疗资源过度集中,挂号非常困难。而且由于众所周知的长期以来的医患问题,都愿意去找"靠谱"的医生处理,于是许多知名专家被迫不断接诊各种小毛小病,而那些真正需要帮助的人,却因此得不到宝贵的机会。

见面就诊的过程中,经常会遇到医生两分钟打发病人了事,但是这一点上,我很想为国内的医生说句话,很多情况下客观条件不允许详详细细地和病人沟通交流,毕竟排队的病人太多,实在是没有办法。

在美国则基本上有这样几种就诊分类,一种是常规电话预约家庭医生就诊,最节约时间,并且是节约双方的时间,还有的诊所支持walk in,有点像国内的"加号",可能会让病人排队等一会儿,但是价格上这两者都是比较接近的。接着两种就贵了,一种是urgent care,没有生命危险但需要立即紧急处理的,比如手臂被割伤;另一种更贵的则打911叫救护车都可以了,比如心脏病犯了。去年踢球的时候有一同事脚疑似韧带断裂,躺在地上根本就起不来了,我们没办法就打911,结果五分钟左右消防车就最先开道到达了,车上下来两个负责应急处理的医护人员,之后到达的才是救护车。至于救护车的呼叫费用,每个州的情况都不相同。

整个就诊过程很舒适,到单独的隐私密闭的房间里,护士先来问诊,最开始建立档案的时候,问得特别细致,包括父母有什么遗传基本,开车系不系安全带都问清楚,之后的问诊则是就患者疾病收集信息,这个过程大概十几分钟。之后医生来问诊,检查一下,配了点抗生素就撤了,今天耳朵疼得厉害,再去又配了个滴剂。总体来说,和国内输液、中成药满天飞的情况比,配药挺谨慎的。我看了一下药费,可能和国内的药费差距不大,但是医生求诊的费用,会以账单形式寄到信箱里,这个数会比国内看病贵上好多倍。关于取药,诊所内是没有我需要的抗生素的,但是这种东西在一般的超市里面的pharmacy都可以根据医生处方买到。因此凭借医生的处方就可以去超市拿药了。

在美国看病如果没有保险的话,真可谓看不起病。而保险又是很贵的。说"穷人不怕得病,政府会管"这种话是很荒唐的,事实上,申请破产来让政府接济账单是有的,但是只有急救才必须接诊,而其他毛病,据我所知,没有保险并且无法付款的话医生是可以拒诊的。

国内的医疗还在逐步发展,但是根据这一点中美对比,有这么几个方面是可以借鉴的:

  • 社区全科医生(或者说家庭医生),他们可以解决70%以上的问题,节约医疗资源,而且有助于改善医患关系;
  • 医药分离,这一点据我所知已经在北京开始慢慢推广了,没有了药品中的回扣,看医生的价格会更贵,但是医生开的药方会更加透明;
  • 药品审核,相对于西药,恐怖的是中成药:中药利润小,西药审核制度严,而许多中成药简直就是胡来;
  • 医保体系,当然这个已经比前些年更完善了,大病医保的上限和报销比例尤其重要。

Read full article from 一点美中医疗的对比 | 四火的唠叨


直面歧视 | 四火的唠叨



直面歧视 | 四火的唠叨

最近在知乎上面看到不少关于歧视讨论的帖子,大部分人的观点都是,歧视是负面的,要避免歧视,尤其是在公众场合歧视的人,要惩戒。这条观点展开来的话题,大部分我都认同,只是我想补充的是,其实歧视没有那么遥远,不要把歧视的事情全部看做多么罪恶深重的事情,事情要一码一码分开来看,有轻有重,我向来厌恶鸡汤,统一的道德帝是可恶的。

首先,来澄清"歧视"的概念:歧视,是针对特定族群的成员,仅仅由于其身份或归类,而非个人品质,给予不同的对待。好,就针对这样的定义,有那么多人跳出来说,"我不歧视任何人","我不歧视任何事",说说如此容易,可这样的话经得起考验么?从最简单的分类例子看起,知乎"歧视"话题下面的几个子话题:

  • 种族歧视。有个女性,找了个黑人男友,仅仅是因为肤色,他们就成了众人议论的对象,父母都很难接受这一点。
  • 地域歧视。我老婆说,最讨厌上海人,上海人都排外;老妈说,过年了,谨防小偷,尤其我们家乡外地人中安徽人多,觉得他们偷东西;坐出租车,司机说到那个河南人杀人犯最多的传言……
  • 性别歧视。你一个女人,那么张扬干什么,那么努力工作干什么,那么有野心干什么?
  • 国别歧视。最著名的"国外的月亮比较圆"的那句话。
  • 疾病歧视。都知道乙肝日常的接触不传染,艾滋病日常的接触不传染,但是实际上呢?有多少人谈之色变,避恐不及?
  • ……

这样的例子实在是太多太多了,我建议对这个话题有话要说的朋友看看维基百科的"歧视"词条,上面列出了太多例子,很有分类性和典型性。我列出来的只是比较常见的几种而已,它们也是在多数人认可的价值观中,极端错误的几条。可是严格说起来,说"从不歧视"的人,一定是在说谎。比如说,有的人会说,"我看xxx不爽",而这个"不爽",并非其"个人品质"导致的,仅仅是"身份"或者"归类",也有可能是一些并不存在因果关系的现象。先入为主的因素在这里起了作用。再比如说,大部分长辈都会觉得那些打舌洞、穿鼻环,身上纹着各色文字、青龙白虎的人,不是什么"好人",是"流氓",是"混混"……但是他们给出这样的定义,却多是没有,也不可能经过实际调查分析的。

所以,"事情要一码一码分开来看",情节有的严重有的轻微,一概而论只会走入极端。正视自己,也正视别人;容忍自己,也包容别人。每个人都会带着有色眼镜看别人,这很难避免,如果仅仅因此就过度上升到道义层面上来,这样的做法显然是过于粗暴的。

大部分国家都在努力消灭歧视,我觉得其中最重要的一个概念是"包容"(tolerance)。唯有包容程度高的国家和民族,才能有多样性,才有希望。否则,只是成为符合某一种特定价值观,某一种类型的人的天堂;而那些本能有杰出贡献,却因为某些无法被认可的非品质原因,被拒之门外,或者被政府、被舆论、被世俗打压。这无疑令人遗憾。然而,说包容容易,做起来困难。尤其是对于中华民族这样一个历史厚重深远,民俗文化中"传统"渗入骨髓的精神社会的背景来说。一方面许许多多的人都看到了哪些民族文化遗产的流失,另一方面却依然墨守成规,无法容忍那些不同的声音出现。事实上,在一个移民国家里,文化、人种差异巨大,很多情况大家都见怪不怪了,因此这种问题要好得多;但是对于文化非常纯粹和久远的的国家来说,要"包容",要尊重那些世俗观念之外的事实,其实是非常困难的事情。

正视歧视。中国人普遍脸皮薄,"佛为一炷香,人争一口气",其实在日常生活中,歧视的情况确实很难避免。那依然要一码一码地看问题,如果无可厚非的问题,自不应当放在心上。就平日接触的很多人来说,一来你的观点对别人其实远没那么重要,二来别人的看法对你其实也没那么重要。既然如此,顶多摇摇头,叹息一声,罢了罢了。可是如果觉得自己的尊严受到侵犯,当选择合适的方式回击。当然,这种情况其实极少遇到,因为大家都很忙,没有人会那么想和你过不去。

最后说一说教育。教育程度越高的人群中,歧视的情况越少出现。这一点在起码在中国和美国皆是如此。教育决定了一个民族的未来,这是千真万确的事。前面已经说到了包容,可是如何培养包容性呢?正是要靠教育。不能指望民众的观点态度在一夜之间发生改变,但是也许几代人,也许十几代人,逐渐塑造年轻人积极的世界观、价值观,却是让我们上一辈经历了文革和阶级斗争摧残后遗痛不已的民族,重新恢复成长的希望。


Read full article from 直面歧视 | 四火的唠叨


写在Gmail被墙后 | 四火的唠叨



写在Gmail被墙后 | 四火的唠叨

12月27号开始,Gmail服务被GFW屏蔽(具体时间可从Google的Transparency Report上获知),并且这种屏蔽方式是极其原始的IP地址屏蔽,这意味着,以往能够使用的POP3、IMAP、SMTP等等,所有的端口都被屏蔽了(请参阅维基百科词条)。换言之,今次的事件,可不只是简单的网页无法访问的问题,国内邮箱与Gmail互发邮件的能力,已经被彻底废掉了。如此地逆信息流动而为,如此地人为制造沟通障碍,和原有的网页请求关键字和时限数分钟的屏蔽方式相比,简单粗暴,毫无伪装,鲜血淋漓。

截止到目前,已有一些人发起了白宫请愿,上面也写得很明白"From Dec. 27, Chinese netizens are completely out of Gmail service, due to a new blockage from Great Firewall via IMAP and POP3 protocols.",只有在达到10万人的签名以后,才会得到白宫的正式回应。

微博上面许许多多的IT人都摆出了讽刺或者咒骂的态度,已经很少有人去正儿八经"批评"始作俑者了。但凡做技术的,崇尚信息自由和流动的,各路背景的程序员,在这一问题上,都站出来表明了类似的立场。你我都清楚,我们所憎恨的对象,已经不值得去"批评"了;所谓的代价与后果,已经不值得去"解释"了。知识分子,在现今的环境下,极少得到重视。这次的事件就是一典型例子。或许VPN是被默许的翻墙方式,亦或要阻止这样一簇人这样一种方式的成本太高,我们都还可以通过这样那样的办法跨国信息的隔阂。但是知识分子浪费在这上面的时间精力,是不会得到任何人在乎的。

从这件事情上面,我也有一些新的感触。其中之一便是,墙内的世界,比想象的要脆弱得多。Gmail于我的重要性之大,显然如今的可用性残疾令我无比失望。其二便是,能够使用"互联网技术",而非"局域网技术",已经成为一道实实在在的门槛。当互联网不易互联,互联网便不再亲民。

监管着的电影电视,监管着的书报媒体,唯有互联网,是不易控制的一方混沌。投入了多少人力物力(譬如新浪微博的专职内容审查人员,就有数千人),换来如今这种半残不残的局面。这堵当代的柏林墙,只见它愈来愈厚,不知还要耸立下去多久?难道"大中华局域网",真的指日可待了?


Read full article from 写在Gmail被墙后 | 四火的唠叨


大型互联网应用的技术选型和决策,10条成功与失败的记录 | 四火的唠叨



大型互联网应用的技术选型和决策,10条成功与失败的记录 | 四火的唠叨

作为以老版本为模子重做的解耦版本,这个大型互联网应用产品是从2009年中开始落地的。而我本人也是该版本的主创人员之一,到今日,团队已经发展到开发测试人数百人的大型互联网产品团队的规模,发布、割接和上线了许许多多个商用版本。

 

对架构的审视,对选型和设计的反思,不仅仅要在产品初创时期,更要在产品发展的整个过程中进行,团队做同类型产品的能力就是这样在不断总结和自我批评中成熟的。以下为个人观点,难免不对许多人的胃口,不过还是希望这些文字有足够到让人思考的价值。无论如何,对于这样一款产品,从如今的视角来解读它的历史故事,更别有一番风味。

 

―――――――――――――――――――――――――――――

 

5条成功的记录:

 

1、Portlet技术作为整个架构的核心。

这一条既是成功的记录,也是失败的记录。

Portlet给各个局点的不同定制版本带来了相当的页面定制灵活性,不懂jsp的管理员都可以按照自己的要求部署页面,通过简单的选择和拖动,将一个个内容丰富的频道展现出来。

另一方面,Portlet对于栏目的扩展和定制保留了相当的灵活性,尤其是对于潜在的互联网应用按照栏目维度保持伸缩性方面,留足了空间。

 

2、持久层选择了更加轻量级的iBatis,没有选择Hibernate。

事实证明,iBatis透明、简单,易于配置和使用,多数开发人员可以读透持久层的代码,擅长数据库的开发人员可以轻易地完成Oracle下SQL语句的调优,应用到iBatis的配置文件中去,并不需要太多ORM的技术积累,也不需要深厚的Hibernate调优技巧。

 

3、业务核心逻辑层得以抽象出来,独立成可以单独发布的API模块。

面对多种接入渠道,把核心业务通过API的行为抽取出来,给项目组带来的最大好处是:清晰的团队分工。

虽然API模块还不成熟,但是API的诞生和发展意味着可以让各个接入门户的开发和定制团队更聚焦在以展现为核心的工作上面,把业务代码的梳理交给专门的API团队去做。

从长远看,纯Java的API是干净、简洁和易于UT的,通过这种天然的方式隔离了持久层,也保护了核心业务的代码质量。

 

4、将功能的界面展示部分抽取成可重用的业务标签。

有人会对这个有异议,事实上,除了FreeMarker的性能确实让人不敢恭维以外,将界面的展示部分以标签的方式组件化带来的益处是很大的。

理想状况下,定制团队可以通过简单的标签插入、删减和修改,完成页面的定制工作,这比理解宏伟复杂的jsp页面,进行拷贝粘贴大法简单了不少。

 

5、基础设施稳定且有质量保障

基础设施包括日志、协议栈、License等等,大多稳定而且易于使用。

比如异常体系,整个异常体系给开发带来了自然和轻松的异常处理流程,开发人员只需要更关注核心流程,把错误流程交给运行时异常去处理;不同的异常捕获层次给最终页面的错误展示和归纳带来便捷。

也有遗憾的地方,比如错误码比较纠结,错误码是团队内部讨论经过激烈的斗争和妥协的结果,有些过于庞大和繁杂了,这似乎更验证了:软件工程不是明主选举。

 

―――――――――――――――――――――――――――――

 

5条失败的记录:

 

1、Portlet技术作为整个架构的核心。

这一条既是成功的记录,也是失败的记录。

Portlet的许多特性还远未得到适合的发挥,譬如Portlet状态的保持、远程聚合的能力等等,却给开发人员带来了许多困扰,譬如页面分解困难,Portlet Session和Portal Session的互异性,聚合流程性能问题等等,给开发人员定制手提出了更高的要求。

 

2、独立出基于Portlet核心的负责门户运营的Portal平台。

Portlet规范作为一种聚合展现行为的抽象,通过组件化这样一种独立平台的形式,将页面控制聚合流程从业务页面展现和业务流程处理中剥离出来,开发人员得以将更多的精力聚焦在业务开发上面。

我想这是它诞生的本意,但是实际上,却带来了聚合流程复杂,方法调用栈过深等问题,而门户定制的开发人员,也必须经过相当的培训才得以上手。

 

3、通过ajax方式聚合Portal位于不同war包内的管理台页面。

本意是想让不同的管理台页面随着不同的Portal接入渠道分离发布,在展现时在页面上进行简单集成。

但由于浏览器的安全机制和对于不同域的会话独立管理的机制,使得它像恶魔一般被引进来,带来的不仅仅是定制的困难,开发人员理解的困难,还有一些因会话无法统一而导致的在不同域页面间信息传递时难以解决的问题。

 

4、保留XDIME、WML和XHTML三套WAP的模板页面。

当然也许这有一些人为无法控制的因素在里面。

XDIME页面的目的就是经过终端适配组件转换成适合手机的WML和XHTML页面的,而由于局点或某些历史原因,WML和XHTML还无法被干脆地摒弃掉,无论是一种主动的决策还是迫于无奈,带来的问题就是页面模板数量增加了两倍,给开发和测试带来了大量的工作量。

最终,WML和XHTML模板还是被抛弃了,只保留了XDIME一套模板。

 

5、缺少一套简易的和可管理的UI框架。

前端开发是整个产品的瓶颈,尽管页面并不非常复杂,前端的混乱却已经带来了诸多问题,这些问题主要暴露在产品定制和最终的用户细节体验环节上。互联网产品是否专业,很大程度上是由产品的前端团队所决定的。

依据不同的团队级别、不同的前端展示要求,需要定制不同的UI框架。由展现的简易性,而且需要定制的基线版本,决定了我们的UI框架应该简单;并且由于开发成员普遍前端能力欠佳,决定的我们的UI框架应当便于控制和管理,不应暴露过于复杂的界面行为给普通开发人员。


Read full article from 大型互联网应用的技术选型和决策,10条成功与失败的记录 | 四火的唠叨


The Netflix Tech Blog: Linux Performance Analysis in 60,000 Milliseconds



The Netflix Tech Blog: Linux Performance Analysis in 60,000 Milliseconds

Linux Performance Analysis in 60,000 Milliseconds You login to a Linux server with a performance issue: what do you check in the first minute? At Netflix we have a massive EC2 Linux cloud, and numerous performance analysis tools to monitor and investigate its performance. These include Atlas for cloud-wide monitoring, and Vector for on-demand instance analysis. While those tools help us solve most issues, we sometimes need to login to an instance and run some standard Linux performance tools. In this post, the Netflix Performance Engineering team will show you the first 60 seconds of an optimized performance investigation at the command line, using standard Linux tools you should have available. First 60 Seconds: Summary In 60 seconds you can get a high level idea of system resource usage and running processes by running the following ten commands. Look for errors and saturation metrics, as they are both easy to interpret, and then resource utilization.

Read full article from The Netflix Tech Blog: Linux Performance Analysis in 60,000 Milliseconds


Twitter vs. Weibo: 8 Things Twitter Can Learn From The Latter - Hongkiat



Twitter vs. Weibo: 8 Things Twitter Can Learn From The Latter - Hongkiat

I was a dedicated user of Twitter for around 2 years, but I decided to convert to Sina Weibo recently. I'm ultimately satisfied with the Sina Weibo, and in this post I'm going to list out 8 particular things that Twitter can really learn from Sina Weibo, which also serve as possible reasons that why Sina Weibo can gain 140 million users in just less than 2 years of its realms, beating all other China microblogging services.

Note: Wanting to explore Sina Weibo but don't know anything about Chinese language? No worries, here's a complete 20 pages guide from Digicha to help you understand all essential basics about Sina Weibo! Account set-up guide here.

1. Threaded Comment

Apparently most successful microblogging services in China, such as Tencent Weibo and Sina Weibo, focus heavily on making user's social feedback easier in their own services. The reason is pretty easy, we human are social animal, therefore we care about what others think about us, and threaded comment is really a big plus in making the entire feedback tracking process easier.


Read full article from Twitter vs. Weibo: 8 Things Twitter Can Learn From The Latter - Hongkiat


(10) What's the difference between sharding and partition? - Quora



(10) What's the difference between sharding and partition? - Quora

Partitioning is a general term used to describe the act of breaking up your logical data elements into multiple entities for the purpose of performance, availability, or maintainability. 

Sharding is the equivalent of "horizontal partitioning".  When you shard a database, you create replica's of the schema, and then divide what data is stored in each shard based on a shard key.  For example, I might shard my customer database using CustomerId as a shard key - I'd store ranges 0-10000 in one shard and 10001-20000 in a different shard.  When choosing a shard key, the DBA will typically look at data-access patterns and space issues to ensure that they are distributing load and space across shards evenly. 

"Vertical partitioning" is the act of splitting up the data stored in one entity into multiple entities - again for space and performance reasons.  For example, a customer might only have one billing address, yet I might choose to put the billing address information into a separate table with a CustomerId reference so that I have the flexibility to move that information into a separate database, or different security context, etc.   

To summarize - partitioning is a generic term that just means dividing your logical entities into different physical entities for performance, availability, or some other purpose.  "Horizontal partitioning", or sharding, is replicating the schema, and then dividing the data based on a shard key.  "Vertical partitioning" involves dividing up the schema (and the data goes along for the ride). 

Final note:  you can combine both horizontal and vertical partitioning techniques - sometimes required in big data, high traffic environments.

Read full article from (10) What's the difference between sharding and partition? - Quora


程序員不得不知道的技術面試資料大全 : 歌穀穀



程序員不得不知道的技術面試資料大全 : 歌穀穀

  • GeeksforGeeks.org 非常著名的漏題網站之一。上面會時不時的有各種公司的面試真題漏出。有一些題也會有解法分析。

  • CareerCup.com CC150作者搞的網站,也是著名的漏題網站之一。大傢會在上面討論各個公司的面試題。

  • Glassdoor.com 一個給公司打分的網站,類似yelp的公司版。會有一些人在上面討論面試題,適合你在面某個公司的時候專門去看一下。

  • themianjing.com 面經網。應該是個人經營的一個積累面經的網站。面經來源主要是一畝三分地,mitbbs之類的地方。

  • 一畝三分地

  • mitbbs.com jobhunting版。北美華人找工作必上。


在線OJ及部分題解

  • LintCode – 專門提供面試題在線評測的OJ,篩選比較方便,還可以在source處選擇cc150或者其他來源的題,有階梯訓練系統,不用擔心不知道從哪兒開始刷題。目前會根據系統locale選擇中文或者英文,評判時也比leetcode快,總之是比較贊啦。

  • LeetCode Online Judge – 找工作方面非常出名的一個OJ,相應的題解非常多

  • soulmachine/leetcode – 含C++和Java兩個版本的題解

  • Woodstock Blog – IT,算法及面試。有知識點及類型題總結,特別贊

  • Acm之傢,專業的ACM學習網站 – 各類題解

  • 九章算法LeetCode / LintCode 題解。上面的題解是專業老師提供的,代碼質量很不錯。

  • 水中的魚http://fisherlei.blogspot.com/有很多LeetCode的題解。

論壇博客

  • 刷題 | 一畝三分地論壇 – 時不時就會有驚喜放出。

  • VisuAlgo – visualising data structures and algorithms through animation相當碉堡的數據結構和算法可視化。

  • Data Structure Visualization – 同上,非常好的動畫演示!!涵蓋瞭常用的各種數據結構/排序/算法。

  • POJ的部分題解 – Category: POJ | Beeder's Blog

  • 專欄:算法筆記——《算法設計與分析》 – CSDN上對《算法設計與分析》一書的學習筆記。

  • 算法練習 | billryan – 本文協同作者yuanbin的刷題總結和筆記,求大神們輕拍,求大神們輕拍

書籍推薦

  • Algorithm Design (豆瓣)

  • The Algorithm Design Manual, 作者還放出瞭自己上課的視頻和slides – Skiena's Audio Lectures,The Algorithm Design Manual (豆瓣)

  • 大部頭有 Introduction to AlgorithmTAOCP

  • Cracking The Coding Interview. 著名的CC150,Google, Mircosoft, LinkedIn 前HR離職之後寫的書,從很全面的角度剖析瞭面試的各個環節和題目。之所以叫CC150就是有150道面試題,除瞭算法數據結構等題以外,還包含OO Design, Database, System Design, Brain Teaser等類型的題目。準備北美面試的同學一定要看。

  • 劍指Offer。英文版叫Coding Interviews. 作者是何海濤(Harry He)。Amazon上可以買到。有大概50多題,題目的分析比較全面,會從面試官的角度給出很多的建議和show各種坑。

  • 進軍矽谷 — 程序員面試揭秘。有差不多150題。


簡介


九章算法,幫助更多中國人找到好工作!

Read full article from 程序員不得不知道的技術面試資料大全 : 歌穀穀


Police: Mizzou teaching assistant became violent with relative who didn't wear hijab | Fox News



Police: Mizzou teaching assistant became violent with relative who didn't wear hijab | Fox News

Published November 29, 2015 Youssif Omar is accused of dragging a relative out of school because she wasn't wearing a hijab. (Police handout) A Benghazi native who recently served as a teaching assistant at the University of Missouri was arrested Wednesday on suspicion of child abuse after police said he "very violently" pulled a 14-year-old female relative out of school by her hair because she wasn't wearing a Muslim headscarf, the Columbia Tribune reported. Youssif Z. Omar pulled the female relative down a flight of stairs and outside of Hickman High School on Tuesday when he noticed she was not wearing a hijab, Officer Latisha Stroer said in an email to the Tribune. Omar is also accused of slapping the girl's face, Stroer said. Omar has posted a $4,500 bond and was released from Boone County Jail. Omar is listed on the University's website as a graduate teaching assistant of Arabic and the managing editor of the undergraduate journal "Artifacts.

Read full article from Police: Mizzou teaching assistant became violent with relative who didn't wear hijab | Fox News


问下g-o-o-g-l-e大神们一个问题。【一亩三分地论坛面经版】 - Powered by Discuz!



问下g-o-o-g-l-e大神们一个问题。【一亩三分地论坛面经版】 - Powered by Discuz!

9月20多号面的..很早之前就被拒了.但是有一个问题一直困扰着我.所以来这请教g-o-o-g-l-e大神们我知道full time onsite的时候。面试官会拍照你的code。然后所有的feedback弄成一个package给hc来审。
因为实习只有2面。面试官是不是也是会把在document里所有写的code会交给hc来审?因为面试官提出新的feature,所以我想要改document里正确的code的时候。面试官说不要再上面改。在最下面写全新的。
还有。。我面试的时候。。第一面和第二面的第二题都是一样的(但是第二面的第二题做完了之后。面试官又提出了新的feature based on that question。)。我当时傻逼没说。是不是hc直接挂掉那些碰到同样题目但是不提醒面试官的那些面试者?
第二轮的时候印度mm问了我很多big o 问题。我都问他了。我有没有回答正确。她说是的。我当时面完感觉非常好。开车直接和女朋友再+室友直接开车1个小时去法拉盛吃饭。。几个星期后。却迎来hr的拒绝。。hr嘴巴也很严。一直说不能提供feedback。
我还专门去问了下hr。是不是遇到同样的问题要告诉面试官。hr说建议要讲。

Read full article from 问下g-o-o-g-l-e大神们一个问题。【一亩三分地论坛面经版】 - Powered by Discuz!


NoBlogDefFound: Which thread executes CompletableFuture's tasks and callbacks?



NoBlogDefFound: Which thread executes CompletableFuture's tasks and callbacks?

November 30, 2015 CompletableFuture Running tasks This is the fundamental part of the API. There is a convenient supplyAsync() ExecutorService.submit() The problem is, CompletableFuture s, all parallel streams and all applications deployed on the same JVM (if you are unfortunate to still use application server with many deployed artifacts). This hard-coded, unconfigurable thread pool is completely outside of our control, hard to monitor and scale. Therefore you should always specify your own Executor ExecutorService pool = Executors.newFixedThreadPool(10); final CompletableFuture future = CompletableFuture.supplyAsync(() -> { //... }, pool); But that is just the beginning... Callbacks and transformations CompletableFuture String Who, exactly, invokes the s.length() code? Frankly, my dear developers, we don't give a damn [1] . As long as the lambda expression inside all of the operators like thenApply is cheap, we don't really care who calls it.

Read full article from NoBlogDefFound: Which thread executes CompletableFuture's tasks and callbacks?


Buttercola: Zenefits: Two Minus



Buttercola: Zenefits: Two Minus

Zenefits: Two Minus

在一个整数数组中(有重复元素)找出有多少对,满足条件:他们的差等于k。例如[1,5,5,2,4,6,7],k=3,满足条件的对子有[1,4], [2,5], [2,5](注意有两个5),[4,7],所以程序返回4。这题比较tricky的地方在于k=0的情况需要另外考虑一下。

Solution:
1. Sort the array
2. Maintain two pointers, lo and hi, points to index 0 and 1, respectively.
3. If nums[hi] - nums[lo] == k. Add into result. Then we need to check the duplicates for lo + 1, lo + 2. .... If no duplicates, hi++. 
4. if nums[hi] - nums[lo] > k. lo++
5. If nums[hi] - nums[lo] < k, hi++.

Read full article from Buttercola: Zenefits: Two Minus


Buttercola: Zenefits: Middle element



Buttercola: Zenefits: Middle element

Zenefits: Middle element

在一个整数数组中(无重复元素)找出一个元素,使得其大于所有他前面的数,并且小于所有他后面的数,返回其下标。例如[4,1,2,6,10,7]中,6满足条件,返回下标3。若有多个满足条件,返回一个即可。若无,返回-1

Solution:
Maintain two arrays, left[] and right[]. The left[i] stores the biggest element prior to i. The right[i] stores the minimum value after i. 

Then for each element in array nums[i]. If it is greater than the biggest element left to i, and smaller than the smallest element after i. Then nums[i] must be the intermediate element.

Read full article from Buttercola: Zenefits: Middle element


Buttercola: Zenefits: Minimum Cost



Buttercola: Zenefits: Minimum Cost

Zenefits: Minimum Cost

一堆商品,买一个可以送一个,但送的那个的价格必须小于买的那个的价格(强调一下,不能等于)。给定商品总数n和每个商品的价格,求得到全部商品的最少开销。 例如:4个商品价格为[5, 4, 3, 3],最优解为9,即买5和4,送3和3。 
两个test case: [100, 99, 98, 1, 1, 1], [100, 99, 98, 98, 97, 97, 97, 97]

Read full article from Buttercola: Zenefits: Minimum Cost


我的算法路 (1)_peking2_新浪博客



我的算法路 (1)_peking2_新浪博客

既然有了博客就想多写一点。离上一次Google onsite差不多正好一年。那个时候心情是悲伤的,心里绝望的。后来才知道我并不孤独,火鸡大哥也经历过类似的感受。当时曾短暂的失去了方向,但是半年以后我怀着非常感激的心理来面对这次失败。

这次失败真正的触动了我,因此我开始了一段比较全面的思考,我做了一个几年以来都犹豫不决的决定,并且给自己定下了一年的期限来完成,否则的话我会选择另外一条路去走。我做了几个重要的决定,学习Java,潜心学习算法和练习编程,找到自信。

再往下继续之前我想谈谈我对面试的理解过程。可能由于我面试公司的档次比较低,以前在国内面试基本上就是聊聊天,现在想起来也就是在华为面试出现过一道算法题,就是小孩站成一个圈数数out的问题。后来有机会在北京去微软,Google面试的时候才发觉他们的重点就在算法题上。当时很幼稚的认为能够解决就算很不错了,因此基本上给出的都是brute force的解法,但是发觉他们马上会要求自己进行优化,我基本就stuck了。因此这种算法面试在我的心理蒙上了一层阴影,长期以来不敢触及他们。后来有关系不错同事在外边找工作,闲聊的时候他介绍给我了PIE和CC150这两本书。当时他的意思是面试的算法题都是这两本书里边的,学好了面试就没啥问题了。因此,我开始看这两本书,学习如何优化以及面试题的各种trick。基本扫了扫这两本书以后,并没有怎么做练习,当时的理解就是面试能说出最优解就可以了。在这种理解之下开始了仓促的面试,并且不断的得到据信,同时也开始混这个论坛。lolhaha是第一个尖锐的指出我的准备十分的不足,而我当时却没有意识。起初把失败归于了语言,我刚开始使用C语言,很快就发觉面试十分的不方便,因此匆忙改到了C#,短暂练习了1个多星期的时候由于很不熟练fail了一个面试,但是一个月以后情况开始好转,拿到了一个offer,很接近另外一个offer。

转到C#不到两个月fail了G。其实当时感觉已经发挥出自己最好的状态了。因此自己很清楚的知道不下一番功夫的话看来是不行了。在我准备面试之前我有一定的数据结构知识,但是算法的知识几乎为零。我感觉我大学根本就没有学什么binary search, 更不要说DP了。因此理论基础非常的差。论坛上看到的很多很多对我来说都是新的术语。

面G之前,从yangcheng那里知道了topcoder。在我决定了转Java,学算法之后,我就正式的开始了我的算法路。现在回想起来我也非常怀念那段时光。

Read full article from 我的算法路 (1)_peking2_新浪博客


San Fransisco Onsite面经 - ┅☆心随风飞 - 博客频道 - CSDN.NET



San Fransisco Onsite面经 - ┅☆心随风飞 - 博客频道 - CSDN.NET

财大气粗的Dropbox不愧为dream company,每天可以报销伙食费90美元,是我面过的公司给的最高的,并且还可以额外住一天酒店并报销100刀的观光费用。HR还很贴心的列出一堆景点,以供游玩。里面的工作环境很赞,食堂不错,白人比例高,由于靠海,view也不错,可以看海边日落。

需要注意的一点是,在代码写完后,不少人会拍个照,所以代码还是写工整一点比较好,这个一开始不知道,字迹潦草了点有些吃亏。

第一轮问research和behavioral questions。

第二轮是Game of life,一个二维数组里,每个元素有生和死两个状态,根据周围元素的生死情况按规则进行状态转换。Follow up就是对大的file操作,而非内存中的数组。基本属于纯实现题目,很简单。

第三轮 实现web crawler。follow up是网页抓取和网页解析的异步实现。其实就是异步实现BFS。我用了三个queue去实现,除开一个本身BFS需要的queue,另外用了两个BlockedQueue,不知道对不对。

第四轮实现两个函数,int allocate()和void release(intid),每调用一次allocate返回的id需要unique,为1到N之间的一个整数。如果release以后,就可以继续被allocate。之前用array+hashmap,达到O(1)时间和O(N)空间。后来被告知空间用得太多,map空间效率低,最后用了bitmap。这题其实和实现文件系统的metadata区域比较类似,不过最后居然是用时间换空间,有点让我诧异。

第五轮系统设计:对分布式的server,获取对每台server各种信息汇总后的time series。非常的open-ended,反正把各种系统设计原理都用上就行了。

加吃饭一共面了6个小时,还有些题目不记得了。。。


Uber:

最大感觉是公司扩招得很厉害,但是体制的改进以及设施的更新都没有跟上,很多地方都不成熟。面试过程其实也不怎么规范,还要求带上自己的laptop。感觉由于快ipo了,逼格非常的高,题目比起FLAG难不少。

第一个面试官是烙印,感觉挺不友好的,一开始讨论项目经历的时候就各种不以为然。然后40分钟问了四个问题,根本没时间做完。第一题是LeetCode原题,next permutation,秒之。不过烙印一开是怀疑我的思路,后来费不少力气才说服。第二题是实现hash map,指明非要用chaining的方法,CC150上应该有,也秒之。最奇葩的是,刚开始写了一部分代码,后来烙印觉得我代码排版不够好,于是给我擦了,中间划了一条线,让我用双栏排版重写。(总共就只有一块很窄的竖着放的白板,白板上面1/3的空间其实浪费掉了,因为手根本够不着)。无奈就费了一些时间重写代码。之后让我实现concurrent map,有点实现读者写者问题的感觉,没时间写完。还剩5分钟的时候又问如何在chaining的机制下实现load factor,实在不会,后来发现答案其实解法刁钻。其实三哥也就进来了一个月,感觉牛逼哄哄的,做题的时候一直在旁边指手画脚,比如算法设计的时候一开始很容易声明一些多余的参数,等题目探索完了其实往往也就一目了然,自然最后会去掉,可是三哥中途非要指着说认为某参数不必要,严重影响了自己探索问题的乐趣和连续性。另外我也严重怀疑他如果不看标答,是否能够一开始就知道某个参数是最后不必要的,

第二个人就一道题目,感觉很难,想了40分钟才想出来一个解。要求设计一个数据结构,满足insert(int key),remove(int key)和int getMostFrequentKey()。对于同一个key,每次被insert,计数加1;每次被remove,计数减1;然后需要取最大count的key。要求所有操作都是O(1)复杂度。

这题首先通过尝试排除掉map+maxHeap的组合,然后又联想streaming max等各种尝试。后经过提示数据结构需要保持部分的排序性质(如果保证完全排序,插入删除操作是不可能O(1)的)。考虑到需要统计的count是整数,我就想到了bucket sort,另外联系类似LRU设计思想(doubly linked list + hash map),设计出了如下结构:

class Node {

         int key;

         int count;

class Bucket {

         Set<Node>set;        // All the nodes with equal count.

         Bucket prev;

         Bucket next;

}

Bucket head;

HashMap<Integer: key, Node: node>

虽然这个解被证明是可行的,但总感觉自己的设计有点过于复杂。做完这题后,脑力废去大半。。。 

第三轮设计一个游戏,从起点到终点有两条不重合的长度相等的路径,每沿着当前路径走一步,需要耗费一定体力,如果切换到另一路径的相同位置,也需要耗费一些体力。每次只能继续往前或者切换路径,要求打印出消耗最少体力的路径。其实就是一个一般难度的DP问题,不过这个年代还考DP的真不多了。后来讨论了functional programming,要求给一个链表和一个filter函数指针,输出一个filter后的新链表,只能用递归写。其实iterative转recursive也不难。之后跟我讨论kmeans的并行实现,然后让我猜另一种clustering算法。我猜了hierarchical clustering和density-based,结果都没猜对,最后告诉我是想让我答EM算法。狂汗啊,我压根就没有把EM放到clustering分类里面。最后跟我聊了下最大似然估计。统计方面的东西自己不怎么懂,有些郁闷:自己明明面的infrastructure team,可是这货怎么总往machine learning上聊呢?这new grad要求也太全面了。。。

第四个人主要聊背景是否跟team match,题目只出了个power set,算是最后放松了下。


Twitter:

问题都不难,这里就不透露太多细节了。

1.      质数问题变种。

2.      各种sampling的问题,大数据的,分布式的。

3.      LeetCode原题:Clone alinked list with random pointers。

4.      设计如何分布式存储tweets,包括保持排序性质什么的。

5.      字符串匹配问题,都还没涉及到什么fancy的方法例如KMP什么的时间就完了。

6.      设计一个Timer class。

 估计由于我的项目经历,很多问题最后都延伸到了分布式实现和用MapReduce实现。


Read full article from San Fransisco Onsite面经 - ┅☆心随风飞 - 博客频道 - CSDN.NET


leetcode Burst Balloons - 细语呢喃



leetcode Burst Balloons - 细语呢喃

leetcode Burst Balloons

Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by array nums. You are asked to burst all the balloons. If the you burst balloon i you will get nums[left] * nums[i] * nums[right] coins. Here left and right are adjacent indices of i. After the burst, the left and right then becomes adjacent.

Find the maximum coins you can collect by bursting the balloons wisely.

Note:
(1) You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them.
(2) 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100

Example:

Given [3, 1, 5, 8]

Return 167

题意:

给定n个气球。每次你可以打破一个,打破第i个,那么你会获得nums[left] * nums[i] * nums[right]个积分。 (nums[-1] = nums[n] = 1)求你可以获得的最大积分数

思路:

一开始想dp[i][j] 为第 i 天打破第j 个气球,然后枚举上一轮打破的为第k个气球 dp[i][j] =max( dp[i �C 1][k] + left * nums[j] * right) (当然要记录都打了哪些O) 复杂度 O(n^3) 然而TLE (python)

看了discuss是dp[i][j]为打破的气球为i~j之间。

我们可以想象:最后的剩下一个气球为i的时候,可以获得的分数为:nums[-1]*nums[i]*nums[n].

那么介于i,j之间的x,有: dp[i][j] = max(dp[i][j], dp[i][x �C 1] + nums[i �C 1] * nums[x] * nums[j + 1] + dp[x + 1][j]);

 

C++跑1330MS  ,JAVA 187MS ,python TLE 。。。。python TLE 可以理解,但C++比JAVA这题还慢这不合理。。。。可能是vector太慢?


Read full article from leetcode Burst Balloons - 细语呢喃


Median of Integer Stream - 我的博客 - ITeye技术网站



Median of Integer Stream - 我的博客 - ITeye技术网站

Given a stream of unsorted integers, find the median element in sorted order at any given time. So, we will be receiving a continuous stream of numbers in some random order and we don't know the stream length in advance. Write a function that finds the median of the already received numbers efficiently at any time. We will be asked to find the median multiple times. Just to recall, median is the middle element in an odd length sorted array, and in the even case it's the average of the middle elements.

 

This is a data structure question. We will insert the received numbers into such a data structure that we'll be able to find the median very efficiently. Let's analyse the possible options.

 

We can insert the integers to an unsorted array, so we'll just append the numbers to the array one by one as we receive. Insertion complexity is O(1) but finding the median will take O(N) time, if we use the Median of Medians algorithm that I described in my previous post. However, our goal is to find the median most efficiently, we don't care that much about insertion performance. But this algorithm does the exact opposite, so unsorted array is not a feasible solution.

 

What about using a sorted array? We can find the position to insert the received number in O(logN) time using binary search. And at any time if we're asked for the median we can just return the middle element if the array length is odd, or the average of middle elements if the length is even. This can be done in O(1) time, which is exactly what we're looking for. But there's a major drawback of using a sorted array. To keep the array sorted after inserting an element, we may need to shift the elements to the right, which will take O(N) time. So, even if finding the position to insert the number takes O(logN) time, the overall insertion complexity is O(N) due to shifting. But finding the median is still extremely efficient, constant time. However, linear time insertion is pretty inefficient and we would prefer a better performance.

 

Let's try linked lists. First unsorted linked list. Insertion is O(1), we can insert either to the head or tail but we suffer from the same problem of unsorted array. Finding the median is O(N). What if we keep the linked list sorted? We can find the median in O(1) time if we keep track of the middle elements. Insertion to a particular location is also O(1) in any linked list, so it seems great thus far. But, finding the right location to insert is not O(logN) as in sorted array, it's instead O(N) because we can't perform binary search in a linked list even if it is sorted. So, using a sorted linked list doesn't worth the effort, insertion is O(N) and finding median is O(1), same as the sorted array. In sorted array insertion is linear due to shifting, here it's linear because we can't do binary search in a linked list. This is a very fundamental data structure knowledge that we should keep at the top of our heads all the time.

 

Using a stack or queue wouldn't help as well. Insertion would be O(1) but finding the median would be O(N), very inefficient.

 

What if we use trees? Let's use a binary search tree with additional information at each node, number of children on the left and right subtrees. We also keep the number of total nodes in the tree. Using this additional information we can find the median in O(logN) time, taking the appropriate branch in the tree based on number of children on the left and right of the current node. However, the insertion complexity is O(N) because a standard binary search tree can degenerate into a linked list if we happen to receive the numbers in sorted order.

 

So, let's use a balanced binary search tree to avoid worst case behaviour of standard binary search trees. In a height balanced binary search tree (i.e. AVL tree) the balance factor is the difference between the heights of left and right subtrees. A node with balance factor 0, +1, or -1 is considered to be balanced. However, in our tree the balance factor won't be height, it is the number of nodes in the left subtree minus the number of nodes in the right subtree. And only the nodes with balance factor of +1 or 0 are considered to be balanced. So, the number of nodes on the left subtree is either equal to or 1 more than the number of nodes on the right subtree, but not less. If we ensure this balance factor on every node in the tree, then the root of the tree is the median, if the number of elements is odd. In the even case, the median is the average of the root and its inorder successor, which is the leftmost descendent of its right subtree. So, complexity of insertion maintaining balance condition is O(logN) and find median operation is O(1) assuming we calculate the inorder successor of the root at every insertion if the number of nodes is even. Insertion and balancing is very similar to AVL trees. Instead of updating the heights, we update the number of nodes information.

 

Balanced binary search trees seem to be the most optimal solution, insertion is O(logN) and find median is O(1). Can we do better? We can achieve the same complexity with a simpler and more elegant solution. We will use 2 heaps simultaneously, a max-heap and a min-heap with 2 requirements. The first requirement is that the max-heap contains the smallest half of the numbers and min-heap contains the largest half. So, the numbers in max-heap are always less than or equal to the numbers in min-heap. Let's call this the order requirement. The second requirement is that, the number of elements in max-heap is either equal to or 1 more than the number of elements in the min-heap. So, if we received 2N elements (even) up to now, max-heap and min-heap will both contain N elements. Otherwise, if we have received 2N+1 elements (odd), max-heap will contain N+1 and min-heap N. Let's call this the size requirement.

 

The heaps are constructed considering the two requirements above. Then once we're asked for the median, if the total number of received elements is odd, the median is the root of the max-heap. If it's even, then the median is the average of the roots of the max-heap and min-heap. Let's now analyse why this approach works, and how we construct the heaps.

 

We will have two methods, insert a new received number to the heaps and find median. The insertion procedure takes the two requirements into account, and it's executed every time we receive a new element. We take two different approaches depending on whether the total number of elements is even or odd before insertion.

 

Let's first analyze the size requirement during insertion. In both cases we insert the new element to the max-heap, but perform different actions afterwards. In the first case, if the total number of elements in the heaps is even before insertion, then there are N elements both in max-heap and min-heap because of the size requirement. After inserting the new element to the max-heap, it contains N+1 elements but this doesn't violate the size requirement. Max-heap can contain 1 more element than min-heap. In the second case, if the number of elements is odd before insertion, then there are N+1 elements in max-heap and N in min-heap. After we insert the new element to the max-heap, it contains N+2 elements. But this violates the size constraint, max-heap can contain at most 1 more element than min-heap. So we pop an element from max-heap and push it to min-heap. The details will be described soon.

 

Now let's analyse the order requirement. This requirement forces every element in the max-heap to be less than or equal to all the elements in min-heap. So the max-heap contains the smaller half of the numbers and the min-heap contains the larger half. Note that by design the root of the max-heap is the maximum of the lower half, and root of the min-heap is the minimum of the upper half. Keeping these in mind, we again take two different actions depending on whether the total number of elements is even or odd before insertion. In the even case we just inserted the new element to the max-heap. If the new element is less than all the elements in the min-heap, then the order constraint is satisfied and we're done. We can perform this check by comparing the new element to the root of the min-heap in O(1) time since the root of the min-heap is the minimum. But if the new element is larger than the root of min-heap then we should exchange those elements to satisfy the order requirement. Note that in this case the root of the max-heap is the new element. So we pop the the root of min-heap and insert it to max-heap. Also pop the root of max-heap and insert it to min-heap. In second case, where the total number of elements before insertion is odd, we inserted the new element to max-heap, then we popped an element and pushed it to the min-heap. To satisfy the order constraint, we pop the maximum element of the max-heap, the root, and insert it to the min-heap. Insertion complexity is O(logN), which is the insertion complexity of a heap.

 

That is exactly how the insertion procedure works. We ensured that both size and order requirements are satisfied during insertion. Find median function works as follows. At any time we will be queried for the median element. If the total number of elements at that time is odd, then the median is the root of the max-heap. Let's visualize this with an example. Assume that we have received 7 elements up to now, so the median is the 4th number in sorted order. Currently, max-heap contains 4 smallest elements and min-heap contains 3 largest because of the requirements described above. And since the root of the max-heap is the maximum of the smallest four elements, it's the 4th element in sorted order, which is the median. Else if the total number of elements is even, then the median is the average of the roots of max-heap and min-heap. Let's say we have 8 elements, so the median is the average of 4th and 5th elements in sorted order. Currently, both the max-heap and min-heap contain 4 numbers. Root of the max-heap is the maximum of the smallest numbers, which is 4th in sorted order. And root of the min-heap is the minimum of the largest numbers, which is 5th in sorted order. So, the median is the average of the roots. In both cases we can find the median in O(1) time because we only access the roots of the heaps, neither insertion nor removal is performed. Therefore, overall this solution provides O(1) find heap and O(logN) insert.

 

A code is worth a thousand words, here is the code of the 2-heaps solution. As you can see, it's much less complicated than it's described. We can use the heapq module in python, which provides an implementation of min-heap only. But we need a max-heap as well, so we can make a min-heap behave like a max-heap by multiplying the number to be inserted by -1 and then inserting. So, every time we insert or access an element from the max-heap, we multiply the value by -1 to get the original number:


Read full article from Median of Integer Stream - 我的博客 - ITeye技术网站


Scheduling Problem (greedy algorithm) | Hello World



Scheduling Problem (greedy algorithm) | Hello World

Both of the questions is attacked by using the greedy algorithm

First Question:
If you have only one room, what is the maximum number of meetings you can scheduled into that room.

Solution:
1. sort the meetings by finishing time, this is because we greedily choose the meeting that finishes first.
2. go through all the meetings in order of finishing time, schedule the meeting into the room if the room is not occupied at its start time, and increase the count by one.
3. no of count will be the max number of meetings you can schedule into the room.

We need to prove that the greedy algorithm is correct (choosing the meeting that finishes first can result in a optimal solution) assume there is another schedule S' that schedules more meetings (k + 1) then the solution S (k solutions). Then at some point the S' must scheduled some meeting that tm' ends before the tm scheduled by S. But as we know that since S scheduled meeting that finishes first so the mth meeting must finishes no later than mth scheduled by S'. which is a contradiction.

Second Question:
You are given a set of meetings with start time and end time, what is the minimum number of meeting rooms you need to have to hold all the meetings.

The brute force method is to compare every start and end time one by one, and that will take a O(n^2) run time where n is the number of meetings to find out the minimum number of meeting rooms.

A better solution using the greedy approach
1. We sort the meetings by start time
2. Then step through all the meetings in order of start time, keep a set of meeting rooms, if all the rooms are occupied, then we schedule a new room. To check all the previous scheduled meetings, we keep a priority queue by finishing time of all the scheduled meetings. Assume there are d number of rooms, then checking takes logd time.
3. count the number of rooms.

The run time will be nlogn + nlogd = nlogn time.

class Meeting {
int startTime;
int endTime;
public Meeting(int s, int e) {
startTime = s;
endTime = e;
}
}

class solution {
public int minRoom(ArrayList meetings) {
Collections.sort(meetings, new Comparator () {
@Override
public int compare(Meeting m1, Meeting m2) {
if (m1.endTime > m2.endTime)
return 1;
if (m1.endTime < m2.endTime)
return -1;
return 0;
}
}
int max = 1;

}
}

Feasible problem:
Given a serial of jobs that contains a processTime and a deadLine, check if you can schedule them so that all the Jobs are finished before deadline.

1.Sort the jobs by deadline.
2. Schedule the job by the order of deadline, see if any job can not finish before deadline, if so, it is not possible, otherwise, the problem is feasible.

Minimum Lateness problem:
Assume we have a serial of jobs that contains a processTime and a deadLine, the lateness is the time between the finish time and the deadline of the job, if the job is finished before the deadline, then the lateness is 0. How do you schedule the job to minimize the total lateness?

1. Sort the jobs in deadline
2. step through all the elements in the order of the deadline, pick the earliest deadline and sums up the lateness if exist.
3. return the lateness

Third follow up question, what if each meeting has a priority, how can we schedule a set of meeting that has the largest priority sum given one meeting room?

1. Sort the meetings according to the finish time (like the first question)
2. Try schedule meeting starting from the first one greedily and record the total priority, mark those meetings that has been scheduled
3. Pass through all the meetings and schedule any meeting that has not been marked in previous schedules. record the max total priority


Read full article from Scheduling Problem (greedy algorithm) | Hello World


Facebook interview - Suffix Array Order - 我的博客 - ITeye技术网站



Facebook interview - Suffix Array Order - 我的博客 - ITeye技术网站

首先定义了suffix string 或者说suffix arrary
如果有个数组是 int[] text = {10, 20, 30, 25}
那么 suffix[0] = {10, 20, 30, 25}
           suffix[1] = {20, 30, 25}
           suffix[2] = {30, 25}
           suffix[3] = {25}
如果对这些数组进行lexical order 的排序,我们可以得到
suffix[0] < suffix[1] < suffix[3] < suffix[2]
问题是:
    input: int[] text
    output: int[] suffix_array_order
e.g.
input: int[] text = {10, 20, 30, 25}
output: int[] suffix_array_order = {0, 1, 3, 2}

 

Solution:

注意: Arrays.sort(T[], Comparator)只能用于排序对象数组,不能用于排序int, long之类的原始值数组!


Read full article from Facebook interview - Suffix Array Order - 我的博客 - ITeye技术网站


董的博客 >> 系统设计面试题思路综述



董的博客 » 系统设计面试题思路综述

在正式介绍基础知识之前,我先罗列几个常见的系统设计相关的笔试面试题。

(1) 要求设计一个DNS的Cache结构,要求能够满足每秒5000以上的查询,满足IP数据的快速插入,查询的速度要快。(题目还给出了一系列的数据,比如:站点数总共为5000万,IP地址有1000万,等等)

(2) 有N台机器,M个文件,文件可以以任意方式存放到任意机器上,文件可任意分割成若干块。假设这N台机器的宕机率小于1/3,想在宕机时可以从其他未宕机的机器中完整导出这M个文件,求最好的存放与分割策略。

(3) 假设有三十台服务器,每个上面都存有上百亿条数据(有可能重复),如何找出这三十台机器中,根据某关键字,重复出现次数最多的前100条?要求用Hadoop来做。

(4) 设计一个系统,要求写速度尽可能高,说明设计原理。

(5) 设计一个高并发系统,说明架构和关键技术要点。

(6) 有25T的log(query->queryinfo),log在不段的增长,设计一个方案,给出一个query能快速反回queryinfo

以上所有问题中凡是不涉及高并发的,基本可以采用google的三个技术解决,分别为:GFS,MapReduce,Bigtable,这三个技术被称为“google三驾马车”,google只公开了论文而未开源代码,开源界对此非常有兴趣,仿照这三篇论文实现了一系列软件,如:Hadoop、HBase、HDFS、Cassandra等。

在google这些技术还未出现之前,企业界在设计大规模分布式系统时,采用的架构往往是database+sharding+cache,现在很多公司(比如taobao,weibo.com)仍采用这种架构。在这种架构中,仍有很多问题值得去探讨。如采用什么数据库,是SQL界的MySQL还是NoSQL界的Redis/TFS,两者有何优劣? 采用什么方式sharding(数据分片),是水平分片还是垂直分片?据网上资料显示,weibo.com和taobao图片存储中曾采用的架构是Redis/MySQL/TFS+sharding+cache,该架构解释如下:前端cache是为了提高响应速度,后端数据库则用于数据永久存储,防止数据丢失,而sharding是为了在多台机器间分摊负载。最前端由大块大块的cache组成,要保证至少99%(该数据在weibo.com架构中的是自己猜的,而taobao图片存储模块是真实的)的访问数据落在cache中,这样可以保证用户访问速度,减少后端数据库的压力,此外,为了保证前端cache中数据与后端数据库中数据一致,需要有一个中间件异步更新(为啥异步?理由简单:同步代价太高。异步有缺定,如何弥补?)数据,这个有些人可能比较清楚,新浪有个开源软件叫memcachedb(整合了Berkeley DB和Memcached),正是完成此功能。另外,为了分摊负载压力和海量数据,会将用户微博信息经过片后存放到不同节点上(称为“sharding”)。

这种架构优点非常明显:简单,在数据量和用户量较小的时候完全可以胜任。但缺定早晚一天暴露出来,即:扩展性和容错性太差,维护成本非常高,尤其是数据量和用户量暴增之后,系统不能通过简单的增加机器解决该问题。

于是乎,新的架构便出现了。主要还是google的那一套东西,下面分别说一下:

GFS是一个可扩展的分布式文件系统,用于大型的、分布式的、对大量数据进行访问的应用。它运行于廉价的普通硬件上,提供容错功能。现在开源界有HDFS(Hadoop Distributed File System),该文件系统虽然弥补了数据库+sharding的很多缺点,但自身仍存在一些问题,比如:由于采用master/slave架构,因而存在单点故障问题;元数据信息全部存放在master端的内存中,因而不适合存储小文件,或者说如果存储的大量小文件,那么存储的总数据量不会太大。

MapReduce是针对分布式并行计算的一套编程模型。他最大的优点是:编程接口简单,自动备份(数据默认情况下会自动备三份),自动容错和隐藏跨机器间的通信。在Hadoop中,MapReduce作为分布计算框架,而HDFS作为底层的分布式存储系统,但MapReduce不是与HDFS耦合在一起的,你完全可以使用自己的分布式文件系统替换掉HDFS。当前MapReduce有很多开源实现,如Java实现Hadoop MapReduce,C++实现Sector/sphere等,甚至有些数据库厂商将MapReduce集成到数据库中了。

BigTable俗称“大表”,是用来存储结构化数据的,个人觉得,BigTable在开源界最火爆,其开源实现最多,包括:HBase,Cassandra,levelDB等,使用也非常广泛。

除了google的这三家马车,还有其他一些技术:

Dynamo:亚马逊的key-value模式的存储平台,可用性和扩展性都很好,采用DHT(Distributed Hash Table)对数据分片,解决单点故障问题,在Cassandra中,也借鉴了该技术,在BT和电驴的中,也采用了类似算法。

虚拟节点技术:该技术常用于分布式数据分片中。具体应用场景是:有一大坨数据(maybe TB级或者PB级),我们需按照某个字段(key)分片存储到几十(或者更多)台机器上,同时想尽量负载均衡且容易扩展。传统的做法是:Hash(key) mod N,这种方法最大缺点是不容易扩展,即:增加或者减少机器均会导致数据全部重分布,代价忒大。于是乎,新技术诞生了,其中一种是上面提到的DHT,现在已经被很多大型系统采用,还有一种是对“Hash(key) mod N”的改进:假设我们要将数据分不到20台机器上,传统做法是hash(key) mod 20,而改进后,N取值要远大于20,比如是20000000,然后我们采用额外一张表记录每个节点存储的key的模值,比如:

node1:0~1000000

node2:1000001~2000000

。。。。。。

这样,当添加一个新的节点时,只需将每个节点上部分数据移动给新节点,同时修改一下这个表即可。

Thrift:Thrift是一个跨语言的RPC框架,分别解释一下“RPC”和“跨语言”,RPC是远程过程调用,其使用方式与调用一个普通函数一样,但执行体发生在远程机器上。跨语言是指不同语言之间进行通信,比如c/s架构中,server端采用C++编写,client端采用PHP编写,怎样让两者之间通信,thrift是一种很好的方式。

文章最前面的几道题均可以映射到以上几个系统中的某个模块中,如:

(1) 关于高并发系统设计。主要有以下几个关键技术点:缓存,索引,数据分片,锁粒度尽可能小。

(2) 问题2涉及到现在通用的分布式文件系统的副本存放策略。一般是将大文件切分成小的block(如64MB)后,以block为单位存放三份到不同的节点上,这三份数据的位置需根据网络拓扑结构配置,一般而言,如果不考虑跨数据中心,可以这样存放:两个副本存放在同一个机架的不同节点上,而另外一个副本存放在另一个机架上,这样从效率和可靠性上,都是最优的(这个google公布的文档中有专门的证明,有兴趣的可参阅一下。)。如果考虑跨数据中心,可将两份存在一个数据中心的不同机架上,另一份放到另一个数据中心。

(3)问题4涉及到BigTable的模型。主要思想是将随机写转化为顺序写,进而大大提高写速度。具体是:由于磁盘物理结构的独特设计,其并发的随机写(主要是因为磁盘寻道时间长)非常慢,考虑到这一点,在BigTable模型中,首先会将并发写的大批数据放到一个内存表(称为“memtable”)中,当该表大到一定程度后,会顺序写到一个磁盘表(称为“SSTable”)中,这种写是顺序写,效率极高。说到这,可能有读者问,随机读可不可以这样优化?答案是:看情况。通常而言,如果读并发度不高,则不可以这么做,因为如果将多个读重新排列组合后再执行,系统的响应时间太慢,用户可能接受不了,而如果读并发度极高,也许可以采用类似机制。


Read full article from 董的博客 » 系统设计面试题思路综述


Labels

Algorithm (219) Lucene (130) LeetCode (97) Database (36) Data Structure (33) text mining (28) Solr (27) java (27) Mathematical Algorithm (26) Difficult Algorithm (25) Logic Thinking (23) Puzzles (23) Bit Algorithms (22) Math (21) List (20) Dynamic Programming (19) Linux (19) Tree (18) Machine Learning (15) EPI (11) Queue (11) Smart Algorithm (11) Operating System (9) Java Basic (8) Recursive Algorithm (8) Stack (8) Eclipse (7) Scala (7) Tika (7) J2EE (6) Monitoring (6) Trie (6) Concurrency (5) Geometry Algorithm (5) Greedy Algorithm (5) Mahout (5) MySQL (5) xpost (5) C (4) Interview (4) Vi (4) regular expression (4) to-do (4) C++ (3) Chrome (3) Divide and Conquer (3) Graph Algorithm (3) Permutation (3) Powershell (3) Random (3) Segment Tree (3) UIMA (3) Union-Find (3) Video (3) Virtualization (3) Windows (3) XML (3) Advanced Data Structure (2) Android (2) Bash (2) Classic Algorithm (2) Debugging (2) Design Pattern (2) Google (2) Hadoop (2) Java Collections (2) Markov Chains (2) Probabilities (2) Shell (2) Site (2) Web Development (2) Workplace (2) angularjs (2) .Net (1) Amazon Interview (1) Android Studio (1) Array (1) Boilerpipe (1) Book Notes (1) ChromeOS (1) Chromebook (1) Codility (1) Desgin (1) Design (1) Divide and Conqure (1) GAE (1) Google Interview (1) Great Stuff (1) Hash (1) High Tech Companies (1) Improving (1) LifeTips (1) Maven (1) Network (1) Performance (1) Programming (1) Resources (1) Sampling (1) Sed (1) Smart Thinking (1) Sort (1) Spark (1) Stanford NLP (1) System Design (1) Trove (1) VIP (1) tools (1)

Popular Posts