怎么看php奇偶数,为什么程序员越来越排斥面试时做题?
《crack the code interview》,出自谷歌的面试官之手,几乎是所有程序员面试的时候可能遇到的题目。
这本书大家应该都说烂了,问题看起来很简单,题量也不多,但这本书却长盛不衰,必然有他的道理,它的好处正是以最经典的方式呈现了面试题的类型和归类。在准备面试的时候,可以从这一套题目中发现自己的薄弱点,也可以把他当作一个面试前的训练。
【部分《crack the code interview》】
1.1 判断一个字符串中的字符是否唯一1.2 字符串翻转1.3 去除字符串中重复字符1.4 写一个函数判断两个字符串是否是变位词1.5 写一个函数,把字符串中所有的空格替换为%201.6 矩阵旋转1.7 矩阵行列置01.8 利用已知函数判断字符串是否为另一字符串的子串2.1 从链表中移除重复结点2.2 实现一个算法从一个单链表中返回倒数第n个元素2.3 给定链表中间某结点指针,删除链表中该结点2.4 求由两个链表结点组成的数之和2.5 给定一个循环链表,实现一个算法返回这个环的开始结点3.1 如何只用一个数组实现三个栈3.2 实现一个栈,要求实现min函数以返回栈中的最小值3.3 实现数据结构SetOfStacks来模拟叠盘子3.4 编程解决汉诺塔问题3.5 使用两个栈实现一个队列3.6 写程序将一个栈按升序排序4.1 用一个函数判断一棵树是否平衡4.2 设计算法判断有向图两结点间是否存在路径4.3 将递增数组构建成一颗最小高度二叉树4.4 将二叉树每一层结点构建成一个链表4.5 查找二叉查找树的任意给定结点的“下一个”结点4.6 找出一棵二叉树中两个结点的第一个共同祖先结点4.7 判断一棵二叉树是否为另一棵二叉树的子树4.8 输出二叉树中路径上结点值之和为给定值的所有路径5.1 写程序使整数N中第i位到第j位的值与整数M中的相同5.2 给定一个字符串类型表示的小数,输出其二进制表示5.3 给定一个整数x,找出另外两个二进制表示中1的个数和x相同的数5.4 解释以下代码的作用:((n & (n-1)) == 0)5.5 写程序计算从整数A变为整数B需要修改的二进制位数5.6 交换一个整数二进制表示中的奇数位和偶数位5.7 写程序找出丢失的整数,要求时间复杂度O(n)6.1-6.6 程序员”脑筋急转弯”7.1 为通用卡牌游戏设计数据结构,并设计子类7.2 为电话呼叫中心设计类和数据结构7.3 用面向对象的方法设计一个音乐播放机7.4 用面向对象思想设计一个国际象棋游戏7.5 利用OOP思想设计在线读书系统7.6 设计一个拼图游戏的数据结构7.7 如何设计一个聊天服务程序7.8 用面向对象思想设计奥赛罗游戏(Othello)7.9 为一个内存文件系统设计数据结构和算法7.10 使用C++实现一个垃圾回收器8.1 写一个函数来产生第n个斐波那契数8.2 机器人路径计算8.3 写一个函数返回一个集合中的所有子集8.4 写一个函数返回一个串的所有排列8.5 实现一个算法打印出n对括号的有效组合8.6 实现图像处理软件中的“填充”函数8.7 有25分,10分,5分和1分的硬币无限个,计算组成n分的组合数8.8 经典八皇后问题9.1 写一个函数将数组B融入数组A,并使其有序9.2 写一个函数对字符串数组排序,使所有变位词都相邻9.3 在一个数字中查找特定元素9.4 如何给一个2G文件中的字符串排序?9.5 写一个函数找到给定字符串的位置9.6 在一个矩阵中找出特定的数9.7 写一个函数模拟叠罗汉节目10.1-10.7 程序员面试——数学相关题目看完这些题目你发现了什么,是不是很容易就发现这些都是比较偏理论的题目。就算你的开发能力非常强,但如果有一段时间没有看书或者练习,再来做这些题也会遇到很多不会的。
而已经入行的程序员更明白这一点:做题目做的准确程度与实际开发应用中的能力强弱无关,在职场上,我们注重的更多的是发现问题、解决问题的能力,而这些能力与上面的题目有关吗?我敢说没有太大关系,甚至没有关系。以上的面试题目,涉及的都是简单的算法和数据结构,是最能体现一个人的理解能力和学习态度的。
虽然说这不是一个真正考察程序员能力的好办法。但你能不做吗?答案当然是不能。因为这个面试的存在就是为了把不会做或者不愿意做面试题的人给排除掉,如果你不想要这个Offer当然可以选择不做。
其次,如果靠投递简历来选择工作的,这个公司并不认识你,对你也没有了解,除了做这些题目,实在没有办法来考察你的能力和学习态度。
如果你不想通过做题来获得Offer,走其他面试渠道的话,可以通过内推,通过企业内部员工推荐,绕过猎头公司、招聘网站等中间步骤,使应聘者和招聘方直接沟通。前提是在相应的公司有认识的人并获得他的认可。
为什么感觉程序员普遍会用Mac?
这一点太重要了,尤其是对开发人员,至少对于我来说很重要,这意味着Unix 下一堆好用的工具都可以随手捡到。如果你是个 windows 开发人员,我想你会在 windows 上装一套cygwin 环境吧?你不用 flex/yacc,grep,screen,ssh,make?好多 open source 的项目只提供cygwin/gcc/make 的编译环境。Mac 就是基于 BSD Unix 的,所有这些都是 built in 的。
2、开发环境。c/c++/java/perl/python/php/ruby/lisp,各种 shell,应有尽有,直接支持,非常方便。你要在 windows 上开发 C++,要装个 Visual Studio 编译器吧?或者其他的 C++ 编译器;你要开发 Java,你要下载 Java SDK 吧,说不定还要一个 Elipse 或者 Netbean;你要用 Perl,要安装一个 Perl 解释器吧,Active Perl?你要 python/php/ruby,你要安装……?开发程序需要库,图像处理,视频处理,人工智能之类大部分库都是只支持 Unix/Linux 的。Mac 基于 Unix,所以这些通通都和 Mac 能很好和睦相处。
3、编辑器 Vi/Emac。作为 程序员/IT 人员一个好用的编辑器太重要了,因为写程序/改系统配置都需要编辑器。我在 Mac 上差不多1/2的时间是 browser/email,另外1/2时间差不多就是 Vi 了。
5、不需要维护。Mac 买来就直接用,磁盘碎片整理?不需要。装驱动?Mac 装好了,驱动就好了。重装系统?我5年没有重装过一次(期间换了几次不同的 Mac)。
6、简洁。Mac 上所有的操作都简洁到了极致,尽量避免干扰用户,增加了程序员的生产力。比如切换无线网功能,在 Mac 上切换只需要1次鼠标点击就可以完成,在 windows 上需要点击多次鼠标(包括一些很愚蠢的确认对话框);再比如卸载 USB 盘,Mac 只需要1次鼠标点击,windows 至少需要点击右下角图标、停止设备、确认对话框等多次点击。
7、多窗口切换。这个很方便管理打开的程序/文档。我经常要在多个虚拟窗口切换,比如看浏览网页/邮件一个窗口,写程序/文档一个窗口。
8、程序员文化。国外程序员是以 Unix 为主流成长起来的。这一点和国内不同,中国程序员/开发人员大都是从90年代的 DOS 开始的,随着 Windows 的壮大,成长了一批使用 Microsoft 工具的程序员。这也解释了为什么自从 Mac 切换到 Unix 阵营后,Mac 会发展这么快。基于 Unix 的 Mac 一经推出后,迅速赢得了一大批老 Unix hacker 和新 Web 2.0/Linux hacker 的关注,正是因为这些忠实的 fans 影响了他们的人际网络,圈子,博客,从而影响了整个程序员文化。有点像 Ruby on Rails,开始是一小部分人(精英人士)试用,这些人感觉不错就在博客,研讨会等各种场合鼓吹,从而在 Web 开发领域刮起一阵 Ruby 风。
9、苹果很酷。每台电脑,每个系列都设计完美,从包装盒,宣传册,广告,电源线,电脑内部,电脑外观,电脑软件都精心设计,风格统一。甚至微小到螺丝,看过苹果机箱上的螺丝,机箱里面的数据线吗?那个也是设计。每个 Mac 上都标记着:Designed by Apple in California,而不是 Desgined in USA,苹果就是这么酷,“我们是一家加州公司”。苹果的保密措施可以说做到了极致,产品官方不发售就在市场上看不到踪影。
10、企业家精神。苹果的传奇经历吸引了大批硅谷创业者,Apple/Google/Microsoft/Amazon/eBay/Yahoo 代表了创新,进取的企业家精神。这不是一个大原因,但可以看作是 Mac 在国外,尤其是在美国,尤其是在硅谷,尤其是在大学这么流行的一个小原因吧。据调查2007年美国大学 Mac 市场占有率第一,这些大学精英们毕业以后走上工作岗位,走上社会,再过几年其中一部分走入中层,走进高层,他们会如何影响 Mac 呢。
如何把Linux的性能调整到最佳状态?
Linux操作系统是一个开源产品,也是一个开源软件的实践和应用平台,在这个平台下有无数的开源软件支撑,我们常见的apache、tomcat、mysql、php等等,开源软件的最大理念是自由、开放,那么linux作为一个开源平台,最终要实现的是通过这些开源软件的支持,以低廉的成本,达到应用最优的性能。因此,谈到性能问题,主要实现的是linux操作系统和应用程序的最佳结合。
一、性能问题综述
系统的性能是指操作系统完成任务的有效性、稳定性和响应速度。Linux系统管理员可能经常会遇到系统不稳定、响应速度慢等问题,例如在linux上搭建了一个web服务,经常出现网页无法打开、打开速度慢等现象,而遇到这些问题,就有人会抱怨linux系统不好,其实这些都是表面现象。操作系统完成一个任务时,与系统自身设置、网络拓朴结构、路由设备、路由策略、接入设备、物理线路等多个方面都密切相关,任何一个环节出现问题,都会影响整个系统的性能。因此当linux应用出现问题时,应当从应用程序、操作系统、服务器硬件、网络环境等方面综合排查,定位问题出现在哪个部分,然后集中解决。
在应用程序、操作系统、服务器硬件、网络环境等方面,影响性能最大的是应用程序和操作系统两个方面,因为这两个方面出现的问题不易察觉,隐蔽性很强。而硬件、网络方面只要出现问题,一般都能马上定位。下面主要讲解操作系统方面的性能调优思路,应用程序方面需要具体问题具体对待。
以下从影响Linux性能的因素、分析性能涉及的人员、系统性能优化工具、系统性能评价标准四个方面介绍优化Linux的一般思路和方法。
二、影响Linux性能的因素
2.1系统硬件资源
1.CPU
CPU是操作系统稳定运行的根本,CPU的速度与性能在很大程度上决定了系统整体的性能,因此,CPU数量越多、主频越高,服务器性能也就相对越好。但事实并非完全如此。
目前大部分CPU在同一时间内只能运行一个线程,超线程的处理器可以在同一时间运行多个线程,因此,可以利用处理器的超线程特性提高系统性能。在Linux系统下,只有运行SMP内核才能支持超线程,但是,安装的CPU数量越多,从超线程获得的性能方面的提高就越少。另外,Linux内核会把多核的处理器当作多个单独的CPU来识别,例如两个4核的CPU,在Lnux系统下会被当作8个单核CPU。但是从性能角度来讲,两个4核的CPU和8个单核的CPU并不完全等价,根据权威部门得出的测试结论,前者的整体性能要比后者低25%~30%。
可能出现CPU瓶颈的应用有db服务器、动态Web服务器等,对于这类应用,要把CPU的配置和性能放在主要位置。
2.内存
内存的大小也是影响Linux性能的一个重要的因素,内存太小,系统进程将被阻塞,应用也将变得缓慢,甚至失去响应;内存太大,导致资源浪费。Linux系统采用了物理内存和虚拟内存两种方式,虚拟内存虽然可以缓解物理内存的不足,但是占用过多的虚拟内存,应用程序的性能将明显下降,要保证应用程序的高性能运行,物理内存一定要足够大;但是过大的物理内存,会造成内存资源浪费,例如,在一个32位处理器的Linux操作系统上,超过8GB的物理内存都将被浪费。因此,要使用更大的内存,建议安装64位的操作系统,同时开启Linux的大内存内核支持。
由于处理器寻址范围的限制,在32位Linux操作系统上,应用程序单个进程最大只能使用4GB的内存,这样以来,即使系统有更大的内存,应用程序也无法“享”用,解决的办法就是使用64位处理器,安装64位操作系统。在64位操作系统下,可以满足所有应用程序对内存的使用需求 ,几乎没有限制。
可能出现内存性能瓶颈的应用有NOSQL服务器、数据库服务器、缓存服务器等,对于这类应用要把内存大小放在主要位置。
3.磁盘I/O性能
磁盘的I/O性能直接影响应用程序的性能,在一个有频繁读写的应用中,如果磁盘I/O性能得不到满足,就会导致应用停滞。好在现今的磁盘都采用了很多方法来提高I/O性能,比如常见的磁盘RAID技术。
通过RAID技术组成的磁盘组,就相当于一个大硬盘,用户可以对它进行分区格式化、建立文件系统等操作,跟单个物理硬盘一模一样,唯一不同的是RAID磁盘组的I/O性能比单个硬盘要高很多,同时在数据的安全性也有很大提升。
根据磁盘组合方式的不同,RAID可以分为RAID0,RAID1、RAID2、RAID3、RAID4、RAID5、RAID6、RAID7、RAID0+1、RAID10等级别,常用的RAID级别有RAID0、RAID1、RAID5、RAID0+1,这里进行简单介绍。
l RAID 0:通过把多块硬盘粘合成一个容量更大的硬盘组,提高了磁盘的性能和吞吐量。这种方式成本低,要求至少两个磁盘,但是没有容错和数据修复功能,因而只能用在对数据安全性要求不高的环境中。
l RAID 1:也就是磁盘镜像,通过把一个磁盘的数据镜像到另一个磁盘上,最大限度地保证磁盘数据的可靠性和可修复性,具有很高的数据冗余能力,但磁盘利用率只有50%,因而,成本最高,多用在保存重要数据的场合。
l RAID5:采用了磁盘分段加奇偶校验技术,从而提高了系统可靠性,RAID5读出效率很高,写入效率一般,至少需要3块盘。允许一块磁盘故障,而不影响数据的可用性。
l RAID0+1:把RAID0和RAID1技术结合起来就成了RAID0+1,至少需要4个硬盘。此种方式的数据除分布在多个盘上外,每个盘都有其镜像盘,提供全冗余能力,同时允许一个磁盘故障,而不影响数据可用性,并具有快速读/写能力。
通过了解各个RAID级别的性能,可以根据应用的不同特性,选择适合自身的RAID级别,从而保证应用程序在磁盘方面达到最优性能。
4.网络宽带
Linux下的各种应用,一般都是基于网络的,因此网络带宽也是影响性能的一个重要因素,低速的、不稳定的网络将导致网络应用程序的访问阻塞,而稳定、高速的网络带宽,可以保证应用程序在网络上畅通无阻地运行。幸运的是,现在的网络一般都是千兆带宽或光纤网络,带宽问题对应用程序性能造成的影响也在逐步降低。
2.2 操作系统相关资源
基于操作系统的性能优化也是多方面的,可以从系统安装、系统内核参数、网络参数、文件系统等几个方面进行衡量,下面依次进行简单介绍。
1.系统安装优化
系统优化可以从安装操作系统开始,当安装Linux系统时,磁盘的划分,SWAP内存的分配都直接影响以后系统的运行性能,例如,磁盘分配可以遵循应用的需求:对于对写操作频繁而对数据安全性要求不高的应用,可以把磁盘做成RAID 0;而对于对数据安全性较高,对读写没有特别要求的应用,可以把磁盘做成RAID 1;对于对读操作要求较高,而对写操作无特殊要求,并要保证数据安全性的应用,可以选择RAID 5;对于对读写要求都很高,并且对数据安全性要求也很高的应用,可以选择RAID10/01。这样通过不同的应用需求设置不同的RAID级别,在磁盘底层对系统进行优化操作。
随着内存价格的降低和内存容量的日益增大,对虚拟内存SWAP的设定,现在已经没有了所谓虚拟内存是物理内存两倍的要求,但是SWAP的设定还是不能忽略,根据经验,如果内存较小(物理内存小于4GB),一般设置SWAP交换分区大小为内存的2倍;如果物理内存大于8GB小于16GB,可以设置SWAP大小等于或略小于物理内存即可;如果内存大小在16GB以上,原则上可以设置SWAP为0,但并不建议这么做,因为设置一定大小的SWAP还是有一定作用的。
2.内核参数优化
系统安装完成后,优化工作并没有结束,接下来还可以对系统内核参数进行优化,不过内核参数的优化要和系统中部署的应用结合起来整体考虑。例如,如果系统部署的是Oracle数据库应用,那么就需要对系统共享内存段(kernel.shmmax、kernel.shmmni、kernel.shmall)、系统信号量(kernel.sem)、文件句柄(fs.file-max)等参数进行优化设置;如果部署的是Web应用,那么就需要根据Web应用特性进行网络参数的优化,例如修改net.ipv4.ip_local_port_range、net.ipv4.tcp_tw_reuse、net.core.somaxconn等网络内核参数。
3.文件系统优化
文件系统的优化也是系统资源优化的一个重点,在Linux下可选的文件系统有ext2、ext3、ReiserFS、ext4、xfs,根据不同的应用,选择不同的文件系统。
Linux标准文件系统是从VFS开始的,然后是ext,接着就是ext2,应该说,ext2是Linux上标准的文件系统,ext3是在ext2基础上增加日志形成的,从VFS到ext4,其设计思想没有太大变化,都是早期UNIX家族基于超级块和inode的设计理念。
XFS文件系统是一个高级日志文件系统,XFS通过分布处理磁盘请求、定位数据、保持Cache 的一致性来提供对文件系统数据的低延迟、高带宽的访问,因此,XFS极具伸缩性,非常健壮,具有优秀的日志记录功能、可扩展性强、快速写入性能等优点。
目前服务器端ext4和xfs是主流文件系统,如何选择合适的文件系统,需要根据文件系统的特点加上业务的需求综合来定。
2.3 应用程序软件资源
应用程序的优化其实是整个优化工程的核心,如果一个应用程序存在BUG,那么即使所有其他方面都达到了最优状态,整个应用系统还是性能低下,所以,对应用程序的优化是性能优化过程的重中之重,这就对程序架构设计人员和程序开发人员提出了更高的要求。
三、 分析系统性能涉及的人员
3.1 Linux运维人员
在做性能优化过程中,Linux运维人员承担着很重要的任务,首先,Linux运维人员要了解和掌握操作系统的当前运行状态,例如系统负载、内存状态、进程状态、CPU负荷等信息,这些信息是检测和判断系统性能的基础和依据;其次,Linux运维人员还有掌握系统的硬件信息,例如磁盘I/O、CPU型号、内存大小、网卡带宽等参数信息,然后根据这些信息综合评估系统资源的使用情况;第三,作为一名Linux运维人员,还要掌握应用程序对系统资源的使用情况,更深入的一点就是要了解应用程序的运行效率,例如是否有程序BUG、内存溢出等问题,通过对系统资源的监控,就能发现应用程序是否存在异常,如果确实是应用程序存在问题,需要把问题立刻反映给程序开发人员,进而改进或升级程序。
性能优化本身就是一个复杂和繁琐的过程,Linux运维人员只有了解了系统硬件信息、网络信息、操作系统配置信息和应用程序信息才能有针对性地的展开对服务器性能优化,这就要求Linux运维人员有充足的理论知识、丰富的实战经验以及缜密分析问题的头脑。
3.2 系统架构设计人员
系统性能优化涉及的第二类人员就是应用程序的架构设计人员。如果Linux运维人员在经过综合判断后,发现影响性能的是应用程序的执行效率,那么程序架构设计人员就要及时介入,深入了解程序运行状态。首先,系统架构设计人员要跟踪了解程序的执行效率,如果执行效率存在问题,要找出哪里出现了问题;其次,如果真的是架构设计出现了问题,那么就要马上优化或改进系统架构,设计更好的应用系统架构。
3.3 软件开发人员
系统性能优化最后一个环节涉及的是程序开发人员,在Linux运维人员或架构设计人员找到程序或结构瓶颈后,程序开发人员要马上介入进行相应的程序修改。修改程序要以程序的执行效率为基准,改进程序的逻辑,有针对性地进行代码优化。例如,Linux运维人员在系统中发现有条SQL语句耗费大量的系统资源,抓取这条执行的SQL语句,发现此SQL语句的执行效率太差,是开发人员编写的代码执行效率低造成的,这就需要把这个信息反馈给开发人员,开发人员在收到这个问题后,可以有针对性的进行SQL优化,进而实现程序代码的优化。
从上面这个过程可以看出,系统性能优化一般遵循的流程是:首先Linux运维人员查看系统的整体状况,主要从系统硬件、网络设备、操作系统配置、应用程序架构和程序代码五个方面进行综合判断,如果发现是系统硬件、网络设备或者操作系统配置问题,Linux运维人员可以根据情况自主解决;如果发现是程序结构问题,就需要提交给程序架构设计人员;如果发现是程序代码执行问题,就交给开发人员进行代码优化。这样就完成了一个系统性能优化的过程。
四、调优总结
系统性能优化是个涉及面广、繁琐、长久的工作,寻找出现性能问题的根源往往是最难的部分,一旦找到出现问题的原因,性能问题也就迎刃而解。因此,解决问题的思路变得非常重要。
例如,linux系统下的一个网站系统,用户反映,网站访问速度很慢,有时无法访问。
针对这个问题,第一步要做的是检测网络,可以通过ping命令检查网站的域名解析是否正常,同时,ping服务器地址的延时是否过大等等,通过这种方式,首先排除网络可能出现的问题;如果网络没有问题,接着进入第二步,对linux系统的内存使用状况进行检查,因为网站响应速度慢,一般跟内存关联比较大,通过free、vmstat等命令判断内存资源是否紧缺,如果内存资源不存在问题,进入第三步,检查系统CPU的负载状况,可以通过sar、vmstat、top等命令的输出综合判断CPU是否存在过载问题,如果CPU没有问题,继续进入第四步,检查系统的磁盘I/O是否存在瓶颈,可以通过iostat、vmstat等命令检查磁盘的读写性能,如果磁盘读写也没有问题,linux系统自身的性能问题基本排除,最后要做的是检查程序本身是否存在问题。通过这样的思路,层层检测,步步排查,性能问题就“无处藏身”,查找出现性能问题的环节也就变得非常简单。