- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 566867 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 175283
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 3
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
, a& s6 d7 z' ?, Q
算法越学越扎心,有没啥破解之法?4 @! M, I3 m: x+ Z/ g. k
算法越学越扎心,有没啥破解之法? |# J$ A/ |) \2 _
M# f P. v8 }. `/ t对于算法的学习,我也是从一个小白一步步走来,当然,现在仍然很菜,,,不过,鉴于我觉得还有一些人比我更菜了,我决定谈谈我算法学习过程走过的坑,以及自己总结的一些经验。
" O6 h4 L* S9 ~( d9 I1 }) m+ h8 z% R2 A# x P( M2 _. u
切勿盲目刷题:刷题前的知识积累, C t0 @1 S. K$ N$ [ y u/ [
0 p" i) ?0 y. K# A+ d: f6 k说实话,想要提高自己的算法,真的没啥捷径,我觉得最好的捷径就是脚踏实地着多动手去刷题,多刷题。
n- k" e' i4 E" b+ ~4 y6 R- A: H M4 K
但是,我必须提醒的是,如果你是小白,也就是说,你连常见的数据结构,如链表、树以及常见的算法思想,如递归、枚举、动态规划这些都没学过,那么,我不建议你盲目疯狂着去刷题的。而是先去找本书先去学习这些必要的知识,然后再去刷题。
4 r, G7 A3 ]" S/ } G
& L* r0 Q' I m( E( X$ d因为,如果这些基础都不懂的话,估计一道题做了几个小时,然后看答案都看不懂,做题没有任何思路,这是很难受的。久而久之,估计没啥动力了,我刚开始就是这样,一道题答案看一天,然而还是不大懂,什么回溯啊,暴力啊,还不知道是啥意思。
# B4 j4 I' i; G* h
! K9 o* u* m9 ^4 N' c& p! g5 H4 Z也就是说,假如你要去诸如leetcode这些网站刷题,那么,你要先具备一定的基础,这些基础包括:
( [: m( E; p4 \' U* J
1 \$ _/ s, f# D0 d) t1、常见数据结构:链表、树(如二叉树)。(是的,链表和二叉树是重点,图这些可以先放着), g- b& N1 D( E9 C! g. T8 H/ Y
, g9 H% i& J& u9 ]# p
2、常见算法思想:贪婪法、分治法、穷举法、动态规划,回溯法。(贪婪、穷举、分治是基础,动态规划有难度,可以先放着)
* f: I! t3 L3 R9 V5 n& \( K8 y9 F3 [8 U: p# D& r
以上列出来的算是最基本的吧。就是说你刷题之前,要把这些过一遍再去刷题。如果你连这些最基本的都不知道的话,那么你再刷题的过程中,会很难受的,思路也会相对比较少。( b2 h- f, t9 r9 @
$ t' x: N, }( q. s' `" O* P3 i
总之,千万不要急,先把这些基本的过一遍,力求理解,再去刷题。* r% T" d& L$ F! r t; P* v( o
: c. x7 n) N4 B1 z在这里,我推荐基本我大一时看过的书籍吧,感觉还是非常不错的,如果对于数据结构时零基础的话,那么我建议你可以看《数据结构与算法分析:C语言描述版》这本书,这本书自认为真的很 nice,当时我把这本书里面的全部都看了,并且 coding 了一遍,感觉整个人有了质的飞跃。
: v1 d) W: s# t5 Y8 ~
: u/ U* @: C) j* v+ m) f- k8 x2 d后面我时在一些学校的OJ刷题,当时看的一本书叫做《挑战程序设计大赛》,日本作家写的,我觉得这本书也很nice,里面有分初级,中级和高级三个模块,基础比较差的可以从初级开始看起。1 K/ ~. K% B2 j
' H- J& t; t7 o* J
当然,这两本书,你可以在这个Github上找到:https://github.com/iamshuaidi/CS-Book9 |1 U' s" t0 c: o1 g% F; |
总结下:$ U' s! S0 M/ o7 l, i. z+ C4 x4 L
0 g% }8 u R |8 K提高数据结构与算法没啥捷径,最好的捷径就是多刷题。但是,刷题的前提是你要先学会一些基本的数据结构与算法思想。3 [" ]/ H2 \/ j) P. j: b: F* f) W# Z
5 v9 c8 a: `7 u/ V% H! p& V. S
AC不是目的,我们要追求完美1 _1 J! C# i: j- P+ M/ ]
! I0 v0 F) V5 h" \6 K9 O) C如何刷题?如何对待一道算法题?
0 j0 U0 ?" ], d4 m5 f$ x7 _/ J5 E: K! G4 F7 G9 f6 I- V, ~& F
我觉得,在做题的时候,一定要追求完美,千万不要把一道题做出来之后,提交通过,然后就赶紧下一道。我认为这意义不大,因为一道题的解法太多了,有些解法态粗糙了,我们应该要寻找最优的方法。
! C) }* }' w8 Q1 \, n" e1 W4 u1 O! M& V6 R: M8 N
算法能力的提升和做题的数量是有一定的关系,但并不是线性关系。也就是说,在做题的时候,要力求一题多解,如果自己实在想不出来其他办法了,可以去看看别人是怎么做的,千万不要觉得模仿别人的做法是件丢人的事。
; M# J7 ~& I7 a. U
U u7 |7 s; r0 X$ U我做题的时候,我一看到一道题,可能第一想法就是用很粗糙的方式做,因为很多题采用暴力法都会很容易做,就是时间复杂度很高。之后,我就会慢慢思考,看看有没其他方法来降低时间复杂度或空间复杂度。最后,我会去看一下别人的做法,当然,并不是每道题都会这样执行。! H5 c8 O, F- r" I
* j4 I6 j8 x7 v% w8 x Z) @衡量一道算法题的好坏无非就是时间复杂度和空间复杂度,所以我们要力求完美,就要把这两个降到最低,令他们相辅相成。
4 Y9 K7 b W" `4 H: ^7 J
v7 I3 M+ A0 _我举道例题吧:
7 D/ p' v; E' z6 h9 \
# C$ D1 W: `+ ?& I问题: 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法?
) R8 u" b9 C4 I7 s& v( n
6 C5 f& X p( H这道题我在以前的分章分析过,不懂的可以先看下之前写的:递归与动态规划—基础篇1& C- p; k3 Y) O4 b
7 ]+ g+ I) t' p8 F+ K& P方法1::暴力递归" A) {: N+ j) q2 Z0 {8 t
0 w: w( T0 O3 c" |9 E' { F
这道题不难,或许你会采取下面的做法:
. H" N! |6 `% e) d% E0 D- S+ m! Y
: x$ e+ y$ t( ]" y; fpublic int solve(int n){
$ i& {! d: x% t( a1 D" j if(n <= 2){
' |0 G% \0 S2 D# g2 x) P return n;( M" a0 N. i8 `) r5 u0 p- ]; [9 m
}else{
/ N4 P1 Q) C& s. s' X# C return solve(n-1) + solve(n-2);
* n3 b( P7 ^ p7 b }
n+ @* [4 G9 u$ f# y* h}" V2 g' s; i2 `0 }
17 u7 j3 d& D0 h$ L# Y e1 S( y$ @, Y
2
/ X( I* S, G, j. K* \) o: l3& i8 f7 o M' L) N: f$ m8 b
4
: U/ l* m; [' C7 d+ Y5 r0 d! r5
! C1 _ |( a; \6
; E4 W( ~7 T j) C1 j/ b+ I7$ a4 _* O' G. T" b
这种做法的时间复杂度很高,指数级别了。但是如果你提交之后侥幸通过了,然后你就接着下一道题了,那么你就要好好想想了。
* M" D; |/ o6 Q: i+ [2 v# s% h' M7 f# @9 c! m5 o
方法二:空间换时间
* N3 n$ O E; J+ x4 j3 Q+ V" _& E$ t7 g! F0 Q
力求完美,我们可以考虑用空间换时间:这道题如何你去仔细想一想,会发现有很多是重复执行了。不行你可以画个图
: n3 S" L/ ~ H9 }' g
3 ]1 k! d% h( _6 V9 [' b! K' J所以可以采取下面的方法:7 Q0 o" C+ ]# y
( y4 l F* X- _, F* k+ ]//用一个HashMap来保存已经计算过的状态
8 s! \' V0 l8 Q3 m% {static Map<Integer,Integer> map = new HashMap();
6 S/ b- u+ `; l; [public static int solve(int n){8 M3 P+ F K' K) w6 \8 x6 N
if(n <= 2){" u9 ^& @" J2 f# \1 ~- l' [ }
return n;1 V$ s/ `" c8 n8 O* J
}else{//是否计算过$ k Y% x$ c$ U8 P8 Z9 u
if(map.containsKey(n)){
R, h. z/ s' r return map.get(n);" z" l; m* N* g
}else{
/ x- S8 w0 `" ^& n0 l4 ` int m = solve(n-1) + solve(n-2);+ a" |% \7 F6 F3 T8 O6 \; R
map.put(n, m);2 H2 C" |2 v( T& `; N7 D& S
return m;! \5 K% V8 R/ M8 X
}" @5 A; a& O+ f6 r. W0 j
}. p) p, ], M2 M4 X, h$ j! j
}1 n, C$ d8 O9 L
) w6 M( U. D& k1 ^* n1
' _4 e% [: ]& l0 s. v: L2
- j( \, M9 |, i, u- \1 |3 Q( w+ K0 r G- r1 a" ]9 g- q# B J
4. r! U" @: p+ c# g
5
' q% q+ `3 f# r$ Z6
! ^8 e/ A; }5 M1 p7 h7
# c& k4 |7 S+ ~4 [8
9 |3 ?# ~8 b5 `9: g- J' t+ I! J- K8 S; j
10
+ A8 H; k& x* d7 ^% ?( Y11. I+ n$ a2 U( e7 G% ]0 u
122 N( o5 `) G/ N1 ]! y
13+ s" ~0 ]( C) {) U
147 f2 ^. r6 o) C. B+ H& J5 ^! ]
15
* s5 Y! d" H; T$ c* a& x1 r166 J: ^9 H& ^& y7 q- {
这样,可以大大缩短时间。也就是说,当一道题你做了之后,发现时间复杂度很高,那么可以考虑下,是否有更好的方法,是否可以用空间换时间。* Z& d) e4 r0 h C
6 Z1 v. y; w: b+ Z# P
方法三:斐波那契数列5 h& X2 L" Q9 l7 w2 l. D$ U
! K: t7 e$ ~% B, m4 l! g _2 ^实际上,我们可以把空间复杂度弄的更小,不需要HashMap来保存状态:
1 O8 V, x9 ]) o& s" p, `; y: O" E4 {3 Y K$ E* @) D# f+ e# s
public static int solve(int n){% b: Y `4 e% u3 U( [2 |
if(n <= 2){: _8 R$ ]6 b0 q$ ?$ D0 C8 ?
return n; o# s2 O: [$ s
} - @3 \' ~- r' p# n( X
int f1 = 0;
" {: m7 J6 H) I" V int f2 = 1;
) U1 q- n4 Y/ }6 S# G int sum = 0;3 @0 N# x# C4 n5 y
for(int i = 1; i<= n; i++){3 b# i' t! ]2 j+ B2 Z1 _
sum = f1 + f2;
+ P t8 P3 V( h! z: V- h) h" L& R f1 = f2;+ ^6 u2 T/ h( S( V/ X
f2 = sum;( F$ z; k/ \2 r! c& @4 _2 z4 P& y
}
& k) \: v9 Y; a: R3 ^/ O" @9 G return sum;
- W: p% j6 E* W" |# S}7 s) Y' D( r3 W' T: \
1
^' U& C5 Y) D9 N F4 r" Z2( R$ V" w7 Q$ S% G
3
) s; q# V; o' G' ^9 q4
5 r9 P0 v' `1 ], S/ i* I5, F2 N1 x @ w4 S, y7 K
6
7 \* y* G$ y9 n! ?- T( a( j# ~75 L; q$ z, c \2 L1 l+ r
8/ A" s' Q2 @1 b# e+ C/ z
90 V7 z& [/ H' t7 {. t' ~
10# m* z* d6 u# h2 G' L" k
11' K/ c) ^* \$ V ?: {4 S5 B1 Q9 S- `
12' w, C7 Q7 [, Z" C( [8 d; w7 e8 ~; S7 S
13
6 Y4 p. s$ k) d14* q: e- @& \9 W1 }" ?# x3 L
我弄这道题给你们看,并不是在教你们这道题怎么做,而是有以下目的:8 X0 ~2 i& j, v1 Y
7 b) u0 |0 j% B& B& n- P1、在刷题的时候,我们要力求完美。. C) N' b1 d: S/ m$ t
, E! q; I l! s5 @, m4 v/ _4 s) B' ~2、我想不到这些方法啊,怎么办?那么你就可以去看别人的做法,之后,遇到类似的题,你就会更有思路,更知道往哪个方向想。6 w% ^! @! O+ Q/ z9 E
" _+ E* w8 n# e, B7 `2 ?3、可以从简单暴力入手做一道题,在考虑空间与时间之间的衡量,一点点去优化。; g1 s& P; V/ G2 g& L
6 ?: ]; h; g7 c* m. L挑战自己,跳出舒适区
, z3 @/ ]0 A) h d3 T: [' s+ H: f9 M- e8 w- X8 N3 t3 O. B! ?" r
什么叫舒适区?在刷题的时候,可能有一类题是你比较懂的,你每次一看就有思路,然后半个小时就撸好代码,提交代码,然后通过了,然后,哇,又多刷了一道题,心里很舒服。
# U* \4 [3 ~5 O l1 E4 L
; ?% v A4 P% i% G但是,记住,前期你可以多刷这种题练手,提升自己的乐趣,但,我还是建议你慢慢跳出舒适区,去做一些自己不擅长的题,并且找段时间一直刷这种题。例如,我觉得我在递归方面的题还是挺强的,. Y, }5 o( l, l$ T" w! R. t+ H
但是,我对动态规划的题,很菜,每次都要想好久,每次遇到这种题都有点害怕,没什么信心。不过有段时间我觉得只刷动态规划的题,直接在 leetcode 选定专题,连续做了四五十道,刚开始很难受,后来就慢慢知道了套路了,一道题从两三个小时最后缩到半小时,简单的十几分钟就搞定。感觉自己对这类型的题也不惧怕的。
0 g' E2 _0 l+ m
9 k1 x7 u% C2 \5 D' K: a, P7 T当然,对于动态规划的学习,大家也可以看我这篇广受好评的文章:为什么你学不过动态规划?告别动态规划,谈谈我的经验
# x5 p/ B- g1 p/ D9 q( w& e
, K& {* E9 j% F1 r) V9 ?所以,建议你,一定要学好跳出自己的舒适区。; \ J+ p' W" \9 M# z K+ T) S
: M% B; L. m/ F* U3 o; C一定要学会分类总结
9 a+ Q/ g% H% {) Q+ V6 a/ r6 e& e. C$ n& i* Z5 h& c3 `
有些人以为 leetcode 的题刷的越多,就一定能越厉害,其实不然,leetcode 虽然有 1000 多道题,但题型就那么几类,我们前期在刷的时候,我是建议按照题型分类刷题的,例如我这整理刷二叉树相关,然后刷链表相关,然后二分法,然后递归等等,每刷一种题型,都要研究他们的套路,如果你愿意去总结,那么 leetcode 的题,其实你刷几百道,有目的、挑选的刷,我觉得就差不多了。
# H2 Y' @$ ~7 `2 h; a, T# V1 p
3 F3 J' A) d( |6 ]& A$ R# u我看过一本书,叫做《程序员代码面试指南:IT 名企算法与数据结构题目最优解》,这本书就非常不错,里面按照栈,队列,链表,二叉树,字符串等一个专题一个专题来刷的,并且每道题都给出了最优解,而且里面的题有一定的难度,感兴趣的,真心不错,如果你把这本书的题全部搞定,并且总结相关套路,那么你的算法一定有很大的提升。: M& v: `+ |. w0 }9 D* M: x
- ], z* D$ i6 n, [0 Q; h. H
推荐一些刷题网站
/ `) ]* |! V7 C: D0 V0 X' s! d; O _8 f7 [' e1 G) r3 I
我一般是在leetcode和牛客网刷题,感觉挺不错,题目难度不是很大。
) ?3 ~- n8 j" H) u: N! @
' [: j5 F, v' R在牛客网那里,我主要刷剑指Offer,不过那里也有个在线刷leetcode,不过里面的题量比较少。牛客网刷题有个非常方便的地方就是有个讨论区,那里会有很多大佬分享他们的解题方法,不用我们去百度找题解。所以你做完后,实在想不出,可以很方便着去看别人是怎么做的。
2 o% j- r. g+ a. x1 j! H& ?3 S# E. N$ d, q
至于leetcode,也是大部分题目官方都有给出答案,也是个不错的刷题网站。你们可以两个挑选一个,或者两个都刷。
5 K5 K9 t% U" f, i5 i+ _2 V$ q& F3 {7 J% q
当然,还有其他刷题的网站,不过,其他网站没刷过,不大清除如何。
! ^. D1 j" ]8 T; s- W' x
+ J+ Y7 F3 \0 X C7 ~( c |至于leetcode,有中文版和英文版
8 _; G" g, l- f3 g% n/ @
5 k& }; L: ^* _& x3 r$ ?+ Z' _+ j. ]leetcode有中文版
' v% ?5 ?6 b& i+ h+ P# Y x4 F- y5 d! x( k! t- o4 N8 _
英文版% _4 K1 K3 {: |3 t0 D0 n
9 O# e$ A. l1 m) T7 j9 X根据自己的兴趣选。
. w1 p+ O O) u: p2 `5 @' G/ O8 h# G% w3 i
学习一些解题技巧9 |% U: i' V! O8 l
) q9 A6 I0 f+ m+ M/ c说实话,有些题在你没看别人的解法前,你好不知道有这么美妙优雅的解法,看了之后,卧槽,居然还可以这样。而我们在刷题的过程中,就要不断累积这些技巧,当你累计多了,你就会形成一种) f% Q$ r: u6 r& Q6 q8 h" n. @) H. V
神经反应,一下子就想到了某种方法。解题技巧很多,例如数组下标法、位图法、双指针等等,我自己也分享过一篇总结一些算法技巧的文章- q# z# q# ]& W p
F8 _! X5 N! }% m1 K) H推荐阅读:一些常用的算法技巧总结
F3 O) Q( \$ [/ ~
. N( R. m! B4 S& G! A6 {例如在刷题的时候,我们要学会巧用双指针、数组下标法、位运算等等技巧来解决问题,可能会有意想不到的效果。我给你再找点我之前写文章的一些例子吧:0 ^* ?1 ~& {' Z6 p: m, x" S
q) t/ ~2 H( `( G3 X分享一道解法巧妙的算法题
* k0 k0 |( R6 F2 _! T$ f! G) b# Z- X# C, d( w
【算法技巧】位运算装逼指南. Z" M! x7 K# g. Q: C4 X
$ J4 ^: T. N4 w$ x' d, p! w4 y# B
这是个长期累积的过程,我自己也精彩在我的公众号里分享一些解题的文章,感兴趣的可以关注我的公众号:帅地玩编程。
+ H: O1 ^4 u+ [
' K+ s+ r- d% t4 d再说数据结构发重要性
$ v7 c4 w! e1 K; t4 I0 b4 s3 v2 e0 E: t* d
前面我主要是说了我平时都是怎么学习算法的。在数据结构方法,我只是列举了你们一定要学习链表和树(二叉堆),但这是最基本的,刷题之前要掌握的,对于数据结构,我列举下一些比较重要的:
7 A& W4 `9 w9 w
/ V1 F1 O- X3 R. \1、链表(如单向链表、双向链表)。 [- L) o4 c8 _1 i
( ~3 I, c/ r' S% d; ^4 Q2、树(如二叉树、平衡树、红黑树)。1 v0 D4 ^1 ]3 e4 Q( i: \ e
& }! {' Q9 M8 c. \- M
3、图(如最短路径的几种算法)。9 r8 U0 y" ]- H* z) o1 y$ x
% M# Q' \% r' z0 e$ y4、队列、栈、矩阵。8 V: @4 Y3 m' _
- r9 K! ~6 X8 R4 Z
对于这些,自己一定要动手实现一遍。你可以看书,也可以看视频,新手可以先看视频,不过前期可以看视频,之后我建议是一定要看书。
) G# N7 L: J, L! S, N+ L/ ^
0 m; g( T2 b( G/ a" `例如对于平衡树,可能你跟着书本的代码实现之后,过阵子你就忘记,不过这不要紧,虽然你忘记了,但是如果你之前用代码实现过,理解过,那么当你再次看到的时候,会很快就记起来,很快就知道思路,而且你的抽象能力等等会在不知不觉中提升起来。之后再学习红黑树啊,什么数据结构啊,都会学的很快。
; s ]! \! _% A
- G7 P9 b" q) i对于有哪些值得学习的算法,我之前也总结过,这里推荐给大家程序员必须掌握的核心算法有哪些?,这篇文章居然 40多万阅读量了,有点受宠若惊。
1 h0 |) `, b3 k4 y, ^
. }8 X- O4 ?6 _" |/ R最最重要$ [# w; N2 _; w5 k
; ]6 D* @( T$ i' K/ _# |! t动手去做,动手去做,动手去做。重要的话说三遍。
4 `4 G1 z* S' Q* p( ?$ @" q1 P# C/ \5 F+ V
千万不要找了一堆资源,订好了学习计划,我要留到某某天就来去做…/ ?1 h# `' o1 R7 H
/ d9 n3 V1 p, I& @5 m
千万不要这样,而是当你激情来的时候,就马上去干,千万不要留到某个放假日啊什么鬼了,很多这种想法的人,最后会啥也没做的。
4 e; s" K# ?# }9 D( ~/ z, E4 D" E5 l& p0 o
也不要觉得要学习的有好多啊,不知道从哪学习起。我上面说了,可以先学习最基本的,然后刷题,刷题是一个需要长期坚持的事情,一年,两年。在刷题的过程中,可以穿插和学习其他数据结构。$ \) {5 V, |- @" L
! T! V% m* T, R* O0 P* |) s3 s" m% @总结一下吧6 v# ~* i' {0 P5 c* H0 X* x
+ Q! A- `$ L; g8 F
所以我给大家的建议就是,先学习基本的数据结构以及算法思想,不要盲目刷题,接着刷题的过程中,不能得过且过,尽量追求最优解,还有就是要跳出舒适区,逼自己成长,刷题的过程中,要学会分类总结。
4 j/ M8 T+ V) i$ Q
' M1 ?; b7 E& x. T {当然,最重要的,就是你去动手了,不然,一切免谈!
. i. k* m4 b$ o2 a) \" D
1 {/ Z3 J1 e6 u1 Z D% r; `看在熬夜写过的份上,送我个赞呗,嘻嘻。
0 j' P/ m+ _/ ?% H9 w" X————————————————+ F2 C/ m( v' F
版权声明:本文为CSDN博主「帅地」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。9 e# Y& G3 j0 }' I6 Z& i
原文链接:https://blog.csdn.net/m0_37907797/article/details/104765116
$ Q H* c& P5 W8 {! g% R7 L+ q0 m1 e+ I
6 Q( G* U- M% D5 ~
|
zan
|