大一从一个小白一路走过来,也在 leetcode 刷了几年了题,也是有点经验,也走过不少坑,在此分享个人一波经验,请耐心看完必定会有所帮助。android
说实话,想要提升本身的算法,我以为就是脚踏实地着多动手去刷题,多刷题。程序员
可是,若是你是小白,也就是说,你连常见的数据结构,如链表、树以及常见的算法思想,如递归、枚举、动态规划这些都没学过,那么,我不建议你盲目疯狂着去刷题的。而是先去找本书先去学习这些必要的知识,而后再去刷题。 由于,若是这些基础都不懂的话,估计一道题作了几个小时,而后看答案都不不懂,作题没有任何思路,这是很难受的。长此以往,估计没啥动力了,我刚开始就是这样,一道题答案看一天,然而仍是不大懂,什么回溯啊,暴力啊,还不知道是啥意思。面试
也就是说,假如你要去诸如leetcode这些网站刷题,那么,你要先具有必定的基础,这些基础包括:算法
一、常见数据结构:链表、树(如二叉树)。(是的,链表和二叉树是重点,图这些能够先放着)编程
二、常见算法思想:贪婪法、分治法、穷举法、动态规划,回溯法。(贪婪、穷举、分治是基础,动态规划有难度,能够先放着)数组
以上列出来的算是最基本的吧。就是说你刷题以前,要把这些过一遍再去刷题。若是你连这些最基本的都不知道的话,那么你再刷题的过程当中,会很难受的,思路也会相对比较少。bash
总之,千万不要急,先把这些基本的过一遍,力求理解,再去刷题。这些基础的数据结构与算法,我是在大一第二学期学的,我没看视频,我是经过看书学的,那时候看的书是:session
一、数据结构与算法分析(c 语言描述版)数据结构
我相信大部分人大学看的教程都是清华大学出版社严蔚敏写的那本书,说实话,做为初学者,那本书我没能坚持看下去,可能比较适合大佬看吧。我本身买了一本《数据结构与算法分析(c 语言描述版)》,挺薄的,不过感受很棒,这本书让我学到了不少,我的感受也挺容易懂的,代码实现是采用 C 语言来实现的,不是伪代码,若是你想学习数据结构,我以为这本书是个不错的选择。班级里有挺多人看了《大话数据结构》,挺他们说也挺不错,不过我没看过。函数
二、挑战程序设计竞赛
这边书也是大一时看的,若是你想刷题,我挺推荐这本书,里面分初级、中级到高级。虽然每道题没有讲的特别详细,但当时都看懂了,真心不错。不太高级那部分我是没看,初级和中级看着挺舒服。也是学到挺多的,推荐给你们。
三、编程之美
四、编程珠玑
五、程序员代码面试指南:IT 名企算法与数据结构题目最优解
作个补充:这些书籍我都有保存了电子版的,不过百度云发出来常常会连接失效,我很差及时更新,不过你能够关注个人公众号:苦逼的码农,回复**“电子书“**便可获取。个人公众号也有100多原创文章,有不少是讲解算法的, 也很是欢迎你来关注,共同窗习。
说实话,我那一学期的时间几乎都花在数据结构与算法上,但刷的题不多,只是书本上的一些例题。因此当我把这些基本的过一遍以后,再去一些网站刷题依旧很是菜。
因此大家千万别期望觉得本身把这些思想学完以后刷题会很牛,只有多刷题,只有多动手实践,你的灵敏度才会提升起来。
总结下:
提升数据结构与算法没啥捷径,最好的捷径就是多刷题。可是,刷题的前提是你要先学会一些基本的数据结构与算法思想。
如何刷题?如何对待一道算法题?
我以为,在作题的时候,必定要追求完美,千万不要把一道题作出来以后,提交经过,而后就赶忙下一道。我认为这意义不大,由于一道题的解法太多了,有些解法态粗糙了,咱们应该要寻找最优的方法。
算法能力的提高和作题的数量是有必定的关系,但并非线性关系。也就是说,在作题的时候,要力求一题多解,若是本身实在想不出来其余办法了,能够去看看别人是怎么作的,千万不要以为模仿别人的作法是件丢人的事。
我作题的时候,我一看到一道题,可能第一想法就是用很粗糙的方式作,由于不少题采用暴力法都会很容易作,就是时间复杂度很高。以后,我就会慢慢思考,看看有没其余方法来下降时间复杂度或空间复杂度。最后,我会去看一下别人的作法,固然,并非每道题都会这样执行。
衡量一道算法题的好坏无非就是时间复杂度和空间复杂度,因此咱们要力求完美,就要把这两个降到最低,令他们相辅相成。
我举道例题吧:
问题: 一只青蛙一次能够跳上1级台阶,也能够跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法?
这道题我在之前的分章分析过,不懂的能够先看下以前写的:递归与动态规划---基础篇1
方法1::暴力递归
这道题不难,或许你会采起下面的作法:
public static int solve(int n){
if(n == 1 || n == 2){
return n;
}else if(n <= 0){
return 0;
}else{
return solve(n-1) + solve(n-2);
}
}
复制代码
这种作法的时间复杂度很高,指数级别了。可是若是你提交以后侥幸经过了,而后你就接着下一道题了,那么你就要好好想一想了。
方法二:空间换时间
力求完美,咱们能够考虑用空间换时间:这道题如何你去仔细想想,会发现有不少是重复执行了。因此能够采起下面的方法:
//用一个HashMap来保存已经计算过的状态
static Map<Integer,Integer> map = new HashMap();
public static int solve(int n){
if(n <= 0)return 0;
else if(n <= 2){
return n;
}else{//是否计算过
if(map.containsKey(n)){
return map.get(n);
}else{
int m = solve(n-1) + solve(n-2);
map.put(n, m);
return m;
}
}
}
复制代码
这样,能够大大缩短期。也就是说,当一道题你作了以后,发现时间复杂度很高,那么能够考虑下,是否有更好的方法,是否能够用空间换时间。
方法三:斐波那契数列
实际上,咱们能够把空间复杂度弄的更小,不须要HashMap来保存状态:
public static int solve(int n){
if(n <= 0)
return 0;
if(n <= 2){
return n;
}
int f1 = 0;
int f2 = 1;
int sum = 0;
for(int i = 1; i<= n; i++){
sum = f1 + f2;
f1 = f2;
f2 = sum;
}
return sum;
}
复制代码
我弄这道题给大家看,并非在教大家这道题怎么作,而是有如下目的:
一、在刷题的时候,咱们要力求完美。
二、我想不到这些方法啊,怎么办?那么你就能够去看别人的作法,以后,遇到相似的题,你就会更有思路,更知道往哪一个方向想。
三、能够从简单暴力入手作一道题,在考虑空间与时间之间的衡量,一点点去优化。
什么叫温馨区?在刷题的时候,可能有一类题是你比较懂的,你每次一看就有思路,而后半个小时就撸好代码,提交代码,而后经过了,而后,哇,又多刷了一道题,内心很舒服。
可是,记住,前期你能够多刷这种题练手,提高本身的乐趣,但,我仍是建议你慢慢跳出温馨区,去作一些本身不擅长的题,而且找段时间一直刷这种题。例如,我以为我在递归方面的题仍是挺强的, 可是,我对动态规划的题,很菜,每次都要想很久,每次遇到这种题都有点惧怕,没什么信心。不过有段时间我以为只刷动态规划的题,直接在 leetcode 选定专题,连续作了七八十道,刚开始很难受, 后来就慢慢知道了套路了,一道题从两三个小时最后缩到半小时,简单的十几分钟就搞定。感受本身对这类型的题也不害怕的。
因此,建议你,必定要学好跳出本身的温馨区。
我通常是在leetcode和牛客网刷题,感受挺不错,题目难度不是很大。
在牛客网那里,我主要刷剑指Offer,不过那里也有个在线刷leetcode,不过里面的题量比较少。牛客网刷题有个很是方便的地方就是有个讨论区,那里会有不少大佬分享他们的解题方法,不用咱们去百度找题解。因此你作完后,实在想不出,能够很方便着去看别人是怎么作的。
至于leetcode,也是大部分题目官方都有给出答案,也是个不错的刷题网站。大家能够两个挑选一个,或者两个都刷。
固然,还有其余刷题的网站,不过,其余网站没刷过,不大清除如何。
至于leetcode,有中文版和英文版,我的建议英文版,英文版里面有各类大佬的解法分析。
leetcode有中文版
根据本身的兴趣选。
说实话,有些题在你没看别人的解法前,你好不知道有这么美妙优雅的解法,看了以后,卧槽,竟然还能够这样。而咱们在刷题的过程当中,就要不断累积这些技巧,当你累计多了,你就会造成一种 神经反应,一会儿就想到了某种方法。解题技巧不少,例如数组下标法、位图法、双指针等等,我本身也分享过一篇总结一些算法技巧的文章。给你举个例子吧,有时候有些技巧真让你大喊“卧槽”。
给你一组整型数据,这些数据中,其中有一个数只出现了一次,其余的数都出现了两次,让你来找出一个数 。
这道题可能不少人会用一个哈希表来存储,每次存储的时候,记录 某个数出现的次数,最后再遍历哈希表,看看哪一个数只出现了一次。这种方法的时间复杂度为 O(n),空间复杂度也为 O(n)了。
然而我想告诉你的是,采用位运算来作,绝对高逼格!
咱们刚才说过,两个相同的数异或的结果是 0,一个数和 0 异或的结果是它自己,因此咱们把这一组整型所有异或一下,例如这组数据是:1, 2, 3, 4, 5, 1, 2, 3, 4。其中 5 只出现了一次,其余都出现了两次,把他们所有异或一下,结果以下:
因为异或支持交换律和结合律,因此:
1^2^3^4^5^1^2^3^4 = (1^1)^(2^2)^(3^3)^(4^4)^5= 0^0^0^0^5 = 5。
也就是说,那些出现了两次的数异或以后会变成0,那个出现一次的数,和 0 异或以后就等于它自己。就问这个解法牛不牛逼?因此代码以下
int find(int[] arr){
int tmp = arr[0];
for(int i = 1;i < arr.length; i++){
tmp = tmp ^ arr[i];
}
return tmp;
}
复制代码
时间复杂度为 O(n),空间复杂度为 O(1),并且看起来很牛逼。
若是让你求解 2 的 n 次方,而且不能使用系统自带的 pow 函数,你会怎么作呢?这还不简单,连续让 n 个 m 相乘就好了,代码以下:
int pow(int n){
int tmp = 1;
for(int i = 1; i <= n; i++) {
tmp = tmp * m;
}
return tmp;
}
复制代码
不过你要是这样作的话,我只能呵呵,时间复杂度为 O(n) 了,怕是小学生都会!若是让你用位运算来作,你会怎么作呢?
我举个例子吧,例如 n = 13,则 n 的二进制表示为 1101, 那么 m 的 13 次方能够拆解为:
m^1101 = m^0001 * m^0100 * m^1000。
咱们能够经过 & 1和 >>1 来逐位读取 1101,为1时将该位表明的乘数累乘到最终结果。直接看代码吧,反而容易理解:
int pow(int n){
int sum = 1;
int tmp = m;
while(n != 0){
if(n & 1 == 1){
sum *= tmp;
}
tmp *= tmp;
n = n >> 1;
}
return sum;
}
复制代码
时间复杂度近为 O(logn),并且看起来很牛逼。
给你算法技巧,固然也能够关注个人公众号:苦逼的码农,专一与分享算法、计算机基础等相关文章,已有100多篇原创,欢迎来撩。
推荐阅读:一些经常使用的算法技巧总结
例如在刷题的时候,咱们要学会巧用双指针、数组下标法、位运算等等技巧来解决问题,可能会有意想不到的效果。我给你再找点我以前写文章的一些例子吧:
这是个长期累积的过程,我本身也精彩在个人公众号里分享一些解题的文章,感兴趣的能够关注个人公众号:苦逼的码农。
前面我主要是说了我平时都是怎么学习算法的。在数据结构方法,我只是列举了大家必定要学习链表和树(二叉堆),但这是最基本的,刷题以前要掌握的,对于数据结构,我列举下一些比较重要的:
一、链表(如单向链表、双向链表)。
二、树(如二叉树、平衡树、红黑树)。
三、图(如最短路径的几种算法)。
四、队列、栈、矩阵。
对于这些,本身必定要动手实现一遍。你能够看书,也能够看视频,新手能够先看视频,不过前期能够看视频,以后我建议是必定要看书。
例如对于平衡树,可能你跟着书本的代码实现以后,过阵子你就忘记,不过这没关系,虽然你忘记了,可是若是你以前用代码实现过,理解过,那么当你再次看到的时候,会很快就记起来,很快就知道思路,并且你的抽象能力等等会在不知不觉中提高起来。以后再学习红黑树啊,什么数据结构啊,都会学的很快。
动手去作,动手去作,动手去作。重要的话说三遍。
千万不要找了一堆资源,订好了学习计划,我要留到某某天就来去作.....
千万不要这样,而是当你激情来的时候,就立刻去干,千万不要留到某个放假日啊什么鬼了,不少这种想法的人,最后会啥也没作的。
也不要以为要学习的有好多啊,不知道从哪学习起。我上面说了,能够先学习最基本的,而后刷题,刷题是一个须要长期坚持的事情,一年,两年。在刷题的过程当中,能够穿插和学习其余数据结构。
你们也能够关注个人公众号:苦逼的码农,在个人公众号里,我也分享了不少与数据结构算法相同的文章,并且也分享了不少解题技巧。目前已分析了 100 多篇原创文章,下面是一些我以为 很不错的文章,强烈建议阅读:
链表的重要性不言而喻,若是你把我分享的这10道题都搞懂了,那么你在链表方面算过关的了:
就不一道道列出来了,一共挑选了10还不错的文章
我还讲解了一些经常使用数据结构与算法思想,每篇都通俗易懂着讲解了,被各类号所转发
二、十大排序重要性不言而喻,文章还附带了动画、讲解文章,代码 必学十大经典排序算法,看这篇就够了(附完整代码/动图/优质文章)(修订版)
三、总结了刷题过程当中经常使用的技巧,推荐阅读:一些经常使用的算法技巧总结
四、用漫画的形式讲解了AVL树:【漫画】之后在有面试官问你AVL树,你就把这篇文章扔给他。
五、大量图讲解了堆的各类操做:【算法与数据结构】堆排序是什么鬼?
索性把写的一些文章连接都分享一波,你们能够挑感兴趣的看算法与数据结构系列文章
也很是欢迎你们关注公众号「苦逼的码农」里面已有100多篇原创文章,我也分享了不少视频、书籍的资源,以及开发工具,欢迎各位的关注,第一时间阅读个人文章。
若是你以为这篇内容对你挺有启发,为了让更多的人看到这篇文章:不妨
一、点赞,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)
二、关注我和专栏,让咱们成为长期关系
三、关注公众号「苦逼的码农」,主要写算法、计算机基础之类的文章,里面已有100多篇原创文章