前言
前段时间面试百度Java技术岗时碰到了一道算法题:任意数分三组,使得每组的和尽量相等。由于时间仓促,加之面试时头昏脑涨,这道题没做出来甚至没有给出思路,导致百度面试之旅失败。这让我多少有些遗憾和不甘。因为最近接触算法的东西较多而且本身对算法感兴趣,所以回家之后绞尽脑汁想把这题做出来。
说说我的思路:首先一定要先排序,这也是解决问题的关键。然后降序排序后的前三个数各分一组把剩余数往三个数上叠加。我最开始的思路也是如此,问题在于分组个数不确定,出现极端大的数怎么办,怎么叠加?那层窗户纸就是将剩余数中的最大值加到前三个数的最小值上,然后重排序,继续叠加,直到数组个数剩三个为止!(不知道大家能不能看懂)我事后解题思路大致就是这样,太苦逼了。
还记得我当初校招的时候第一场面试也是倒在算法,算法可以说是我们每个程序员的痛,明明平时工作的时候不会太多用到,但这个却是面试必问的点,也是我们进阶必须要面对的东西。现在算法挺吃香的,但我们也不可能全身心的投入到算法的学习,这时候就需要一本好的参考书来协助我们学习。下面要与大家介绍的文档可以作为从事计算机研究与开发的技术人员的参考书,特别是对正在准备面试、参加选拔性考试以及校园面试的读者尤为有用。
这份文档以Java为描述语言,介绍了计算机编程中使用的数据结构和算法。这份文档强调问题及其分析,而非理论阐述,共分为21章,讲述了基本概念、递归和回溯、链表、栈、队列、树、优先队列和队、并查集DAT、图算法、排序、查找、选择算法(中位数)、符号表、散列、字符串算法、算法设计技术、贪婪算法、分治算法、动态规划算法、复杂度类型等内容。每章首先阐述必要的理论基础,然后给出问题集。文档中大约有700个算法问题及相应的解法,对于许多问题,文档中提供了多个具有不同复杂度的解决方法。由于篇幅限制无法全部展示出来,需要的朋友只需要点赞文章,关注我直接前往github地址:传送门 即可获取!
字节内部算法文档
第1章绪论
本章的目的是阐述算法分析的重要性、它们的表示法和关系,并尽可能求解多个问题。首先,让我们重点关注算法的基本要素、分析的重要性,然后再逐步讨论上述提及的其他主题。在完成本章的学习后,能够分析任意给定算法的复杂度(特别是递归函数)。
第2章递归和回溯
本章将探讨一个重要的内容“递归”。本书中几乎每章都要用到递归,同时还介绍一个与之相关的概念“回潮”。
第3章链表
第4章栈
第5章队列
第6章树
第7章优先队列和堆
第8章并查集ADT
本章将介绍一种非常重要的数学概念;集合。它说明如何表示一组无需考虑顺序的元素。并查集ADT可以表示一组无序元素,可用来解决等价问题。并查集易于实现,使用一个简单数组就能实现它,且每个函数也只需几行代码。在许多算法中,并查集ADT是作为一个辅助数据结构而存在的(例如,图论中的Kruscal算法)。在讨论并查集ADT前,首先了解集合的几个基本性质。
第9章图算法
在现实世界中,许多问题是由对象以及它们之间的联系所描述的。例如,在航空地图中,我们可能对这样的问题感兴趣:“从海德拉巴去纽约,哪种方式最快?”或者“哪种方式价格最便宜?”为了回答这些问题,需要关于对象(城镇)之间的联系(飞行路线)信息。图就是用来解决这类问题的数据结构。
第10章排序
第11章查找
第12章选择算法(中位数)
第13章符号表
第14章散列
第15章字符串算法
为了理解字符串算法的重要性,考虑在任意一个浏览器(如InternetExplorer、Fire-fox或Google Chrome)中输入一个URL(Uniform Resource Locator,统一资源定位符)时发生的情况。在键入URL的一些前缀字符后,可以看见浏览器会显示一个所有可能的URL.列表。这意味着,浏览器执行了一些内部处理后,给用户一个可能匹配的URL列表。这种技术常称为自动完成。
第16章算法设计技术
前面的章节针对不同的问题介绍了各种算法。在求解一个新问题时,通常的思路是寻找当前问题与已解决问题之间的相似之处,从面轻松找到新问题的求解方法。本章将对各种算法按照不同的方法进行分类,然后在随后的3章中分别介绍3个算法设计思想〔即贫婪、分治和动态规划〕.
第17章贪婪算法
首先通过对一个简单理论的讨论,初步理解贪婪思想。以下棋为例,每一步的决策都需要考虑对后续棋局的影响。而在网球(或排球)比赛中,选手的行为仅取决于当前的状况,选择当下最为正确的动作,而不关心后续的影响。这说明在某些情况下选择当下最佳行为的决策,可以得到一个最优解(贪婪),但并非所有情况都如此,贪婪策略适用于上述第二类问题。
第18章 分治算法
对于第17章列举的许多问题,贪婪策略不能提供最优解。而其中的某些问题可通过分支(Divid and Conquer,D&C)法来轻松求解。分治法是一种重要的基于递归的算法设计技术,分治算法递归地将问题分解为两个或多个同类型的子问题,直至这些子问题简单到能够直接求解,然后再将这些子同题的解合成为原始问题的解。
第19章动态规划算法
本章将试图求解那些采用其他技术(如分治法和贪婪法)无法获得最优解的问题。动态规划(Dynamic Programming,DP)是一项虽简单但较难掌握的技术。一个容易识别和求解DP问题的方法是通过求解尽可能多的问题。“Programming”一词并不是指编程,二是表示填充表格(类似于线性规划)
第20章复杂度类型
在前面的各章中,描述了不同问题求解的复杂度。某些算法随着问题规模的增加其复杂度的增长速率较低,而另一些则有比较高的增长速率。对于具有较低增长率的问题,称为简单问题(或易求解问题);对于具有较高复杂度的问题,称为难问题(或难求解问题)。该分类是基于求解某个问题时算法的运行时间(或者占用内存)决定的。
第21章杂谈
本章将介绍一些对于面试和考试有用的话题,我们来看看文中的一些其他的编程题。
1.设计一个算法,按照螺旋顺序依次输出矩阵中的元素。
2.设计一个洗牌算法。
3.基于反转算法的数组旋转问题。设计一个函数rotate(A[],d,n),该函数将大小为n的数组旋转d个元素。例如,数组1,2,3,4,5,6,7在经过2个元素的旋转后变为3,4,5,6,7,1,2。
4.已知数组s[1..n]和反转函数(s,i,j),反转函数颠倒à到j之间的数组元素(包括第i和j个元素)的顺序。以下序列的功能是什么?(1<kn)
5.字符串由词和空格组成,设计一个程序将字符串中所有空格移到字符串的最前面,要求仅遍历数组一次,并且在原字符串中进行调整。
6.能否降低问题5算法的复杂度?
7.对于一个包含词和空格的字符串,设计一个程序将所有空格移到字符串的末尾,要求仅遍历数组一次,并且在原字符串中进行调整。
8.移动0到末尾。给定由n个整数组成的数组,将数组中的0移动到末尾。例如,如果有数组{1,9,8,4,0,0,2,7,0,6,0},应该变为{1,9,8,4,2,7,6,0,0,0}。所有其他元素的顺序不变。
9.能否降低问题8算法的复杂度?
10.问题9的变型。已知一个包含正数和负数的数组,设计一个算法将正数和负数分开,要求正数和负数的相对顺序保持不变。输人:一5,3,2,一l,4,一8,输出:一5,—1,—8,3,4,2。
这些问题你能答出多少?(手动狗头)反正我一时半会搞不定。不过没关系文档中也是有着每一题的解析,最后我们来看一看一位大佬对算法的一些看法。
大佬的一些看法
PS:我国软件学习形式主义太过严重,算法这种东西必须要与实践相结合才能真正起到作用,很多程序员算法非常厉害可是就是做不出东西,为啥,因为他们并不能能深刻理解算法,很多情况就是机械性套用算法,而且算法这种东西必须要与编程技术相结合,单一的算法几乎难以解决问题,比如云计算就属于算法,与互联网技术,多线程技术,多进程技术,和各种软硬件技术结合体,单一从一个层面去看算法几乎解决不了任何问题,国外的顶级软件大师则是将算法转化为计算机可以识别算法,并结合于其他计算机技术,使其达到最大效能,例如深度学习就和cuda相结合,使其最好的运转在某些硬件之上,再加之cuda具有极强并行运算能力,其效能达到最大化,其实算法与计算机技术具有极大跨度需要那种对数学或其他学科与计算机都较为精通的人才能正真转化,否则单—算法工程也仅仅只是书呆子的形式。难成大事。
我觉得他字多他说的都对,言归正传如果有朋友需要这份字节内部算法文档,只需要点赞文章,关注我之后直接前往Github地址:传送门 即可免费获取了~