- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563399 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174243
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
2 \9 \: W9 l: t+ O( {
算法越学越扎心,有没啥破解之法?! [, o1 k$ p9 w3 D
算法越学越扎心,有没啥破解之法?
/ O4 h' c1 b) x0 J5 _) _. B
6 R0 ]. |) A @/ \0 C. h' k) a对于算法的学习,我也是从一个小白一步步走来,当然,现在仍然很菜,,,不过,鉴于我觉得还有一些人比我更菜了,我决定谈谈我算法学习过程走过的坑,以及自己总结的一些经验。' }4 G" \& m" G
$ {) O" [* ~% [3 i
切勿盲目刷题:刷题前的知识积累- S8 T; e3 ?9 z. Z# K
' v( S) Q8 f# s. | C$ ]' M说实话,想要提高自己的算法,真的没啥捷径,我觉得最好的捷径就是脚踏实地着多动手去刷题,多刷题。4 {, y& l+ ]% r
7 k$ ~ J7 q1 I6 l" C
但是,我必须提醒的是,如果你是小白,也就是说,你连常见的数据结构,如链表、树以及常见的算法思想,如递归、枚举、动态规划这些都没学过,那么,我不建议你盲目疯狂着去刷题的。而是先去找本书先去学习这些必要的知识,然后再去刷题。( y' O5 Y6 d6 }+ ~" K! {2 ^; a
7 Q+ _+ I3 o# z% _% b& j
因为,如果这些基础都不懂的话,估计一道题做了几个小时,然后看答案都看不懂,做题没有任何思路,这是很难受的。久而久之,估计没啥动力了,我刚开始就是这样,一道题答案看一天,然而还是不大懂,什么回溯啊,暴力啊,还不知道是啥意思。3 x2 E% ~" |- i* j& _
% n4 Y' F! R/ j1 p# ?1 N
也就是说,假如你要去诸如leetcode这些网站刷题,那么,你要先具备一定的基础,这些基础包括:
+ Z, V' I" o1 C/ }1 ^& G, U9 z- u4 B$ ]2 u/ r
1、常见数据结构:链表、树(如二叉树)。(是的,链表和二叉树是重点,图这些可以先放着)
8 v/ y$ U. S$ N+ D4 L3 t% |/ }" R: j& V4 T% W4 Z
2、常见算法思想:贪婪法、分治法、穷举法、动态规划,回溯法。(贪婪、穷举、分治是基础,动态规划有难度,可以先放着)
, o. H1 K) b( `/ S. O* K0 r; g; n
% T( P) H# F5 V0 _/ R, c( G! ~7 E以上列出来的算是最基本的吧。就是说你刷题之前,要把这些过一遍再去刷题。如果你连这些最基本的都不知道的话,那么你再刷题的过程中,会很难受的,思路也会相对比较少。
! G) ?; V0 U% c' f: k9 q" R- B: \6 |
总之,千万不要急,先把这些基本的过一遍,力求理解,再去刷题。) f |/ Y( u1 u! ]& u
3 H4 O7 {9 B. Z
在这里,我推荐基本我大一时看过的书籍吧,感觉还是非常不错的,如果对于数据结构时零基础的话,那么我建议你可以看《数据结构与算法分析:C语言描述版》这本书,这本书自认为真的很 nice,当时我把这本书里面的全部都看了,并且 coding 了一遍,感觉整个人有了质的飞跃。# J; t- e- B/ F% ]3 {/ G
/ f) k, K/ ^) Y: \# j O3 F, d o H后面我时在一些学校的OJ刷题,当时看的一本书叫做《挑战程序设计大赛》,日本作家写的,我觉得这本书也很nice,里面有分初级,中级和高级三个模块,基础比较差的可以从初级开始看起。
5 G: s4 X3 @/ \( q' {8 j% F V
9 `, e n9 |3 h( |) T当然,这两本书,你可以在这个Github上找到:https://github.com/iamshuaidi/CS-Book0 q2 }7 x1 E* a" d [
总结下:
( M o8 G3 X3 E$ H9 K4 O" p; s6 a9 o! Z7 G3 _3 k2 m8 ~
提高数据结构与算法没啥捷径,最好的捷径就是多刷题。但是,刷题的前提是你要先学会一些基本的数据结构与算法思想。
2 L0 `! @/ m- l: Y! V+ \
) A: ~9 G, k- Q( D) B: [AC不是目的,我们要追求完美! W, \/ J0 ]5 I* l9 y
' e6 s* z6 J6 L5 \
如何刷题?如何对待一道算法题?6 `1 Z! D i7 k% r/ Y K' Z1 U
3 R8 Z/ \$ U5 i9 p我觉得,在做题的时候,一定要追求完美,千万不要把一道题做出来之后,提交通过,然后就赶紧下一道。我认为这意义不大,因为一道题的解法太多了,有些解法态粗糙了,我们应该要寻找最优的方法。
3 B; a( P3 K4 M" d6 z
9 Y7 q C$ K, A7 ^算法能力的提升和做题的数量是有一定的关系,但并不是线性关系。也就是说,在做题的时候,要力求一题多解,如果自己实在想不出来其他办法了,可以去看看别人是怎么做的,千万不要觉得模仿别人的做法是件丢人的事。
- }6 C! a& m+ h
; i3 e8 h* V* I5 z# o我做题的时候,我一看到一道题,可能第一想法就是用很粗糙的方式做,因为很多题采用暴力法都会很容易做,就是时间复杂度很高。之后,我就会慢慢思考,看看有没其他方法来降低时间复杂度或空间复杂度。最后,我会去看一下别人的做法,当然,并不是每道题都会这样执行。
+ x& b3 \1 J! f* D; k0 `6 M: f$ _( A
衡量一道算法题的好坏无非就是时间复杂度和空间复杂度,所以我们要力求完美,就要把这两个降到最低,令他们相辅相成。; v( Y! D; }0 g1 a4 F6 Q
0 R: ]* x3 u4 T) n9 _$ ?/ [; h我举道例题吧:9 i2 B0 Y# n( Y% u# d! i2 d& Y
; Q! U% w7 J/ a7 D n
问题: 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法?
* a) l; |( `) z% J0 _6 f) X, {+ f/ I& w4 }, u: I
这道题我在以前的分章分析过,不懂的可以先看下之前写的:递归与动态规划—基础篇19 t: u9 } B2 |% r9 J( g/ M# F8 ]
. Y2 `9 A( o8 r9 o# E4 a
方法1::暴力递归# P- }/ ]5 z: |3 D1 V
' W0 I! Z" z' {7 a
这道题不难,或许你会采取下面的做法:
. a7 ` O+ E# K/ p$ f! e( H; x8 k' e, S
public int solve(int n){: P( N+ Y' v! N7 y) p' D
if(n <= 2){
4 O1 L9 s( z# Y; f0 r, B return n;1 |8 u# x: K5 P2 ~& _, ~
}else{7 N9 ?" `: J! l
return solve(n-1) + solve(n-2);
7 R/ U" G5 b! a }
; j$ n( j" j$ L( u}6 A8 d/ ]$ E' H+ K# z
1
! X& Y: Z) T& W% t9 D2/ R% W- g0 M0 U" w9 W6 o
3
( M" g: b/ i, m* L6 U% D4
& p3 J: i; @& ^8 `9 B5
; V) F: y" q0 X% f7 y6
1 c+ B' Q- b& {* a7
- @% G7 w- g8 _" `0 P这种做法的时间复杂度很高,指数级别了。但是如果你提交之后侥幸通过了,然后你就接着下一道题了,那么你就要好好想想了。
7 g: j$ {4 l1 |* F3 U, H
# p1 r" O& O5 ~/ C3 _' r" M方法二:空间换时间9 C& t( b% T- a9 B0 ?; r' Z- _
2 h( i* \, W7 ^3 N力求完美,我们可以考虑用空间换时间:这道题如何你去仔细想一想,会发现有很多是重复执行了。不行你可以画个图
1 U4 Y9 W; Q: Z8 Z: m' c8 k( x. C# \1 R6 g, z' r4 h/ S; ~2 Q. g8 j
所以可以采取下面的方法:1 r( g, {8 h7 e. I
5 A. y# b) v1 S//用一个HashMap来保存已经计算过的状态
5 ]2 D+ w' W: D" D$ }8 r: \static Map<Integer,Integer> map = new HashMap();
' Q) R: N s, a; I% E9 }- upublic static int solve(int n){2 L3 ?* x+ N- W& a
if(n <= 2){3 g8 ~' H9 a# Q0 o6 D! T. }
return n;
" d9 ~ Y0 j5 E& @3 M }else{//是否计算过- W, O8 e# e8 y6 k& m
if(map.containsKey(n)){$ `+ S- v ~9 Y- b" P5 v/ f
return map.get(n);2 Y( ? H* d; W3 P1 [3 H% c
}else{4 z+ H3 | A5 S. }8 v6 k% J
int m = solve(n-1) + solve(n-2);
& F# E$ U+ Q4 N1 g1 \ map.put(n, m);& d! }" {& m* D7 v! a8 U
return m;
; ^+ A5 B* b4 z) h }; X" y4 k( F8 c. U' [
}4 ?; v Q" |) W+ h
}$ V, t) X% D2 Z8 J/ Q) e1 A5 G- O* R
& p6 o0 ~6 t- _$ F
1
) b6 ?: o* O$ K1 p' K2( L' A- X- j9 ~! f6 K
3; t& e7 T4 L8 i
4
V. I! R6 ?4 w- w5& `# N% |2 ~: Y8 }; h1 f( I
6) [2 ]: L, j" k3 Q" ~
7
" N7 _7 W: M4 S8
' q# j9 v2 o1 E0 E0 T9
2 S- w9 S5 o! \( W5 S$ P/ G106 y7 E% e7 d; W* Q
11
' t% ^* M& q/ B' ]+ I( A) W126 \ Z( e# v+ p) @1 B' x. T
13
( C9 U- D; b R7 l" b. k1 J7 Q! c145 Z/ T" B/ h1 n4 D. i
15 m1 g- ]$ [4 z" g( k! A
16: J0 `* s; G) k7 ^0 |' M
这样,可以大大缩短时间。也就是说,当一道题你做了之后,发现时间复杂度很高,那么可以考虑下,是否有更好的方法,是否可以用空间换时间。. K# I1 Y" [1 H( h0 {
* s, H p2 I1 S2 h方法三:斐波那契数列
! {0 z- v! |) s: c
( t; w1 w g4 q5 R# w1 A- S实际上,我们可以把空间复杂度弄的更小,不需要HashMap来保存状态:0 s8 o5 }, N0 {' `1 |0 d
& d2 n6 k: @; H) V8 spublic static int solve(int n){( v; @ ~" q) x; q4 C
if(n <= 2){& b" y. Z; ?% m$ `! A
return n;3 V, `8 F) O3 S* q/ |( B# a! r
}
* E* m) D2 I3 |$ g( Y: K int f1 = 0;8 c$ V% m6 ?% k
int f2 = 1;
1 K8 G$ q2 _) R int sum = 0;' ^8 ?7 L' v9 Y4 a9 x# _5 K
for(int i = 1; i<= n; i++){% {- Y! P' w. R) \8 R5 I
sum = f1 + f2;
& X. t0 R: e8 t& S0 d f1 = f2;
]! R1 p1 i! S" E8 Q f2 = sum;0 c/ J a' A% E# F# M
}0 r; J9 y, l0 J, s
return sum;
/ M0 {* f- N3 V, a% l2 J}3 ^' m+ H. }" K6 F8 B$ B
15 K$ y* s9 O; p/ K# X R
2
4 G' u/ {0 t3 b- y! b31 j+ q6 Y8 l# H1 R: v5 p7 a
4) U/ t4 \1 Y$ d- ~% ]% b0 [
5- c) A' P: w3 d4 ?8 T L7 z
6, x/ l/ @7 b- ^0 x, ~ P1 n
7
/ r2 u& f$ k5 a) g6 w+ `8
6 i* s+ B% A/ r2 N* P9
% a( l7 b! Q5 q ^109 I/ j3 a" j3 |& ^: A8 V0 s
11
# S" D; m* d. W6 O2 Z12
4 n1 _0 i. H% q- v139 }% g! r5 S0 ?% N
14
( j0 `% e! c0 j4 d2 m& G- @我弄这道题给你们看,并不是在教你们这道题怎么做,而是有以下目的:3 |; [3 J3 I6 v$ v! N" \
5 E7 X5 O4 x, c
1、在刷题的时候,我们要力求完美。
/ s5 \" C2 R: I; F+ g
, Q4 v9 p S/ Y4 Y; U& r4 S2 b2、我想不到这些方法啊,怎么办?那么你就可以去看别人的做法,之后,遇到类似的题,你就会更有思路,更知道往哪个方向想。
! o* J1 _* l d" u* i8 f/ U
; U% o2 {% t0 x3、可以从简单暴力入手做一道题,在考虑空间与时间之间的衡量,一点点去优化。
3 `& t* s8 n$ J! l3 S1 H2 d: s: B( @1 s' v6 r; M% W! W" g
挑战自己,跳出舒适区
" J- T$ s8 j; F+ K9 Q2 R5 d
. C! h1 S* V. c4 w8 Y什么叫舒适区?在刷题的时候,可能有一类题是你比较懂的,你每次一看就有思路,然后半个小时就撸好代码,提交代码,然后通过了,然后,哇,又多刷了一道题,心里很舒服。8 u6 k" ^7 @& r' a
& @' U0 {+ W3 l. [
但是,记住,前期你可以多刷这种题练手,提升自己的乐趣,但,我还是建议你慢慢跳出舒适区,去做一些自己不擅长的题,并且找段时间一直刷这种题。例如,我觉得我在递归方面的题还是挺强的,
! H' f9 _1 H2 u但是,我对动态规划的题,很菜,每次都要想好久,每次遇到这种题都有点害怕,没什么信心。不过有段时间我觉得只刷动态规划的题,直接在 leetcode 选定专题,连续做了四五十道,刚开始很难受,后来就慢慢知道了套路了,一道题从两三个小时最后缩到半小时,简单的十几分钟就搞定。感觉自己对这类型的题也不惧怕的。
9 { M$ n5 @, q, u. }6 i
0 t* Y6 t( y R当然,对于动态规划的学习,大家也可以看我这篇广受好评的文章:为什么你学不过动态规划?告别动态规划,谈谈我的经验
( f7 H: Z; [) @
, o: X+ C0 Y( h% b& y所以,建议你,一定要学好跳出自己的舒适区。
0 r, [; A2 o a5 G ^8 S2 a! K! Y0 m4 W' Q0 F6 d
一定要学会分类总结
P! S8 ^9 Y7 O) s# i3 Z0 b) g5 x' [
有些人以为 leetcode 的题刷的越多,就一定能越厉害,其实不然,leetcode 虽然有 1000 多道题,但题型就那么几类,我们前期在刷的时候,我是建议按照题型分类刷题的,例如我这整理刷二叉树相关,然后刷链表相关,然后二分法,然后递归等等,每刷一种题型,都要研究他们的套路,如果你愿意去总结,那么 leetcode 的题,其实你刷几百道,有目的、挑选的刷,我觉得就差不多了。! y ~2 S$ t! b' K9 u1 H/ Q9 j
( p$ d5 L6 P: l我看过一本书,叫做《程序员代码面试指南:IT 名企算法与数据结构题目最优解》,这本书就非常不错,里面按照栈,队列,链表,二叉树,字符串等一个专题一个专题来刷的,并且每道题都给出了最优解,而且里面的题有一定的难度,感兴趣的,真心不错,如果你把这本书的题全部搞定,并且总结相关套路,那么你的算法一定有很大的提升。# N" v! u* d: e, c
& D$ i2 \1 j# q s' S" k
推荐一些刷题网站
+ P7 ]! S2 _3 l3 o1 Q; C
/ f+ X! O7 }( Z% y我一般是在leetcode和牛客网刷题,感觉挺不错,题目难度不是很大。
& k2 T7 i1 k2 g! Y- }- J2 Y+ D! H7 M: t! J8 a3 M) R; j
在牛客网那里,我主要刷剑指Offer,不过那里也有个在线刷leetcode,不过里面的题量比较少。牛客网刷题有个非常方便的地方就是有个讨论区,那里会有很多大佬分享他们的解题方法,不用我们去百度找题解。所以你做完后,实在想不出,可以很方便着去看别人是怎么做的。* A5 V; {; H$ L0 @
( T- [2 l" N9 _0 |5 }
至于leetcode,也是大部分题目官方都有给出答案,也是个不错的刷题网站。你们可以两个挑选一个,或者两个都刷。8 |2 O/ T9 l j
" g& |- K* g8 z( c" U! t3 G0 B% Z
当然,还有其他刷题的网站,不过,其他网站没刷过,不大清除如何。3 g% _ p. Z/ t( g m) J* U" I
- A- s2 i/ I2 O! \1 @至于leetcode,有中文版和英文版
' b J' I" y0 G" ?
/ @+ w0 q& E4 g( kleetcode有中文版) L6 Y. c* ~* `3 W
* l5 q+ s% k6 R( ^" e
英文版
0 ~# G) {" u9 b9 _1 k( `; l3 Z' f& f, o, w2 \# ?, V
根据自己的兴趣选。
# M3 }6 T: L3 u
" x$ I# c, Z2 g" m j学习一些解题技巧7 c6 r J+ X R. S
; _9 ~0 c: v3 m2 k, S. j! d/ r; Z
说实话,有些题在你没看别人的解法前,你好不知道有这么美妙优雅的解法,看了之后,卧槽,居然还可以这样。而我们在刷题的过程中,就要不断累积这些技巧,当你累计多了,你就会形成一种
' G/ \& z3 \6 O1 |神经反应,一下子就想到了某种方法。解题技巧很多,例如数组下标法、位图法、双指针等等,我自己也分享过一篇总结一些算法技巧的文章
* U3 y4 X& s6 S, R T2 [0 t2 V6 _) Y) Q$ ]$ C+ x, H& n; N8 g, P
推荐阅读:一些常用的算法技巧总结# X4 K' \0 B4 Q+ @: h5 A! h% E
4 ?) z( j- E* z. w# |: P \
例如在刷题的时候,我们要学会巧用双指针、数组下标法、位运算等等技巧来解决问题,可能会有意想不到的效果。我给你再找点我之前写文章的一些例子吧:
) L' N5 i3 g) Z0 |
& }4 ]7 n; }0 F9 \1 h* r0 @分享一道解法巧妙的算法题
4 s& \2 J; O! Z8 c. Z- |5 c6 T
( ~" C+ \7 {. Y7 |4 A- z! k' ]& {【算法技巧】位运算装逼指南+ F: i. b0 C7 J; s, F* o" d
% Q" U; a+ C5 ~% F这是个长期累积的过程,我自己也精彩在我的公众号里分享一些解题的文章,感兴趣的可以关注我的公众号:帅地玩编程。
# `! V, z! z5 k) N
- ^# S9 { z9 g) C3 P) n4 H4 Q再说数据结构发重要性: ^! V4 V- d, J2 d+ ]
6 t! |1 N1 h% T' {7 V前面我主要是说了我平时都是怎么学习算法的。在数据结构方法,我只是列举了你们一定要学习链表和树(二叉堆),但这是最基本的,刷题之前要掌握的,对于数据结构,我列举下一些比较重要的:& p# W# g7 C0 O& k
7 e, [! u3 {0 i4 ^7 s
1、链表(如单向链表、双向链表)。
/ z/ ~; f2 ^( ^* W1 ^* _
# l6 Z* s3 B3 r7 l0 x! o0 U4 Y9 Q2、树(如二叉树、平衡树、红黑树)。
2 Y8 O2 S) o7 Q; D. \! A: ~9 l/ O+ X+ |" c1 f# ]
3、图(如最短路径的几种算法)。, W) G& h0 o2 E! S
* X2 i* A$ J) |
4、队列、栈、矩阵。
' a) P" `1 F8 r/ y% P
* `& ]% m8 z. ]1 {对于这些,自己一定要动手实现一遍。你可以看书,也可以看视频,新手可以先看视频,不过前期可以看视频,之后我建议是一定要看书。& N6 \! x% v( M$ S" r7 g
- R* B3 ?: }, n$ R' e
例如对于平衡树,可能你跟着书本的代码实现之后,过阵子你就忘记,不过这不要紧,虽然你忘记了,但是如果你之前用代码实现过,理解过,那么当你再次看到的时候,会很快就记起来,很快就知道思路,而且你的抽象能力等等会在不知不觉中提升起来。之后再学习红黑树啊,什么数据结构啊,都会学的很快。
3 n, t: W# c ?5 ~1 U0 |5 J8 l$ K
对于有哪些值得学习的算法,我之前也总结过,这里推荐给大家程序员必须掌握的核心算法有哪些?,这篇文章居然 40多万阅读量了,有点受宠若惊。
4 d0 P# s. k s0 I8 x
4 J. @1 m) _4 E) V. o+ y+ w最最重要
7 k# |% {9 G B: ^7 ~' z" ~( ^( _ E) s3 d0 Q+ F& R2 S6 I4 q4 K
动手去做,动手去做,动手去做。重要的话说三遍。
: j6 D6 N) s u! H7 U. T* t% [$ M+ U' Z8 h$ V8 C, j$ u
千万不要找了一堆资源,订好了学习计划,我要留到某某天就来去做…
$ \/ d) _% O1 ?. b1 v1 v( V" _ ]8 B0 H. F/ f) ~9 f# I9 I& \
千万不要这样,而是当你激情来的时候,就马上去干,千万不要留到某个放假日啊什么鬼了,很多这种想法的人,最后会啥也没做的。! X$ Y# y5 x p& b$ z
9 w0 _$ S% H: @( _) R也不要觉得要学习的有好多啊,不知道从哪学习起。我上面说了,可以先学习最基本的,然后刷题,刷题是一个需要长期坚持的事情,一年,两年。在刷题的过程中,可以穿插和学习其他数据结构。$ ?& @1 d3 K( J- {/ Z
; h7 g7 F& {: F2 P
总结一下吧8 J6 h" b4 Y% L( h
2 @4 \: N# J% T6 C0 K, m" a
所以我给大家的建议就是,先学习基本的数据结构以及算法思想,不要盲目刷题,接着刷题的过程中,不能得过且过,尽量追求最优解,还有就是要跳出舒适区,逼自己成长,刷题的过程中,要学会分类总结。0 v' Z! u) t1 z' b* t% N
9 {& }- _9 _! H- `当然,最重要的,就是你去动手了,不然,一切免谈!
7 \) g7 O6 W2 B- ?# i. v# @# x' i0 w$ U
看在熬夜写过的份上,送我个赞呗,嘻嘻。
$ x+ a: L2 ?6 _ e) O————————————————
& Q \* `& h5 U) i6 w版权声明:本文为CSDN博主「帅地」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
7 j) Y6 q, S' T! V1 Q原文链接:https://blog.csdn.net/m0_37907797/article/details/104765116
% S9 l8 J/ J u" p4 z l8 ~
" X" F/ k6 Z! |0 R# E
3 c0 I/ T) f5 Z+ {7 N$ t |
zan
|