From 25ea11eabc986402f2c094e073993eed4b036918 Mon Sep 17 00:00:00 2001 From: krahets Date: Mon, 22 Jan 2024 19:05:45 +0800 Subject: [PATCH] deploy --- assets/hero/astronaut.png | Bin 0 -> 131111 bytes assets/hero/chapter_array_and_linkedlist.png | Bin 0 -> 25882 bytes assets/hero/chapter_backtracking.png | Bin 0 -> 15078 bytes .../hero/chapter_computational_complexity.png | Bin 0 -> 10586 bytes assets/hero/chapter_divide_and_conquer.png | Bin 0 -> 23079 bytes assets/hero/chapter_dynamic_programming.png | Bin 0 -> 16204 bytes assets/hero/chapter_graph.png | Bin 0 -> 17701 bytes assets/hero/chapter_greedy.png | Bin 0 -> 16716 bytes assets/hero/chapter_hashing.png | Bin 0 -> 13355 bytes assets/hero/chapter_heap.png | Bin 0 -> 9370 bytes assets/hero/chapter_searching.png | Bin 0 -> 10385 bytes assets/hero/chapter_sorting.png | Bin 0 -> 7815 bytes assets/hero/chapter_stack_and_queue.png | Bin 0 -> 12348 bytes assets/hero/chapter_tree.png | Bin 0 -> 14813 bytes assets/hero/ground.png | Bin 0 -> 93650 bytes assets/hero/links.png | Bin 0 -> 135133 bytes assets/hero/pdf_ipad.png | Bin 0 -> 74473 bytes assets/hero/universe_bg.png | Bin 0 -> 73373 bytes assets/hero/web_iphone.png | Bin 0 -> 59658 bytes assets/hero/web_mac.png | Bin 0 -> 86914 bytes assets/images/logo.png | Bin 8188 -> 3448 bytes .../iteration_and_recursion/index.html | 2 +- en/assets/images/logo.png | Bin 8188 -> 3448 bytes .../iteration_and_recursion/index.html | 2 +- en/index.html | 3 +- en/search/search_index.json | 2 +- en/sitemap.xml | 64 +-- en/sitemap.xml.gz | Bin 477 -> 476 bytes en/stylesheets/extra.css | 180 +++++++ index.html | 489 +++++++++++++----- search/search_index.json | 2 +- sitemap.xml | 208 ++++---- sitemap.xml.gz | Bin 999 -> 999 bytes stylesheets/extra.css | 180 +++++++ 34 files changed, 850 insertions(+), 282 deletions(-) create mode 100644 assets/hero/astronaut.png create mode 100644 assets/hero/chapter_array_and_linkedlist.png create mode 100644 assets/hero/chapter_backtracking.png create mode 100644 assets/hero/chapter_computational_complexity.png create mode 100644 assets/hero/chapter_divide_and_conquer.png create mode 100644 assets/hero/chapter_dynamic_programming.png create mode 100644 assets/hero/chapter_graph.png create mode 100644 assets/hero/chapter_greedy.png create mode 100644 assets/hero/chapter_hashing.png create mode 100644 assets/hero/chapter_heap.png create mode 100644 assets/hero/chapter_searching.png create mode 100644 assets/hero/chapter_sorting.png create mode 100644 assets/hero/chapter_stack_and_queue.png create mode 100644 assets/hero/chapter_tree.png create mode 100644 assets/hero/ground.png create mode 100644 assets/hero/links.png create mode 100644 assets/hero/pdf_ipad.png create mode 100644 assets/hero/universe_bg.png create mode 100644 assets/hero/web_iphone.png create mode 100644 assets/hero/web_mac.png diff --git a/assets/hero/astronaut.png b/assets/hero/astronaut.png new file mode 100644 index 0000000000000000000000000000000000000000..2d63a9f7a494f99f7f36c43191059b2f1e275b43 GIT binary patch literal 131111 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
>S5l|9G?7;r6yom$4BL#tpId*Fy z#emuteg>@wB0Ixjuw3Q0cZTwqju~e12{IN-6`V*dlEWY;FFC#<3?0T6nqL*0t;KA% z+Ql3q;=*ArHe}Kdg1_|)=8PEj~cm*q0ug{KfrG^V8I{Ru)-_+(kJ61oG6&gXB zKjcz@0z#65&n8MoX8KOF&9;+=?r0&XsewYEJc2e-LLPL+fLK%dB0}PU6hpJ>5>+!$=0Te&c1P~gZ8;FFVicce}89K*H zLKCwH1NJ?sd-kM4${f>T7rbayRi(c?44$1UC>TLhPy-N3O%Mw>z;kXR0fK3`-d89G z0+p4>6*-bcu+^yMOp+}@4=B5RBsqRWsC-5cSeKKPm?*MQ3<#_!8H+hw6@y6#KxW{0 zkch>Apj;roaQ@)BSSgTx0qRWtCly(XLs9ALtxM9zLGau#-G!tE4O zdSKas@fzkIkAb(1)77m58a1!V^xfZi@7j*?5ScgLo}TW5$d5 z*AXKkA4Kv3%+TyDflPdgEgNjDUF%?AsHvl)si|pzlBPXnWuc;~E{o+vaQ+i*ck z&$F(s9z+Jn7Mo6^hTPWPW--+amdb@*PmqLZd)D)?ZEO~W(6lYgYU8;f@=b_k!yOdLmj~^w|l?WEp zU_T9nT2r!S&6*{!h#=%6g2vsSjvqXD&%VDH3{)1d{%{Pu{ZLnZ+DlzO_}$g*M|bT) zy_g#Rbc=zYMs#~icG~*m#|Z)?8g$HvKxotp%QJhF;|c~!^IHz)*5-8`D=?;J71q`k z60ujIR0IalQmnv*B9_Qtw3Xw6_27vUt&Zbmozvsvz~M)eRw$O$l=k(uBA#gNZJ-8# z=H^rhcZ&kM%XJ(K6-IB+3&jchaQkrbd>la3n&nf z6Vv2cm7&pEk806)-ynDxGzjS&jlx4#VJ@gKVV6yFwL^5tEB3=97=AeSK(~KF=`oV5 zi>nE=8!)wkbP~JKMs=ErIOG)*Y!LD_Wn{rn$+K<_7*%ALEhS|Q@o|Yeu$ss@2yu85 zh@~S#EJWpFs$^&=Vl+B8fm(q8S+i@CQwRY6`1PI2Wn?#ru7=J1gB`PZ?^$KFsb~DV zZC`_c#Xbp1NzjogJ4vcN#@R-ezU70J(Zm|8haw21xl+L)5y~EjR9HQX-lGC-;vU7+ ziSmk6hctnKh@#-m)S;oOE{|v3&qs%<3QqTzcN7{85V8S4kI9#?rlb|5fTkL2Ld|XgOOAf)5Al`=Eya?DvALHo$0uSFCjqAVG%?ee>vh$6AsjI?Er8fj8d$QCB(s$yeLHPQM);VbIgilO$7TYV@fKl4YrGtsk;ibWN2cdE1V z(?b{@^iZokJkXZUM1Mcq6W@{>Dcdl;Phk*5mQA2w2!jyFb#)@(;!G9577MJwZ6#%O zelsU6uQ5n`w5N>N5D1AY z?OL!P$IU|s4xP?+dw8@o>!u?F=31Vx=FAx@tEk(kx4HZl0}N8e3Juu1W=VQ(gvy1_ zcXXtZ!39UdvRwR9_!`k9qH~|GDVV<6F`fQ+p8BL|wy$8{EN0G8qIog<{~3 zw7C2&!86qQ29OM#k@#`Bq-@9LqdA1hcEN?2vZUQm1|&pC56Q;NIS9bd46yH+t?|8nOi;M6i;b_zCCyN7qK;?y3AdtcTmKqel@S!yCk@ zgNvswU&rFA%1Y>gc?RTvCk0coXd>ii&J9BbQT~S_W}&uz&*Y9Cb8xD6HKxRoxb&q9V2sBL$|uK8wAy zv)skZ{S^av+!O+VOV=#TjBw%4_qniHzK4(BPA6-rwk^nBr%)5_Xp%d~k>6YEvvb?t z%}W5mQa8kipMMS%E}r`I`X{}AOg-?vvTCrcz;gNe-~HXyt6w5i#;-dMrA45Rj4bnW zi42V7l|8v(u=(QkYj->R0;;0|WWN7EvwYf+^Ge znU?SqJrV@+)HV?3IYZL?QPWfIXEVsNQk@782%I3`SA1f?rfBJwHl8-%Jc`X|({R8* zk*H|UMl*Anzh(d*F7Dc(%~44uY)5GuCow$(&!uB$$t$vRo&pjDlID4;g*qTDa-Wc! zm3i^lr`yQh-d)&02LF#FO;Uo+ zEk9Ty!n__MaGh8nO5FWr3etu15JXUM;Q|AwDYK`}wD$O3NzH5Tew~5V;GzqdB$Le) z)z1uuo2H}-cP!}yg?+-(@PZzz#AejgHbMUrAr#Div^{uUmTEI9T1q8VCcU(%)ZAs0 z^WYB@$yGL*XkHJ%F3k%daFwMk4Jf0rsXZ5b9w+qNA;-J_67JffH;PIWk(?10?nM#b z7oEpzHsb@4aZ38S3u>O-@<}VTr+3AEtg-!p$ekZ329CfM{Bam~>rYb;D-nWMescZO zQ@Hzfh?3p-rXVs5NLc^DsYpQ+aQ=Mmftc}tRBd@R)xh2W~yx7x0{R$m$ zE9_RPQE%`d3>4`l{rAmPHnB!jUv6ZvHEg|;0XTuLx&!W!hjwSNSX6V1$A#nD2>?4U zVKY@ktcpw4USN!k5+*~0%^JBrQ9CIR)<8CUdoMnBLFo~D1vk#%4wBZA;tkYq9IH!p zmOqLfc;mf4$(7G~bqR~1s?-4MZ3`k4!3*<>x6g4L&3KtltZNgm}y0Ot$kJhjg;TFAA>|}s} zAA|v6Pw=s4<;IzMJDW{b6EM+=9&0ZI4Yia?crx3cHKjLt^ps9H7^tnXGC6V~o0JGy z`a&>35O|FNSMmC&96p~x2;ht!BFkuYC*)`uOcD*cvq}A!5+)P-O*|lMQEXXKCg6wv z3opPM3r^%}uZ-MFm;d&Y6~!BH-D*Lc4E*0;MDpf4m<#or`sMHAn@6S;3Mu+}jg7cz zeDm7Hi`%>x-#(X#iS4M6Y~%x?S02Yi34;j=60_I)=Qx%Wzv>YX2ACeE{1JKCO=PGJB8K~4CHXEhbl`a+(x%iJ{~^FZRr3s0Df z%gTk&1UZTJDTBeI@${6@LNQ>pauDgklpuQH;?N>x30{N1^+HGzi-l+GE;+az0HoAq ziC82dz~}mwl&E~?&t|wIN)&@3j#!G|P|A%>L~?8|>;kU2r$-9aUY_eWd4KuoCo9OU zL&zUV54`yfd#3B*WJ6^o+Gl&GhkN|UzCN}F=@J)17KsM~)~`xP@peO+cqLgnvOdt4 z!=;)@S5y0lqGMebzUR~fU@D5v4vQo1%d985hW0ElkUAJVsMni)wTiB@;Z{YSkVNM5 z-T)}rHw7o5u}CIqvMXxNhMzrlqPwV|r>jEm0&OiFLe?lT(d<`fS5#39$olVhRMj)Y z=nke+je{^s|B?Z|XOfl;b-?qyjkP6Fi7EmBAD!+fVZ^H7@4^=F=_2jHb^hp(NT&)3 zY0+7co*bqs3t185#$xuyY&ow`dZ_$2e!cl3mbWjPR|e=l1_S#4+j`&)%#%$##l&ZG z=O>@u`Sh#rTCr5r?8igX1(Rq?z9=-!ZEwihz|5320hwewIUrcez)m?9QyWcL1Cl4A zGZq+tJrLBKo%Pe+*PBmN85S5QBMg*?%p%oHd$=jD3jM_*I;!-fZbEP}3e;ZPp&Mtya-x@-y@kJy73hW^$OYm;L@q<-+lMPNS9Q|!c9*S6-q_9DQnhcLA`4q;Xi9B)I#Qe3QAjaRqnB9fEA%psPypR6##i9@yB#v0 zt$=b+sa%1;sP`A!>I?wDRaBT-Hl$*(kOAc}OGXm{&?^=2(b0`g34xGhD@$U$ccuhn zj^gC@Xxi3heE zGVlK5*Qkwc$I-8gm%sYzQHzYnr>?xiRnjJ`*^&{O5RgtmfTyly5kJt?)iW>})uXkz zQR(yu9Gm@xwqrjGUAS+qIAg7N#TF0-hUhINgn_f&HP)7vswy0hsB|!WmIk1Tc=RX`*pVHb6BrR1 zO9Y2-$vWmJOxj{7A*rb@>D*60J-+)bU8-%mvPXOG{PC#EpHz~o=y59yEH3T;tRi^x zPc#N^Y7z*LVqEhN-)uj+c?|^F(WMtbK`o8Pq~d)X4+{(mIhYZh8FHI~U_DM3G3ZqD zkSY)sLG)^P2oW}(_{1zO>X+WTk549g_6>8kJ9_cQQLoEGJA<|~u1H1=!>A{dSoACCB z`$we-kQ`8Qd3#7BBS0?g@Z_}saZ>DxuD-{9W-?t*yKx{XMlo{B0=IAurn%@=SmZ4MJ%e> zm?pijdeg3>kGHIh74cypT%Ab*^pY|-7kqtz1NPzVL8`K>Fg7D2B75Vep!7rET>dV< z^UgPy(y^fJ(y5z6O0Tl($w#0F#4fb|i|ysOP&4tYrRQPs{z+3!P5YT+$GQs|t&jfp z({D1f({>{g#DwmqpiL=JqZ~F3Sr?)TGP1Y$BT1ANJ+BDnQ-e$(@EQYbeP?Hfc%W#; z)c#uG&=g$VBsUwYA~edb?wZCaWgbM}J5*>JKnQT=#AyN7CbjenZMA};QbkR7+U?BS zw@p?7>&#ibkQF%aVA+cOPs%!&5=)h+zYz@ZTG~|>L;V@Et#qo$#^cZ&5Kz@ir+Grj zD0k=1L>`#s(wQ`h3+efdyFS_x9ZBklu0&YiSR}$wH9AKzRO?HZu}J|LA!Om6x~81K zz?Es~+aEs;`tqyR=1(47S_Ajl?NpOTo~TrZnWRSf|H0emZ@x1%H@PAi`+thD++(<) z%g=5(bM{#2&E1zSUdjwqg(i4=V^AOP2Q1x@0rN>`INHato)mYB904H{4}RfW{#xmf zjRmz$7dr0GSi1GKP^&K)s1ELzHyXQ2)B?JNEU4-(D({)_piod?HJDIo?oia!NWnmP z_e{ab1j4|hdI9_7S(T8TwWnq5skOGFgD$l+atQ-W!En2w-*Eb*y|H_u#wz5Hzuln+ zh>oJl1yBP)do#I66e4=0N{OxnfgL$2S9b`N8WQ80Wn|>RgKL*BUpG36@Ck2miAv^lx=`#awp0tHE|JlVAFNc>aH|E-5cjr@+BW_N{AGbX%dodXT?SX0>=q6 zl`F9Y^Ic@Gm+Zx|?$#$4Y^O=0@YSMG5n-Up?$CmkSGWU zMfHjri_m5hT2K0!Pu39zZkF?S-DeF#iM^@T9+8vU(ZThoG5Zk)SRQRAZND817`nR( z>K7PTP)yMK5pJ*qG-nl&(gKe+Ws?JmG~e@)%U9yCRY*GIqodomrxV#2a{D$yh3#k? z*aY(*h}+v}ZLCM$^jgZAqaR(m-kMz5Fn#CHPmkAWlogejfibfG@AQ+s@%H=gB4Sqj zTwGmEMnN&+TiTgl-Q4iQr+1nz$k$!_G9>^9OrtUbF}%Oq4G?@3l(1#XK_>OQsma0| zR1K)`5K%WYKmE5DV2Gvd`OkgLr!UyfR3XLN0dY2y1>ck#3l+oplOru%Q+Y&Y&^cOE zN_Nztr>yU!N^P+SYHdRENrT~J-4--<-0bIjm7X>5*h8?-#9iB?SJc?(prVEQwQ6K=Npz^zRKE_jxJj;^V@eYW~kGDSZ1~B={JM zJbtdO9xt!b%OMDV227p7oj=_9^v(8l5SdDyi8|}LYA?KLLjxHLQ!s$m7AqZ zv4^QfWf`Iv=&=^D#ZKe200HuZ-1NO!?zDLZXzcSLi85*AmR);MJRt6`Q_wfywwVZ( zEhL}8>t=i!K~lO;-JTBn)QqI6{{HDxQI8)--9a}IFes`OlEa{JL8jEqpNtKsp(q#^9i*_@aO)6&t^IUd;AQ%ke$<5#~s|(L9j87(HTZ z&}9S$sA-a=Kmb?W$?iRnK)qn5U^BwVfJ--e6e)+{(fDvyfU#q?3!ufB%JqHRtxqs?Zts>%@+tS_X zBx|--tk7l#A%(I9gM>&7(wyf;Tp8NHRe?|g3nt)SGBBcR8>(uz(~ep2SWyOMv3QKs zS~L)piuLt=VssI*Tq>$;^%yt2(+$DMp{2mu^Gi?Lv2MMu7Ja{Z1DmHe8tsjZMjEfN zoGWIjI`*W(BP>icD(lN-9X5$rEGRD$osO+PVUv^=RP?*ZNnk*mhk)oPQZow3bm3DB zxX>=pX*nxDSo6hIpTt-#Ib*N}0t)bk$HuwZ5iU%Y+et#{s)O8vT?&0(9%g98W1>?XE=J}Dnfm7M?fc;>0^zPoekQ>#KtAV|v&*|9#5t0(~kPz3(eG$~vvN5Y7S0YeG_#_uq| z5X?0{Dy%4~6`nC6K5Xpik)fzpTh`PX+)bY-uds8)9F|7I6KdE@KSN<{$G{b|ZJ!2| zSc;q~;-c@@Rlr6=l14*1e`z#q!9;%m7$~f-FDbL?!r_KV4XFkd~HD zSoG}I7{G5G4CL}%2?HD#Nr_gQz47YKB!i3_nii0Pvo?+fLVUOdC7jDCON!d*4U<4I z;E*NrvU%68UEW__FD<~j#lkDsf`0lIxuS;RTJ=gd`IwWrUVtSLFaF743e@2)@kv`L}ey?D1zPGDNv z`c=LjqJ*H3%v^s=8FTq0-f{>HBj)qJh0J^43k(Q*^6w1kZCZuJg2ga31t+XL78pPS z!Ab5!O+|-_O_DNT2$fsv`hahVwvdc@CA}!~MFkN{0}4Ba=p4re0UA;e3^0%i2CVg- zwdOplMN-%yV{$OwY7zAJ%Y~9s%ap~yqrYST@{)l>cP2G?#=4MYSikpbouA@-Ldq9c zL4dbg02!o7$OI2)mkP=8^ew!xZ7&6ZQ=kN#5a2i4cWu6WtaW%IPZ@jVzR$XEx9t7_ z!|_MLZn^w#V*v5rd+)vTr$sC#f&jtP&rct$h>J&Yu&oWV{m;L-gA?zcG$)hKbf0Xi z5|<2gcQ>6s9DO_G^5s*f>ebra0lVu0BcstfEK&f1^aK=!vN2NZNWeOha86lpzwqlq z4{C2}yJsWbYN`DdbQzz3z~T}HI_gEW9m+4HwMIR6h0K?JkpXzj#!&7-)SvPO4I{)pJhPb!`1}67^3j+Xv%V7(J z9y1dU+h$9PDg<-T`^}ZT2xW@H;*X5=bXjNn9;N>yWcxRt#KUvD*_z+ibfM(tsajc~ z&t^BY&lf5qkQYdbWJE--jF2gO69O`${nwLCGq1eIUiH1Gck?^~)RPr^DP`@g24zQh zX+P%7TWXBx_;N5{oG~@p%sdVr&uj9MEe4*J%-*yI@}h~%DWbceL`0MDXkfq&1`6vH zRTieIqXG7H6d$QL=!-8l?bwo#7RYs% zkfMh}6){j9<@rWO!9xgGE8qq0-Wx+bbwEH+a0>YhRKY2HFZa(0l;YH)rt{}t>7WWMMV2YNC*T8WYRp+mG&Eg z;9z0cj1n3T8!Xyd!}ASl#nB^|YPgT5Aez*f&K9PsF}&_wkHjGD6zwHz#lVR%?d6}EDB=C2rlFkC%z zwQK^W`&zdfGWn)2)`YCSyCYhKQUPrNJP2tsElKc>`7GwPuacP^1%p5tgQX4-oHhZn z>+zip8^V&uCe&W~C;bQSJ&D^;^}m9FH{W>|iF%>r*^dvBNk2e!^Yrk~&t@boMWx-B zFMf_U{?}-R`>MJ3=K9-r`o7uz^{!oCAN{5^*rME5hb-}x(7IEp9)?4htJ`@)rpQ58 zU9MIV5gi>XMRX95w9=m}ApG^?cX5~k2LldEAof!0%ljzj(=L!<>$_0jUEXMMVX=l% zYrBJ6ZOS66xn9a~7W-d^08fgj70kKHJOn&EW8ackJJw_q6gnzu_v|4I*a!F(7A~j5 z4#$#js29O4V4%JrZ7g@}#Q60W$qLQ!r9nYSSEURoLcaJYd-aYTfgE=x`J!bg7&#Y~ z5LLlpi=*B4Zr;0el}4=s4x632!11vF!Nxnu8#cr@^a#D==Kh1{55zV8&ohAVp9_pV zrhcAGu14;+y~twf(^aEK^v5pAOjmjP^~>I06FGY6lg=;kdgsoiqr298{`Jz%V2j$T z_M0y+Us_rBWtpPH$1PyZwnPthnNLVswl6y?I=aNeL+i6U`-Am(>-1NBa&ylt^^oF$RC6kCb!UUW`>kvnRUDx1d#n976X&Rt2kCF6`If3 z3}7I(BkOc<{y?6k-)xbIUsVGP$U?;l47e1^rc6aGM!ifTC3o*M8vB5aI0+Gj17JY! zXVJ^S0G%P@+EjAFK-EdT(Zm%~6Y#GBKnaJ7FO|Uxwfk<`1O&1@-Cdz<_$(wzzg@Q~ zgQ|TqsDcwRiNZ+CC~yAEZM|5{h+gba1xuU+Kn^Vq00u{Ik7I>7Dg}J9+3smv<9`DK zZy=U?7xJg~-+BA3H~*ud;JXYK4_@FjH1N2UMi#5-ds@(N}mZNGML&8}UWzWM&nrmwM9<`Gc?e_GB_AOOEGc*ax-Co#_ceG0lIvm z)O7NUfk(J}Rh(OLC{}4)*{U^n?|u}`U~_P7L5$4U@#T>!5rZ)w(LhKSx^}VmVyJ?k zNH4F9v^6gc!ctJ+z+ed=crgtKJ`Q^-#!PmP#X|<}=h1Zs(T)Vx^$HP6*Eog~1n(rb*GP9#S1=`V3Uw0nYC(3_4 zwTR4N0OlEZRSj@7H4XxT`>b@eQh=Tfx}xfAkw9kZma!SEp^jQpb+tulJzdo=V!a++ zzQzFTO06Hp&IV7M4Mua(v6}-nuh^yznZBv1uy8G+o1J7Q_1OqgikuboNn9d%9 z-63Ba{dEc`!JmtCkvMH5g#e8P0+z2^j?>x1Gi1CvqY9163tb$8$BxAwJ}d1|kH8MSEAE$C?(!`>_qK*_S?W(2gdrk#6teGLe3QF_yoP2cpL z+5{$!Ub=p!Q7NcRIeN`!`xg;Pzl5b9#Uvn7kMKeFm{dA68p`5(L|jbxz#k1{FNMBP zE<*54L@XW*ZiOo9vx?P9x!GiALlFpy&Nk-NoG|hz28ybyiE$x z;_XW|UF$n_6bu}?bp51W>7L|v`^KTqeE1$EyMvB;lm5HJpzP=pg(xda#OF)vuK6EV zxl+;pYlA!s+JLDsg$L)C+T=<#qr5Y?+UNy3gp#(>f+q!jOo{;%k4=iMlRX6nHtp9Q z{40MLjah4$89dR1meSGMzJ4&k7Bw}w$o4eV5(WnBl5(TaV5e~y@ElYu8We$`>evZ` zQYK|_o$-p}$vYu+%$`WJAsZ7!?leBzj zpX)Y2tu0=~I^?dYa8K~ZkkAGxbtZ!AvRy~{ho!#yi% z!8K1QL06j*5JW%6^rByagw63 zzC_4`KVaWeTZ7`UV&Y7T)&6S+7RnB!XNgs7SCk$bcu|J}LSNCrJ@u|!Fd*+}svT-7 z5fKLLLcJaNUou|g!XYax#N|e5#m^(|Oa}w>Ut1VD7>L}Mp2cTzJh5vR9T5J@Gkj6` zaBM6h$wJ4CWo#(9u-tDTO{mhy?p4>m)n238<2T!d5O)`*KV!g$(b&+ci(oz3V#m4SFOuTVaeZ15fCd0u%If}=EsWa9_JNxxW{`Kh~hPbv+Vao4s zdj9;%lkuX1spT%TjsdPPwW-$FR3RE@#AGs$Fo38I?wz0BkI&jCR95x1HP5Lz^UD8K z2B@4NKXPM;isu^|z1n{zMkSE||KOl63s0U&R-hdkmIJx{_&d;x_s;de{K(99# z&Gr4JLCgwb?f2X;o;f}!IpFw!EW0)EgYK!s%OiB@-mgDj6IhnA6cC)cxP6yfZsy*- zm%Ef6quvQVdzY5DyO;QU6cg?4!Y;vC<5($8>xpMB)qWXr{QOuv&YUc-YGgAQzoQ7q0~8n5DlBKOycigG@uJ;yu&i9f z>KG6SQU_`cO$P2j;f%GAC$e*yBr5@LsAc%+9QFrE+WQ)sy9Ce#_(Oj6B~lDzgyeEO zSFHyD$a~@g6!=GSeKR5>muF)Y(Z=+Tf&vy}+YG)n0Z{>@x03h)Sk>vh?aMDOU&huf zY`Op8hezLBI)p~cHGB6SR*b}vJ6p^Ci?QKbE-t)h&DXbII<@1cI-fKYGRv59p|7E( zbg;C%agj_e&_68>+mPHaka6#xdAK2L12ycp;np}g8;jY1o(ex~1y^fCw)WP_hGoPE zyzUDS2v!`}`ooJKs@tSOg?7znU&jQUPf9`G#O{krkH+{6MSXVlriX`X(B_bsZ8`3) z?xX3OLS%ebcC=6QS_xk(Vv-f`H&V{?sfX?IFXA~zzXpeHwpz_9jh9>`5;O)|gd7@I z#V)+^0`q;CQ7zm)1ot0k`YOa z%?A=$8J(NvpR;OJ;L4C7vWYe%gxXu0ogGbP=(4lZG6TH52?coX?^@z^@yp9!bvDOi zk^1+u&tLf8jfuLaej0{z7jb5}=uSuGjS7!Ywph^%;JJ44wt$20#m0}KvVM7quNE^-Zv$*yW>6AIf;aD{XR3}xzz7bpSR z3sL>Cp@D#&S8DN7@t97Z-C4DHohz{&i>JaLjo!{Y^rFqQHtUI&ojRZw)YhdMF^AS< zn`tpixkf)3{w#Rx2Vj5NKti;i>#63x*0!SJNL|9d& z@Zgc#WmGnVm=YqdJ~gqiL(vj`dT11Z!SmVWIZtBQHZV}w)By%$O{ri&?qU$hXcPk- zJHr|c)fkuxy~#ly=sGzSBM z>g35DTT$us*v}Ia*75x5D%^@3$*-J#T?tSxm+mave_+MAviJr+jjLdl_nN&49z!=$ z)@*lMy8ZK=h7#|Xi-jKU+NCjW-dXMl32rYT10#IEy}}P#Os0kuP}wT2w5s4Ta`GPn3`2atr#2(KBLMTIg7)#7BrF? zV8qDv2ox3RuL)9uGhN|l+fC1}qz<%;xm1UR^_#fVq&rfKHe%P1D3{vvGYZ)?Ivf-TJ#&Se+Kg;PEAnGe;TgSAOt{ z009Wb?Ab^eIa7rc1gN!rz3bwqD*!=q-1G=N?`izjuyH2+zp|q4Jvw3F)aI0*27Y*S z1sj5!v@CqbT?}-}4B(<-U&p?C&%gUFwKP097>~Z2#_`oLKefJ~FTZlQ zVy36J8b=+J1^K<>E1>>gu>^Rzb7=pE`SaD*4+pfiKOLlE* z@<{XEc0=MWNdp{7$el<=mn7gs4Ld99Tn3*jqWm{WQXL{XiUEJ&5T^G5~ z-lAMwKp?T1<(iTj1B=FrRq-NTl$Ef!5oih_)91##nezN_LU4ZT;JB&AYBqA&Jcm}` zIR8YJs!67(!3K(B$ByNn7_ilJ2n(GI*lJ}RV8AM;I~af#t+7p1R#&#DMO_+oOT%oj zt{2Mgm4=3S2H@0iac;$*%UX9A$2rpyc7y~aXxS_p1u`pg{Yordoc}>-f#b(RT^UT_ zajYnO*+GDA^Icy9gHsI~HsG{QLsiB8xQ~xC%0>T$Ig_`b2gY=NyLs2QZGY=?E-k5U zkDgEbE4jMr7L@*mVpF6>`{=vxu2_HohICIB8FAVfR%k_KGs<)OdvGkw+z_1nbV@oK z+zxy2B)@&Oc>ja>$iSfp8a90cFg85;_Iq86g5fSskBLc_7A7XSQHmhNRqqz#J>=m& z#bdjNhf+V%K8TcJI0RMh*1Q`kW`^-(H^#c2V!NcCvVX)a`9rcoy`j-qatPi6tmCi-jC6OUWAEu%Vc;2gP#&wL&(WTwQ5ZjNqoA5@S5i zCzEe2KtRQc-#ota;eizmcW=k{PG}gsjK!btjgZu3)x|7X8nAJ1p)zUb-b{%*J#$;k z8ZA<3zPA@gvRzodK0%Ru(kevK?V)v!?Zgb+Dny3$WlX^1-l*j-qRs2V_n`!BqEPQWR+$<5Br%L5|u}Z-JcTa7JST567wT#U6k@5mX0#N8ADA)~LwwGGGXQ0Dg zLX%Sa%spg!iK5WSK&?%d+9Wa8i)kv6BS_^)3;HYcYHMXR^q`k)x*ZMw%jN`P2Ka!? z7ma9+dyJ8*{SO{rzY^DY)~)*>I}`JC*`AoFB>z?X4FC17>Vf0O*GE9#xnD?+q3VVK z|lj_J7_fWaBVX!`+|0FWo{Iu*+z4 zv6?#xC9o{4p==+g3F~3*7j}k&0K3LZ%oWR9hPmnjqzdxMcQ5%zsX#z>G3aW94}<&k zYTV4BgYyeLo6sUw7Fq&7UMTZ3T1VQ(iBh11G7zPv0##P6 z4R=q_IYL^=^fZ}YZIgkA;<2H&gAN9I%4JLu*ST*(tS^dHwpF9c&*~*tBPh9rgI5nd z*m&$tStuQ$nPBzm^~e2Jt@6)ay>6X<0wCCdf(Yd}utaOg+AXIhIKF;;s0)+sF222& z(gFcXqe%5|cS2dAy>{UK_3w_g_Es*#8FcI;fg%uc0l{1U>17ba7$o1x{N&Evb7=`l zFaBEh{#x$PXqEJe3G|f}VzW zokiFdJkC*0w4Sc5{QlO0H6W3}(SN+O|HG}H{^RXlU5^0e)AY}_MTk=(^ijLq61TYN zJu>%xRtB#S^^s@{_bbzt0aV*Vnq^q zNi0SW9Ji2w4Hy`DvBywY&#fJhHI~zu3$uk%bH8k|S~t#AH*$r_g2Ay50l|+F7JY#M z2IJ+)owe`JOIli8tpsVIxeZ}hc$D0p zp((uc)mL9#&#;DvpXN&1@q71pqfS67aBRqPL2LE?kzu)nWRvjtrZI$gi`R&|?P z*^=Kh&^-RKSa5(afcg1L`#=8v=s!NvP5a4Rcxz$#g}G6@p~Y@>YhwzPg-{H1cNdJE zr!n~mqn4b5zsyb`3^>ATSEzJX2IW2#*0Sa^yV47pSL+rrY45)h>9CpO!PRa0ClwWF z9E2ud5(pq!IZdTSWoQx{aNN%=L(E7ujcP@7i9|w37{)nVpkRru#pwdMd>?iblFq_Z z41XIP3^aiOIyw+sUpA7%p{nVasvK9VM|87jJ!TSKKy=7)pF_WYaeLYEgd~+jE_et#K)gZEeW{;*cm1ocB2>ZQ z^@5(x@M8=)Lt`tISAdyW_Dcxj_gAUq6a=;lD|F>*MSJVeY~`zp01ROB(l`4*+5V5W zr-RD{43;?kv%Om1tAXl7w;Qn^<$Cy~$1K%)@K?p`4WaX0_!qW^kccV4P0N0n$BPxY zI$Y>l2LlkCliqnPmQRN>u(01kBWkbKRku~u3Tx`sqQnRms)h!1h*Aq@@p7|oun+sD zo)7Fv%>fBe3e-p{p1KT0u&$nh0#O9)1#Vbqkziy)SU5u=VuOJpdy@z~1jZUYYoSpH zz3fFL6->ss4%g4+iiy6Fo{=%#IEzJJVBlrK0B4zxZ&A6DGdJv5pN;ERtx5<&n3$cx zqA0+u12~|OK0^@T8@+k&d=pU=`IP{$7mHh?qIPHI1|H0MK7GV-EPX?Ai%n;gC6cHFz+(lD}U00YJWJ?h6@7L}NC^_{&!(w2UKrnfq|QdeE&r7>HlW`5CG zGz)s*wVWZ}GdhFMpq6cg2BB?oWm?b*C~t?&^YmYW7V}rk09M!HFkW3^ z1e_U4gu=OH8O78v-??x}m@Pc$Z5KQdie-PzV9R2Mi9=-=o0h#+u1QB!o1 zSplE$q|u8BmgU?t7R6Zdk>uX0iU(oKiXkh)4)_T;8bC1U_f*#_%4-Q8cmlU@Axm%v z2y72Jy8Y1hqqpx=4|`w<*X_?@Jj<@es)xK21AVw2B>~$qS?;Ps+tNjRI!*r5ViD%_ zf}%t$XKNmvhGY@N0Bw(*L!E75Q0KqspB==;ntir{nc+^ooN@(z#Q?BCaG+&UjxMQ)pg^!1dk%2c zYKOm;4i`Wk+T+U=8@6DtzSrC6#dgXwxWJb8ee%HBW@;>VA8 zECK}Y{5zWeh@c+)s|`_rfJZa7Sc+8YIfo(W-&gYJJE8>=_toC#NLrC0lnXf2E)9YC zm{~fFBza{EAXstW0O|+vlL9tJSk+uTeBpquU7#Fq&HCYo$z?B#Mvoq&=!wE7UXKnm zH&+N5yx7k^i!QmkhbOu1vo=KKAxqd6Ac8}%Er>9{KE4<&_@XEu8pQy~z?1$FDvKu~ zX)J0B^g*}1K3euWZ@hxDc`z8A&4bT}gPYOnCotxBi+CdR?-A_|!5h8MAfk)8CD=k# z)b6~8O@)RC2rL7z36NAgbo@+&@gURY9eW&-2nL!Ah5>Db33rH{o*rJv3Z$YT#dL6U zV_xH|*lVAyZP2P=FlqmS0aD^bTAE9?n?u|^6GC>7GEoRQ8cA`;&t_T70vBWKDl)3Lk9%N4;(!N0;uZulC-hv5dp)Mnf_Uj@9y0!UWw1~ zG=n>Dt#?YSyK6KUfTm<0T&(50hwe;bGv`ai^L^xOZJkO?mRHJGtx3mXy7ylF?@)_y zoEpO{eKm;G(Bt-TPYzX^iXq(tSH=zT?6yRDzvMX(SWVj;mmD%1h> z@NK{W(*+$A051~vMChB0h5_S*$t>pp!7G+Ghz1`FJnV;Wpi^u*8?yE30vkTknNMV1@~RJ72jKuHyr$A zmSl*X>EcUADJ4KDg7kvs&Iz^)FYq(($a5D}?)=2t=dj1sGiqm+JAW0$fD8L@K&-oT z^lBE{@lIOkBF4XW1#MXF?2;V;(IWnzUgiERxebQk*5q_^b%Oy2&>8!LQ&YmKLUbEq zrL3GI(hk{cv2eD&9wc+k2?@KVl>d7j=;3BZLB!k_+`s zLnQ-tKa)*N%{V%R&F-i#?-$B7BUrs$Jqt^1Exj7Dtu=R$QIx;`VPB(pm54mFXp~X{m_Km{%)JB z&6d{!-K^7%kdx-N0zWxpzC8UqLSsfAjLc3T0tga<$Yj}4ETnJ>AfQ^x7leFn`^MXM zfBN>@A%87>Lt-5I$3&!9te-{C!;92ii*KjyGbNA&RTG%YK3*!6t zDg$T|hckdaq2%^^5flR7-Sh+k86pk?+SEw^@W(iWm-%eHva78!89u>7oLPYsZ>Ufc zYf#-O8;fr?=RFK=oBi}3w@-hF1i^>jJpSepWeO-`aC=TSDP_8{Z-0@nb{ls0aaSjZ z*skmsSCjbek={Nod=#(mW#)MJrudLMaIf_Z;v#@gnRwmCm^C-wAlpKPQz^>`J@)M3Nlo%MmVN07q#1Q}mIY%`_h6+0X0_7;gmS9OBwiP}x^^-sn zpC(QLgiIT9X=oet<;a=}MNMXzsa!0Y--^Z-+E1UhvxSZA6^d!33$1xA=wH}ZSYGAM ze#rpiHwbVM-}BGL@C+V5ML|dqX&`s5Cqi+Elnb2-z#D?CwQfMQ|2Kc({sG;lOxGv z1cLU)2OtMtL|m6zCKL8lcS?yr zoO5mCz0=bpGeah;oHKt|Ow-j|S*4~f*>Vh6K~#G3Ot?dib(a<)V&uvx10hmD+n058 zP|w?uComX{Mv4XK3djHjL!obzOh9{>hI^e5QmeR9V?q#SVGq{Z35U$X0!ZcYu`LH25xx8hW zqsb78Kqi!rhnstnle-nlzD~=hBs28*=+Q%9;0LII^vuk* zRIoej#z3uaN2;{Q1O^Zx@t7T@CZo`iu8_)3U&&LO;T9rSWL9JCns%Vyrk6@l0RELK zz?wa#FDeHg_*3^<9eXzewOkq(tE-7&?ancOi$0O zLlL9i+A=pcGIk*D0>UZStuw@dho7BOgl zdgmQ14n#~K=pl8Y;_`@3VFqsYp9wz=QxJ)JE59W!3_<-db3wDo+@Py$d5V7%_-ue8 zke~~zTQXhTiM2h!rbm|^Z>QwZ{&B3{+2fGhgcqHIGBzB7s|g{yQ4!|SX&e`}XUa8^ zd&bg4(pBLq$NtW%TKCuAJ9uBaAKsh!n=Lc%u|#dX)02}8&B2v2xuc*&9V`;IB*(=y z_b6miIkIycF-J}=)~bc51k_uKx=$Q)YK1eUMg1K{6t) zW^3i05N_T9)VOk7+x_~TzOh4 z?d*Pj@$q)dNFK^0vG1Ojl33Q4-z9W$kG|@Yz8j$+hlzqD-#6--h!+`^!=`bNC>)Ks zn#6Pc)!|r%D|<_T>Nh!mpXOCD`E+<>vZ2k)5Wmy|9EMnij+fxJyq?l34~3X6lR2IO zrs{++5vU(m)t47_pK+pa_Drd%-)uL?g%Gi)cF3`Q0OCv}my~pXfzk}Ei^j!vy3{P> zxy%b!*mbfaZvu{?RasD7-Oxjh=^8rv2h4t`Ie?Uxx`64sehcb{=oiRFeh8atv5k+~ zze=_gb2&(EGqe$f5gESwG$j6GLD(!lODtxy-6ay4i=W1Fm;&K5UElfhD|ZtD5^`c=vl0^%d~Vd$iX@AiLic(|EI~sDvV*7kyYarr zfj1BtnL*Bg?t_TM`{b11clbRM_r=3Ilp2<1Bw1H8w~SH*`~8FxnPM)ye5!ZZnUcJ= z6HiWUUUKMACKSLt0l4Ok*PQlXv%m!&Kva4FNej|A2nE1^iWj*%l1Pwa+_HshqEB$00qhr5JAoe+s(TpN~Eg(Qj1n7<2pk?>XefC zWNqHegEpmAN20{Z3W3^7KAK!|1t z3=9noM32ci9K*&AYZ6SqJdKP6r#OLm^~+P&dwUOH&Es4b7OYB*Bhzu!`7Lu;QP!Ym z|90W%ZKm+Y>h|*hDLPTa=R%D$xgbH62nbRQD!aXQ&ycz&ZrO?r?E^>(q!P#Z{yv7v z*wZriBV=rn$n5Ma#tCL;+botEOIuq_K}%n_<(Fp@Qa@v?re{Sl!GxKX9$g@zg05;1Jw(y?rIWM!0djgCzJkHnfh6*Yd)U=vx^_K24C&HaMCX|(IcB5D^e4^-dzpva+Z^W^UBajPZ5j)*H=`cja-+#V^fSbZXFhfCC4X^&&e=oSJdAI{)%nO@dGP+e}-v$TQ9 z@Xm(szQe=6wi`a{`s3e1jvrr_omBVy5#$HlUcPnf*4S8n`1LD~9^DylX!!BR6~rT; zjDd9OSgEqDug{uSbF#3`sr{*kpO6re2>}CjttJ7J#qrs>Gl@mEyAcLF-Jl1u%81b< z-V<{H0cXw?Zha(|`POeU;KEk-j5k*YPg|ep zT`&T*(fp*Ppy0_91IzLJUMGRU^s)q-K!RM(Ewo|H^~slRWB1@mQ^!8F(NJe0(E0$^7M$FB=$98GM`Tvm@g$bClP?RL@M_U3_-mh z1^|5i`RAKIN6!#`xCI0uba33g+mV(Aw_(+~gNHLhvpwsjI_&-#Y+dKQ_QUxHb9o(TVWtWe2Fp0LB2}VfPuu zlkV>Ry!w+vxpngfAQR6YscP!S?W7aX1864NwzJHgM#XR#EklloofW}yoD6<-DgFFh zn9Nh<`a81}@8f%q*51nAajRLcVZO=$M_|k#<-ducT z;CZM4-f(BmzVit_nF-fUV_KEV&x+a|K`)`JhtWy?V7m8jPY?vcudYYzI{M6$P>DXv$U>`;e8j#Yd!k-M$t=Le(#vy`x;|! zb@SwGZ}qfXZ;*=}3;-jTUjdxLF*$id3*ChhmQc)PTWf@QLaVg}3o4$pkj^y6+5i`H zsLTuYpVtJJa`8ujMUv%V36yH61!NR!>wN|C3bWB{o-$e3_}UkG$jJ+voqDQYmZz8- zp02LsFe~A!R*JmFL8yTM#5-jtWZT|dkAJ#*H0II^Pe%0TpIz*YI|2%pJyhiV7=L6#rJ4P!1i>55 zITGQsINhFmDlXIbL(aX!2_#RDx%*}X6U#7iQj(ZxOqoQQ=lkoIFP{jdjA{=vj>U z_a$zRiK+a7mV@t$HS`j29#zMM?BZf{_t2Gxmbd}LI(Nk(j&d?SA`qaREG}$PF|{o22$dmt z`?q3e_C!Oq>7Fl_U0}I)eyxu~Zq(CU06|tFS0?A~k6ZS`#miq_r_{iy(dW1Jqb^dzy#+gPh6iw2 zS5thFvfwoGJ(LG2zc6N-cT{Fss3(&;md-|wi0`6}KJ>*Gn~xsdyzNj4JK?jP zy&rE~230UQGZwZrc^JnG-ubPDK_+WVS6PM$p|*j0=L3D5as}1^qZ05Eghr(NAANcG z+8Lq-jwK8%!!X(YaRh=8i-o*Sj!%!5p1xLRYS{Ym20Z?)c=Tk-Bzf6~A68-rshxO* z2R4im2Fzzfg+-}^0euO1=#J;VpbOG(KkDP6UMSvv)qwgc6&5hXx36X)u=$k_029EZ z7aCmAId*=BivQlfGDFYQH(=VStr_xgtj~z#|NKo0YjC~N<;P|5VJr4;xJC1F8Mo#M zXM-!@3Yekmss1jfDrbs9Lw(s|QAD68iveS&;ulh~=h&0vz+7DL^*^EJ3qw+H0gb8F?&A8qV7gy6NPvc9-A1dM(1! zfAJSrclwkWT=?WHvQ+p15I`5PTV_@X6OW$U#e)#X7&y3$F5Tv~bjhw5w=8M&XQ$v3 zkhapNPvf>G&*EO@`@i`O;`J2k+QdxJbYB=Ib;R3_wIGF3 zcd2;!M>+iW|CL=DY+ieHb3t2mWo32SGhOxUh*2)^(oh%83xewfaxZbu2&SKgy^u+O zZdTT`SqtC}=*7;z$MGh1<%Z(%v&Er_fxc=hW>nd(EXEKhpvh>8s(v=dTJxl)|M~O! zLO(CTM3oBLN}V_FUtM-b8X#FbeaFp#DnEhJqsPdY*5OOifQ07Cf1P0;C%_{?Ynw|`g-GUi#5&%VzjMl5TBhzFMZI9%^hT^fOEA#@HqU-ee z)Pby<65DB+lYz|n51jb-Nm|=fVBKvjHu*Oa)IRIOG>rGP`zc3)I|Oth`@}ph-iwu$&B5bxK?zXT;PHY2hQY42boSM=R26;_35{D~Ft?Y^wwlD$`C5tr29bp}L!uclCQ{gR zd2U>Ls(Sy|`yZX-~* zl0T1$6cY3qu5u8gZpRqflFi-;$G^TvjU7T@(y^>i^qUnG1fV@tOx9!r7&ss8 zU|@GLT3td;iw^G;o1s|Ei>2#t_*b48gT5Eznwx^#NsmaD+mKH296@~Xh~UC(;iQ;OeUXK;#rm7-Ti?F@t zy?*0< zIXpUANnvW!z!Nkw50!8bS$g;;q$B6I8r>sX(n8ZdN>B3SF<#i5dt$jf$aXMl8w~who*16|tEyc4bg8SaPba zDHjW?ju8ed;cy9+KW_+|rq2-u1gW`!19Y@pT`3d<29f6(TPzqLQ zjXNm8m>IOBmIrE(E^r{g4%``qsblLy0kH@1v#{>({mz;J4B|J&^&SKRlr`8Ll_c`iifDEu^7W_~wFf4Ko}^sD`)C|M z!`eL}`!uhKoCtBX9mr}Lp$7&8s4$%IRs0whW)VD%(+echrn2ZV`hcB7C8m~;Y=FU`S@?i8zTH` zVgZ+1-rQ`qH8)$WvsR8(*T(aB8gB;!elBSA!lnqNV7z*SWQj+r(8pD-Uzr`RA9f&JN5VwSLDVr>~wxspf~et-o$C?cHKdWhylV-1D|ke$K5Bar-kSg~3C_bX&VDZMTy zH`a5&FRP9v&h#l8qDd}513ZR=+`Kb5Xfk;1<2V?2DNJ$h9=H~H=kp=n2>v(Kg7 zPDsm+9t~A_a^2Is$vDcc?LTbT>R_PP$P&H(dzU7-EaM7Y*}cOAg2Pz`Bng?g?&pFe zkzV~UzCH5BmD4Zv00?kUAfhvVS2)6Q)YetTv*Bk%>SrtB+xJOUOsXXws-&zYmxxqJ zQleKzok$=){K1Zmk00;wxpt?!ue97qO~(jPJV7y@$#niv7a~NcVJ(^$>aj2u;idvP zsqn_Xd!Gg+ObsqgVX+V?M{*ktOxakoT}WdIgh(gD9jq=;(w`6n?3Ci6|HecZMFx}2 z=ng)){2qeEgtSl@&(N7~7P4hUHi2d?KK|p$;o*mEeZl#SLi$2};FbA8m)B%IzUO$^ z2FtxzTqc{(M=prtxpoWefv-EIfGCA{Au}aA!r(#oPYd*9AXFgleWpsQ#WK6d(e#-4 zo&vlgDhNtnywtI;>>H;?ur;|r^Sk56Z;F`u>FR-dAOMO0$q=ScWi7YqU7-%VdcqpC zNnhSXTtFBA0xuz8(Ek+%YOtrw3m|j|q))>t3zg4E@fbY-qp9M=SYMwAK}5pAl>lHz zh|f2rC%a8n16!@;RrEj;&*99)gr5W;h^dQ{NX3Xm4gje4>+OcM0**`7FXw2taF zBwhqxd@d#JV1%!4babSz3xha*%#4+{55+(n4<5585NbymnL%(|xLNa35p0bcm$6*l z`8}VBiIpjjC|iIkGKRX#2fw?1s;&?V|K$1=aptvuckw>yn;E!AS%TQZs#yG@`h5tP zaufb(b$9q_jo{f7DoflXrFAarw2pi$BuZBGs@FEQ<3;!&&pJ zS{J(wLGDQ1Pn3L0C%0B#!Ao46YJ#M1*GZb(jk(10|O z;5CHshdCelg3#wb;bmwI&Nn?VYs3XrJj!!qx{ClohO=SD)qVNW^tG`E4@L)i`T|ZC zOSCFIX4^~ghER0`GLp0)@9mWR$00xnsoZn+WEb9wD!=#-(tMZcF(wQ_fPva-y z5o!|>6X~I4^0XxP3wQrMCx4u4sbFj5 zP6Ymh@saDW*)B4sGX?is6nNE; z(^#s&>{Y%}SDv}GwNZ%uo$i(zxmOn)g5-wjhR#;v5#VXQ6za^4*g|eC&C5<4QVp?2y4P2?|;jx%T+_P*hG_`Lx*F-6<)%QR+{EN1B8VT8GHLJp?!Z}3vaX3Z1Sk@)+k!9q1W{?@q*|^3tz?C3 zFaO=eD>?gM3aF>=&;+VT(eFW^smKqnSC)q(8Lw|E_nNpB7C)zy$P$xsYsHBro<5<1 z!;iOrdHK|pLMDp$9M9Om#DSYdmZsW_eHx+tpxgix`Hyy4#AOQv)@mK8CsyP&wij5Rw8#xcHq&JD;*{VB#qW-WdesN#o4s5) z897)mD=_Cn51`Fj<9E74AbuJ)X~rGzAII~Nh-PrPFCn7Q7SOK@Zj?& z`ij}79u-y&1pfyH>~`#kWKj`6eM?Yw=)vQwBe@84xv|k{xmmF)E@T3RK)v8Qq!cdDIlDIKW^xys6 zmp7s_d_6N%&;w3Q5Q*S`_L~d{Tf$Gug+)bJ>$uNL@$-S^&I1zyc!ar0TF+GZXx%>F zOII)6>=2=KhJyj-$k4!?=%j1czqdG>T0bW6M-MxD&cRLs;Q4hy2D<0Xm^2@*b zyUW*dLp>cBz%7U*X2J8d*l>RQl*2O}(`v9hSiDbzQ+6LWU%o!9ka$F3O3pVcmXnzy z+;e%r$WyBK-E+!5BIlDXUfi~A>ACZoeT0I^=x^^-8!?=ZD;@5^Sc+SZP(rH z?$<3sZMT$r?)U!Ap;Y$kk=;5;_ugFqK^sqEM?Pp*@gyCGFgP~vXt8<mSxp8BKADYzhF{wd-fQ9da7v9-uv7RH&pIA(4 z)~R#;jYDPz?+IxT02GwTo#Q*_3@}MP-Nu2SYE_36oSo0<5s1-7{mcF#P-UySdK-s^ z;zKwP45~-sKt1uu?#vkdD{%(t7N=gO*8>S`aiHf@Tr-<9ic1GXrR7rGr5hn{dTC+Y zt}|!v9abw43NozvbS5@LM%!dswZt3^{_l*CiNeB(iI$A8#;Lmfg#q44>wOcaj8vUL zP}G*px&qD{^k3?Dfr9}IP+*bp^DrSd00!6=nF4({DMqW0|HOVoBd@OFTAU;l=o9Nk4*XOIt;lXURlNXJaRG_#1J>KRGVAtlyK7?s(*quRt{Xz0pt zZ!IyJ!UuuJ(PiCYip%6E=X+PxYKD)zzcK?Ht;(x)qc={H%MvR-&_RUB@zux@1K(SnZr^O{ol#8X~jdQ z!q@IxvKAJ=nr{GSWU~-+qU^NTA)!JnKy`_yVMz^u$U&61@8-8|lwqbznCc!#sOR;G zUJ}SBBir0lz(6;PfkxI56q?iz;@G-k)t;*(4~hrI&jSYl!sx_AM!MS)9}h5?VYqlU zxvE_@K2jria-CFuCbAfA0PBNbbsA2uRs>6-~w=qxyvF+MI5;|p=>lD`Hxcp0EiaVfE&e+pE}U5VxmRD*Dy) zhU`)(JWR$jBJq}!Lu7okn8iRvu=0NLBCLf11<*>t=|C6mNY0<1hMk=r9X&q*3uy^~ zGf%HZM-P(&h4KorVq`^eK)}5-XQ$8nxnC>QT2aDSZP;;F2b)?(r_b-OR)`S7$gF{Z za6^PUUZt`fJ3bmfB>V!f5N8ko1@+gHS71ch-v)ZOSs3h^9P4PP#o4_QXRK1fEdSDf z)inSH@NV;pyMJ%Yq>Gx=Gkf7XPd$&(N2h}j zDu^Qkz}Xk7Fz^Am8!IDwtz@c#r>jC>C>kEPSfZp*{uwgg>yfH5FB1?fJXjEULMTB1 z;UGXFfTvj>AH5(9S-mHsx4}?D1bF)-51!n5)KO86Ntsq<8Ng)&*$pGYca|8JB`f!x z`e1Yg1TtyhY!luG5^j#o z%npi4-|y#bojdP_bVh>*`0TI17VhfTHc_WH*$u z8m`E-VupwA(SLRaFNqrRi}xOUf$8Gqw=pvI>Gxxovq>kKVYkNw`5#oiCoy^+*%vGn z>dmI+b%GwCrh9$bKPCfz*;((}|NH9OT+{cV{Jm@krfPm0FzORBN zEn=Ar!N8ezDld0=u1h?e{nxW0d9$>cE#ngxKgBHvjyYgh@r9sOVJm>Jd36-)4zk}F zV#ENFKrC~$tX;DDVM0GdaM}7$Dtn$I0B9PZ^;hsHYr|8lnTpd1uJsElQ=+RXW(-VKO0=5t|SMU`Vz9?9kd>MCoNC-`V z3JFs(erLSIQ>+r2VL})mhF@s0Frsj624B*AXEcB)Ij$c)2MPB&qwHpK+={BW%XS`^ z*5C`~N(Ige4z^u-&?g66_(Y5M-@Ai(qT;c!F45Mm>zEVft8ebbhc09U-JlDb0R(jW zj(k{iL}`?4Db+EIy~o6uZ7w%rfmz6a0!75W$rOxXuu&LUuERG^Fo3yXsZm&m{~pp8 zq_hopnvoOKe)kQ2IQ;;DUB|Hd9(eu>!ongfm<-XR4QarLAQDQz$`3Bzw`V?jln>4= zg)DEpCsRPOO_5Co=ZX{Mu>6QgDCQ^fwy-+(#M{-CPjA|E8Y)(!)nd$~4Z}B+t03UJyFqRE z{cr!Ua!uK6b}*MCkjn8^E!1aVKJ#CEZrS+DU(TaD#tul;Gm#@(n+YjL&}5kHic&}r zjS#ry{>Sqam)t2)2@HL&C0A9If#R^UsBXwVh|r3FMSzS3DWtWOLFecO0xF9xPkJ8S zJv02E!HE3R(LPWvqS=w4Mnn2XbVO=yu2tbW-{J~Ng{mF$08HIe)7|x`DPWG0azeAe zyDScEwS{e8-T2g(NCkUimn0KyyWbH*QY#xdjKud|Q;9-co3fW0fBx4H6? z8aKz8o)X4#@lLx;HH>0{jQ}XJ$Z&);ycQxp6BhN>hQ&Ici_@dir#E*^03-cr2v$hKff?GcA`81bp3 zr>EY`5E!JVCnDYfxTFe#i8FhbZ81OGOzEycV~6(HaaGEaf%bYIT1b)snTG8o)A3mw zU5b*4^xW;J^}LqmfV5OE6o@%98U;oeO=UWYx~`YO9sFt0mp4vtcnA=9`z9r|o-+%K zLTh`z$h9`+i|LPC*&xX$nSh9=FX@U;4jENKiUA}HrOSFX zDl_ZX5Df702IdnG7!F^4{LQ7S*NH1AwHtJj+2S2Q^~m2s5OAVx_th(h?{|e>y~)s& zN>)D5W2YH{D|i76u3&x@8}pQ=ytM7OF%7}YuvNveglj+@Bn250E;di7NaawdP;Z$ckZlH=_9Z( zi6#Oby%S_6oLMZ<(f-kmP8naTwI=NR_*I=`-SOiWj<I!z zmx{5JBKBcpDiUPUvlY?6z)Zf*vFqUV?pjp`NGAlf$OaF{aDrU?_+$w(!Vgb21sezP zyTf(L(o#lMhtkz#by+Kf3IzjpFbgaqF>mpEkp<&m56nUXK}Dtq5_^RPCgVDSd=>nH#{WtF)WQmU>A$e z?3yxLL*rkM3eU30{Ip_ogdK*A@C z^uH^c^8;(71z7OSg? zj6AjA%uCws|{D3Ta)0iB&q zA6(kAVlwp6s;<7vHE`^57iCSF9k&>+b>bG)~$_2KBX zCKU^Uu3a|)!Q|_qI{y4$ajt+x0RH4W!OFIL3NmW=Y7y$CSv&Yu$lqe~Vm2<;2ZkPg zaw}9&-k~z)&lKUBOeDmInM}qG7JS8((vsjKZ!`7pmaB_S)=HVueMX@w^iWahvHJE3 z#07={{}jGAvpkR%IdOBWvUe`qhCVR(KlElA$pMXJK(Y(TpW6!%H{4mLpp2sXkG_qA zzSymUP)6uIQ2?tPX~X?q=3_|v^*unmAY2D57jZR7; zZJB04aHhWr{H_9k;9%EPfMBxLKw+JnWCd&3AOJtWWr!e!R(o6}v*ssveU2p}9 zK7H#GP7rrVLWGgB8J(jCQL0^{xtYQ9T>&2;;Dc$oGM}dHop<)fH|7;$+ z)=6|k-A{_HATjWfp>YdJGNm>ce|f7qSfWs9d6tL@6d@>PVA3` zTZ8=H+1MKJy)E%wnjMmJ%755U7cx3}aChrJ&g>eKs5npX^-Wa4ZM7h+f-fVkfJ6is z7ZTQh3D&sv07d}FL_ScfRR>0{v(4q{hudRfQnts|b==3sU(pDQfd*;GSaE|u>_f4X zBr2XVSgnxPRv1+89Sc@Am8i&%pzlz5!?sY!7rOMr3`zRTPK(7PBW}UWc8g^^3a`GQ zh@B9Ux^V8ej66P&&-AEhm9gV~^0$xIls$g5vh9NhdoC~P&-@0Ojvalw7q&GxG)5eB zp%sxyvk-vHu?NMUqhcqMF+cwpTcB2!y7cv>5G=uz#%g2D3d(`J7I0A^7I>v>V7-A? zKzOP}$f2MC9oAK4e|c-QH)~0l!PLnN(Qo1ec{23hV}M8&5J^0NprIZsD@Wd&+7AN5 z5P%>@BZzPV_(Jra24!-wRKl80f=>htIzTeBNMrHMjOB#o;$2&3P+ExS$O&%w+jFQ;t9su#=l+z5cB~AY<2TH zXmx<38+XtE07(wX0LVC!jJDaTs~sx9pmq$9NPaWrVR&{-RLcIoK7nU#e(?;fLfGH{ z1#04Aj8ML{|i8p@MOun^Q_RSiqZxAh%q=qL>xXs++E?y%|^_JTrYvRW$4j2hkI zb@6VOt->sn)?#r?O0jzaPfuaMJK`wafn?91di3Pme*K&>e!JA0zVt?|+7IMWgn`}ufiOxE;_kZ??o z*fhZ_AR#AunB)ZpW@HuW#EUElywEyaa;lD^jO}GrtFG7nM-gO57GSj$-xW%Prb9!d zWk{~j5?X|oLAei)xIB|p!x!nDgh0=V?;B}Xd@cxcb5h+{%|92CQK3~J8F=A0N=0zj zp9?qck0006rKNrTFCg$)Qh?Ww4XxsYQwsIe`OzD3EB^A?g@Pg-0fDaQ%b9_L$txj4 z;ivc`zEAWDNPc<^G+aOd4E14$8Vc;VF(w(|Fe-7R$#4Y;52Ipovve zJgKU>-uK`^rV%t~vgUSlrD^gHdEm--_Qvh|9b|fcu1M#M*&dQn?<3KPdHVRqXzs$S z0*?ra%vxr}MBs6O!JK+mq^l}9rTfr>xA!np!Wk8a#1s_$$>SP8l>9bI$%s~gvL?V2pd zhLS;*50cp9pM4UZ8y0mpRj(BxgQgjcO(cX=z9oBS6rw1NWdOp1#;8Q~MGcgoxZI#S zaPrEwlhS?1%%zU}efEJ8d;5+Ex5+%LLjTol(l>WTma4@95+1C>#gUOUWPBi`Vd#4D zhKHwyuwKE04vafho)iMYqbF5yuRVSZ#m&tRzTJJbNW>V>```_N@mxkz90Wvo_&>k^ z`i0R}tuSk8s?{f0U`i+K#H^8=ASWl|)H#GEN(>x$Xsmf52?1U#3cTLmucApjXiJXk z|NCbMRNdQqs42n&Pq z?($fFCk~aO3zw!=+dSc0CnlQZ!2|(dK7Uazxzc;@{f$HE?R7yhKMn*zfWSsB3_KeP zX1@wpa!#wWjjsQys_MMR-#oVz&;^?K_Q2N z%^Q}R#fS&B_mh*ayRw&Horr+I*C{aCcPB4u_!&}nFU#bT{B`?T8$tuwR^kxJNYkA1 z5n4!bzn~GnqxYZ|gY1}6IrAnas+GYCr5roJfRR!m>3TaPX2DR4&6)bnk05~3FgDB= zfnZLW369_g0b%_qt%UPg5O@d-wy*Xg9_&o9#7EtYF>4?W0<)51CRz}m8WkQDl@;gKHd_rS->3?8lnx+gbfE$i*!7+5#Sw(B5fGxg>5FjpNdiCZ)>+WWSBN$Rf6J+gbdzLqeSH>-7;7W32jdS zcT2}@oz7w4`+an?$xk1XNK5ot2_d;bgcA@giBrIEMhnCrrg&>orutMhR z_15+cn^(s;#S}o$mYjUmiUZUr5)PK+fnWOS$~MRRpL3caQfM8`mLbB5Ox%G5+tfi3 zXpx%q@j*fUKmg3_DY9v3zBOZ_#pOv7fmtb;7eP2sa62n!zdPNWm;3pGpIB@vAizC; z?w8q5fd&o)5?$Ec(cM+6u8rU8?Nifu`*fnVuLl8wCP|<+bbn9w`Y z3mIKsLF7?d<%v=eWfd`zhmRjbY4y!AvAyP4O}?3MMNp_H$gfge{!uKN9qTEP3H&JP znG^T9Tji&kcOJ~*JX#!)9TOHCmW#e5whyc}c4jD(;e*NMBDuh(wXIoJGc5?D_3n_U z&D*zcSRHOL(tJbTqU7X}=zt{lT?+B1h#QdJ{BurD-cW|klDZ)Frw~}Mbj}Un6 z3}A)ct)sVZe_Bn8;R^h3UpxO+)XrS3W#`>QO(H;$k!7JtGDwRxS;(rRmWG)H_LlSG z)n*k+1x7&GdoEt=Daj0$NToc7-M-GcV+Z5P&8_CeL!x~Dx`N139ptEO(7rMUcae;M zwDsU4S!0WRroIGZWzfRjcC6fy87e|bNn}W6rDR;tS?-Bxw4VZnmTHSX4 zP_#;&e@!;{Wpb}0m=3m|Zsq=Uzs2rm%leN$NxI!1H|q&JA&{8ky8#8}^h5A}sxxp` zgau=4YE6$`98Y)Qb$oScLXJxWjK~thSEnrX4mgMWMuNH3p4zNU-chKzm*mue1FcK& z^W=}Af9R=D9KiM`P%vj44&vbhP*(}#bHSY_Q@{tze^yIozCzpe=ZVyip>wW?)Y*hE z=%*O)eKr@sCqMQC(v3Thzrle3;ebMQ(Da_c_2tS#a*1E?;M!Ks>r|HObf%oUAAbxK z5KmA95Kv;O+RLl;^y%qQH=b1BRQ8$Cl$4#@1>&r`QPEg%L{PQ(QG6H`C|Znw02E|7 zwSgrAEiN8SS_ZV($aky*WlTG?uc0Q3^8`&viH|jLxr;YcN!EsWY=+1;kpaR{g;Ycs zBRC_cq9P2+(VEl-Q^BDX4MQwi1;i9 zJSeA?ipazMDUHV;Nb@Qz=kii<0+ikA6#!ekI$+b;zux--2cj1R3Mib?J=$BW`nl&BC=}%qMQCPywVOl$Kmku5hOsFqG0YY) z58Fr(kpDnY4xvC&+j}poFmEW)l9vVu{1^jB3K0vQ8ixe@@~kIV^1jNrap#S)s;Wf* zL4#UAA)_uW*R8v@cU!Q)PvTm;;kT?KI5Qy7i7nY5fBf;1+t=U;&{7}@;kH)a*6_l$ zXInhPo_@@$X9)+WJ^3S6K^|>i2*-N9MHaaDO`W@*ePEf#; zR)}et1F}}>(2=s3%rqKbwxC3pX#d56$QpHgn17>_uac_Bp-8tvijtmXsNv>^$O=Rz z#^e&}ow%YA0t)$+WQnv`a47P`f!YeIJoCMa(&9t5rd_3;BGjgkONIdobDR}ICtu?- z$Cx|HY-Qcy>D)5lj z?nz$Lv42Svn-FMplbw!v|I@9WTtS4C1_w*lRl5NN!a~7QQX)NiBqf=|1-vkq20RlA ziVKc!EDXY_Y}Sv90&Zv&8xuf;`sQ2#u^(jx0716dn6~pc3xcmYi`51Ow9=&_L(jE> zqF^QN+1I|sfnfTg3`^(n?|=O9C!0sFk#Jz7pwlbM@r81p*ZM-c828+xRx20WmvBt2#^W_Sd zG8B?I6*3+>5agk$q5Kd4z>@!uy$eEte6n*QJEYOyou2jikKF)=fmeN3dq3+5W})Ew z15ePpzb84vb7>o7$UeJ~f}iDNC$%rl!0MfTeK7bjZHi*wWKr;POg!HEuqgk!vC69Wy`y5{4LUkKYI9T$&rcw~9Jl7y(2~^{ zAgN*rIhsb--`)PZH#qiy!tN+Lu~95 zM?gR@*CTvdB0ifHB(3(ZOWR36@TZZl-#*%>GpG#p8iV=kFDm5m5eSh5YvL(tCN(gc}{(t^nMjCB!CX2-Zmd2GNuP&uIP zI8y#We`N88`*7R>0I?wA3(c--H#);mGI8g%pc}A$J$_`|i$j#}pRp8zf-f$NlKp~| z)m}l2PV7q99Cc3YV>rAbxh?e7odg5sj!F?13jSvtyf|;Z@&(vS^XI{ye+Eo?ghdDi z30cuW?u;;mf}c8q1&fgtE?Et)_QNPJ=MCmE#??vh4E=5GZG?lWOEbL~9)M?DL>mTg zyxkN`L2xM#m-qld!sevYHZg_biH{EO#}7yE{bf)rAW4BKhPVRn^{JkLo`KGk^-)pV zojBTFd^al5&7SUC1p-@M5JoMupD8u`^|Z7sEQ~F7(tZ?oc?{zs^ehZ;_^CI!^z{Xi zm7gzgGx3RwUHXVumrpr*u_5yAmVBi|iq12Lg$8YdB9n{J_YAQ6g9QZ;%G*|6VeXDB zC^6VvjHxAE(QwRGaq*5r-BcNRxbx75kKeA@S5EWhOoRnAVj!piAxnidy`_*Gmvc}5 zStrV-2B&Y|yLPh;M|O`t$~6&b-W4$qPjG&Mz1ytDtO{gSo+c;NX@ z;;t+>tpbX=>x_;+0Vbh927v$p2}?@yq`)ikC`**ZJg`E*)RdAIV$vX06SWmnqj9U+ z#=6v{+FEt0)oPm2xTJQf)?Mp1bs2X@9i8#V@ym1H!_d0^#oLOl)}?vp-SymaTU(yK zWTrbYY;rh;?TvpmqLA24!#Ku)<;WTe>LK6=SJ0C@xcL{$a|D7{zTSEBJvacPR4W(d zK6&`YcF2TJ=ll9*PC4r2p4C-LT#u0%`GU#*4_EhFW))f`T!V&hqO71=&;SHXpg))l z8*~aAGQ(jJ1f0CXS;=fLssJFa!*;fW(jW3Rg?{_pxFmg`x;p8<{xS$t&5NNbKsxaKWMIT+`V(K^a1x2# z!DS1T6fH+u5D)&87}OE5AX)hKmoyT?Gq1ksvrCsebS+Xt`6Aj=ZeDgDX zryO+(JVtW_@Q}h6s0T+5pAYphlE*ejV!2s99s_v$7dx(1zwEY8FxfyDa2yr~y70|j z|GC}KmBrvnY$1{}4w-a(x~DB*&WR0jq)#nEuUAK=+eRU|Ju z16X~CP_KS0tH1hf^1^lCwBB&}*LU8#sMDxiWcp-hn;vsa?S^nTF_dWTX>Lk_Dq)PX zDln~~4$dd~4+Ud13{-V6VN27bMeqa-06{WllW2+>M>S~|dWM+@p1sBq9&j*}hIx8N z{230Lr{k5f2ZAuQd$e_N88ig3SwK?)i2@))2FP*tD9_m&zx~!Xc>SYmFMafyO>0)M zR@wYD6W0}RM5<32# z5{|;ziWWMPZQx|%vd-QuSbbo(Bsa?DVI>yNO*Q}DF zD7eacg~V94d(57ck>SQu?PKFkeXKXNaK*;yW$QP!P~?H6JmV__y0h*bjSgxOBnSs0 z5Sp67jAS(c1gho%`=;hbmd1zY7nr~_uAZ`+m}>3J{T z_0BbCEP{OZ^AFy&5C_DRM!WZbzpohv`bn5&D^sjiNezEpInkfYYitApE!PYX1Pt&5 zhCmf5fllYl7vmTy8xRcgnKG*cohSr>P_Bq`6_ONC0AB$8u}Zlp(H)M01_`l#S}uY> z83YEzD~s?4N(jzkSviL@fq+6KKFvd~0PG{ys$Vn#dFuNf-E=8dkugIwJ7aMp8)K!B za=FdQ#mt6WS<$h4P=D3hWoFbN@B*6$006f;x?=}u_pCG43q3ltifS+*`lx_{*%2%v z)-BQ86nN%E{5txg_T^MZOC!#smX>%2q*lrab<^AS)46c1Q;CIF@zB{5-Q9Wu3L9L)Nw9d)nb)Tyua&_#d-pPda6Jm zAio%Nd0AD?8#1C>fPhfU3{?jhFe=~{B7T4%)1YgxdHl&LZu!xeEily#7Vd#eJdd3e!3XvFVJ(`8itNxpt z@6|Ap`O5~N`O(_(&G*0n4YDu0z;#SHdl^2iR0gFt~4 zoF75OUS=F~f>Woo?p(6PsTZIAoD!j&_{SRRDv#%2l^iu8a@>Yce9v^}t<)QkuEG%U znoXN-hn|YWsI?Ut?B<=zRHRBaUv|vVt>$mOZ%zmOJ`n@;*Z%M@ zV4wRiHD(gQmFZ^iIIQT2;RT$UBxf+!NUm2uK_op$4VRw#=Cz$loB)YEa90bc&LE11 z!;owey+@yg>ty^1$Fx=_k>T|ZfJY{PKpUTgr-qFXxuM$r^p5+b5IiFsTW z?*Gl2?Dp9Wd!ATw$?i@oOpR&sRhTAUbtA6e=yi-!jrp?LIGD0ZC?Av-ohmKb@>(rj z1%N>4;6~j1@)*sUNblaEKH)X@PA2>Sx(cQ5l*@&Tss7qLGvgPmX~d%xFmTtoPb|}( zIDe6#j)5jOVW3tR*zI*R)V~WK4z6q1Pb2T1(H*SThO$e`a3xfWe`cG)K&2;Fu=L#9 zwzp`Zh`D_IGLi{J%cn5l8vzIsFpI0AH-@X-8z>+sI+#o~$f-y>0HgILN|iKn8(*#F zZE^+E<**MVt9ETHgUm4B#VCkm9Ov`y=&;Wb$F{eM;VQl87i{qHcFqY`piu92DiI50 zR`nB*qFf|!fQ~RxUj;azeUu{D=zxNq&zT-yvgC14j;D=40rrGt&eWQ#u3EGG_En2p z&A2E7# z`{4j$2yk=z(0t1*SNF0G<+Gi2jni6NTTw zJt|#;yhFvik`6ith?&7`Q-6i-yX)}!N6ZpM+{ba*;2~d&CzHVl$-RM9VnM(V!=5=R zejhmly*h=r+1KdK@CGCWsuj0Ng!2+856KZoYG(#(Pahw1Mmhn4$ymlSfk?1520aQ< z&_azDe1c9`tfIT;yH`k!0SCT6@@0A-72aKEO#yGv5 zK0hDZ=R%pBz^mZ$r#g#)>b5Sm4Y`*#W~us=DrzC>B2BJ{wgDAl;84JTbl>6QOl|@J zl?Ro)yD=_P!bB9n>>aO6r%gqxL%kEnyHi+4QfFrUGo`9^$(#Kn6nPf1#2XkRnN6KHF(kO|>Z%bJwWzc{% zdo0zwPOfvp=ZD-?fIvg#LB$>IDzZwQPHBkP1r+eSBf==P(o_TqgjCl$m}6yX^pMdx zB1f=xA_en|u~NAbb0;WBi_@h#21oz_hxPGmp=Qo_;^YRT3_ho)ClD5tqRG|d&N{CB z`rZd0Tzmbs+rNJPr+04n^ix{rz30ofA9&#LTW)M`FZS-M6xAqNJiUEz_=!?xq%Tnh z|3RzH3;iO3K%zO3pq5b@9phOYVc@bSPCaT~O~gPSmLLNd3DnJQ4>2-lOhf??P|FDF zo`T~8J)(R@!Gw(-ROAZ81SU3B5TZhJ4dk^U8C=0x=Y7*QF|pzbxf%r(ReIefj|c+9 zgP^NqPz?u@0nTWX%R87tHLt;=M?M&Fp)SOq?T7}b4I*y4Bfteliysh=rpx&OACmppPs>#h4|yayiplr+cbD%DMIzWMSG zPdst&nwFN(zI`!JRkhZXw=V$@+HUA0cJXi@lC?8iCmqBYi|foPm#py>}3%!03}K!PM!+H9KCY$gC4xC9c_ z0!k36K==V5cx~AtHErwCq*ZC^9te3h0tD1f@FUHPsJMj1kB*T-(IL%Lv*-KA8XMhnrwG&%hlXv?1*&9v z`FK|}D!%MGt&0A`xLP8WQ!8+c!(YYraT(M;bdngWey6Zxgo+Y|xq&C<;PV-rb~m&)$v*1l>6X;K;Zy@vC*mOc=i$j0#n)WzISdo z?WVe&PIlAj7d-Uz>u?2Lj}=9Z-s2q#2EFC+#89qPp;4(bE}9+*?ZOeS9~cOAH#zD2 z!;1NK14JXb|GMX(g<=VJ)q6yu`FvePaQ7HE&p~9!F_Hl#DA@nV3VeRC-w{l@f(IOo zRZH7gr1We>nD$yQl~UIwpHCyFuFPf-ejJ1AY{OMK%LX zCx^&_&`aS18({fW3aVAvZNJy6>Hv=DYxXoL;ka7u~63GxTQ z≶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� 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%0D;}I3W6pYs~jPBjLfs|c> zDOeq500Bm%7gnl4JFLO=`?#u@jFl-dF{BF%96&Z)>2=t<`p`BX5*n|{89kRrBqbm(pD6Z`(zbOD0FaR)NqiG>Hpy}L< znADIr7>*5uIZ&asPh4ETIce`ofJE{*Z7!t=4HkH?^!dIo7Cu87`7G#vY|%s=IW-mk z`raI33STp)5VJ+pfbHE+EmD zaO1!_wkCE=rv?WUQuTW`usneMam}6GH@027+c#f`{!mq6i*|z)Eg{C%`U9-R+**02 zvXCWt;#LHR!ws$tc8x1Jb=#g>qVUTjxJBM>r7;l?UCKC{wWa9wC88H-5dKX7=KhEV z$lnW25Wpm?OH6YpXoya_m<9{kpZh@~zDbwACE_A6`5Y+<=dVgs4#2&NVeP2n=Yiywp2@ zX=jzHC zTjo1{xm!1y-Mi5m2m0;fNW#d9!>+1Tqs%ttLjri~b-Eld4v3Dcf4-fY_BLM^W zDd?^tZPg3wwh;JQ=_txL#rm*x?H~PMy$~ z5muq#J$rK4P&DgMFL1zdB2!P&gfy8#Hy^m04hnQC_ccz>k7z9C_P@y)qe3wj3=4jH{14|2uY%CBunRSx6lLt!8IPCAp=hhL9kXz?EC;v^3NZ z96eMkaATziTu8>)*S)cFk)nW)2=AcdGQ0y2`~Dn&ydy0nk%?>aO3jV!PQn#Nh8CmA zCmxm?1jI_%U*aS-)DWevVIVL>sg0JKE1h!02xk+N~JNIb!S_ekScCzQyMoQYh`aKPPZ1e#Z-4*^=$j`uN2K!h zYB@JzMPq=bp|7t?1CubcGD=wgyC|NP*lGsMhx4F|!yhqu_2mJtnRtb^w|gf(-R9o) zW6SaRNk3`%WeZ=rx-ii(ViikL*N*W+6XkH_o5ssV4J zfQm$*6mMPvA2<+oA1Ff}0lC7$=yb%>5h@PY#yaK}DFA%+VNn60{D9`9U<)=A4#=49 ziS%`f+|-DiL4f-KDj>#VjiQNdqnVl(RxyG{Oro-mzB-H&e$$0~D>+a|iyQzK@b}mQ z^{j7J%Y-v+81pUGuZg2jJ7&z4cW!)~e%xZ-H8h|!Qs_XT(adm6Pz2=jb-}@E8LL*S zs3~_@!L94x+`iUvWzEf-`r@fZPQ`!#{11O}dbGc?0d)^FlJN1Q+xXHM;L^ov+(8sc zKx+j#Q7{Bnt3#_*ibWq5V3?=k>@7l1mCxTPLZU$w?H zqQrX&)$ptRR#wwOjDb#jTqzSdK#>|7(^~I0c6wD24n(Ov>2OEE0nMqqCvMc%?K2-9 z8l)I(yu)<33T|N`GV0&}bhqEHQcH|irfSOyGB=m&*Fq6!4yR+GrHWCYt3Y?I{^G^T zo<^ev;9C!%yKK{@P5WQEbn)WFGfi4!hy>yoydY15j6h6eN|y=}A6bA*d;>zI;`>nm z(uVw99Vufa&$=-w9|*XybXSL)93`vtt8$!b8j9kPhr<(GghzSit*wX+S0AZD=woX9 z@M@foiAh~*_wVuExH`CCwm zmE$lXFU2pg@L{Pkr2cgZN5}b+Y<AVLWTL);rm5D(whAeU>c0w>T%Lh8rt z=?h!Zc)q9GNQ-|o@1T01UVqv99>*y-7VV{#{Y?XfMq%Qt^2falM%{B0Hs81utr~NwV8DLxHy3V3P3b7Qic7s zO$RmjH;5J(ygTHvb4jtQ!GKAxLPaZB3ttTt&=N!nnL{0^1*;G0tK-pEz{nwXZZQ-h z2_m89zn}-Cz#`#8`f>^t%hYSH+`{t@0@UU;dq+k}ar8Y<_IeqvaeA$&jX?uEyaXV? zPWm^tzVOa?d2FIeA(b%R>7<=jHBCD_$ft(;p(99GS5fM7C;=f3Ufe?w$pEXY{e8U( zBfP@tXq|1>9EwB>(6zOxjh%Ts9jYl(Wb!*hALx{sEL`!`9$HQWMbpYCC~t{E%EX^J z6R(0tslIYPaG|$~vnQgHX6jhzMV2Vsr{uV_Ndcu`St~1@RZa{&ybUb$nO%U?-64_4%wa6Cjf+AA9s+CV50$UQXPFkjL_^?a20#P!Osv(pL!7%|zmWAx1&>ye}NE7w- zHE2}UGyOXqw#MlS5(b2QFxuZ1rSi=>Rg}m9Vh+?%Ic0e=8~@qWZi*BLB=V@BlcMpJ z@Y;M})5|<9L#}<>wVBa5kA+%Ykf&8~3JtnTdwY)&F91`AKP1fr13}iz!$S~c4+?Pc z{$Sh5>gtAu>ULb-f^HHOL8SRl@;93R7N2IM!jC?Z#mFp0Z@jkKy&1}15Pu*&F1N0* zFgViI)`oA8oG}roX@zpxiboz_{%{ij_zGz)fAU8Ydv=^~F%po#5w|M8h>3z5PAeTA zp9GGtR%->c2&R<~{-TVS*ogfXLsn6wySUQGX$FWQ;PYlF6LPbF8j#CL!lbH`jMh-$ z7@TP=_F?t=hl6mPp#*qsofDdXlHdoW(p}u&puuL@XG?BO_sw*w*XNFLjDkjodGBzS zAEIV8hLiRE$O|YnEJrg${K~@WF7z1p_K%9V0F3t5Xu~9ka6s~RbU(H5@S70zJJOO9 zkn~?AN+04!D-G1Y(;6kml^i8a%K@4Mo79RY9)0{PUwP=oFJc*)Iezo{_-cJA;edqk zxU(}PYKT`N!$h@^G@(U6V)yQsp%w$f=EGkbwHj5_r3*V+FfdS4Io$v1Fvo@cLO`@) z_eZFgP(qU{Im*Ul(r>1ZJtBzzb$ENVow*fw>Jbt!a(vw=TF5kjT8};P$m5?E>5F)T zXANtguf%4+Jhhxikny^ck{NQfR$LpmC<V6zhvUL}llt!eDU!93o@wtHv)N08^ z%MuKb;^w#)ZEZC z%-LiL7>ceQjtm~N?Jr-tR0%JD7t{hrU8Zl+K%{Wxbs~c{q%dGLD>Qx0P(cG6J8*^8E`v ztOB5D6?aslJ4ZTAEHvwKZVD6R`>k#H9uRe zuVQ4R$|I9|;%Yq%nT3eNQFwJP5=fV7PD+H5+F(@r4H6q$zp1}VX3eNbL{%ouN#OH& zF?lVgyN@#xXaezBr*%`~hoMv{tK8FRWfN!Xm~ih%l>EglumdGqgiE+=;hA3727Daf zdLw`C^qJl+CA-1Mn&TVloBEqDcW5)4jSgHQo$u`*ZYk7Z0!gPffCl9LV!RqhS-^4u z0t3X!*LxE{=Xx;(M~Bc!69|+A0=03Sxurg>L2XhoYO%5)T~tocem)hz!sM~#T-F=Y zKU(z;LAoWxKHCG?a; zl)z#&Cl&KqDEm-F>$bQz6Zr?y$-_TlRnlt4B;*|gU4p8UOG}_sKK8_;p9AmzZ(_NP zx4)5fY`QEn$DpQ2@=v0s5<9D$qs`UGp?rOZn2{S8^&;iRqmZF;PS*$R_!sE!#@A6?@fcDXPBg*)uc#4dmcV z{JTvDbQ&^deyXx}xTV#GnImIk#um4JdZ?+UjW^qL1|ogfB;QmHM%whdcg~)9`mI(w zFQLQ=g!DcdKrO-D?WE1IMEqgX4|^gLdP_;1B*5Wvp;Q0|@GGBl`G<-I8r`=J4FqEK zrMyhs*(YPP6?qj-iJUaiEp*AeKsUD1l=v)M0W7&BJ&7{5rtcFYhX_(DETlqi@HBKj zqd|85O7gWmJM<@N=emP%4~Y6VIH&Tl0Y?u4q^G9`^xLL>v*|mhK!Wgsip6oD5Uhd# z3J~B~5Fov_IJeHJMO4VB1?5i^zg7fZ;d6-mKc^1By@rqNt%sf*OfPUd5uQZjfe3tmFm6E@(>@kGQPpnuL6;9C6Sl}Q|?#s1v zof6*F*_KwUElR5Om_PtTseG`Gxg4W4Q6*cfI=HBUCQ|t?of%=t<^s3@wzJ17k2NUQ zWA%U{ZEVk;^70eKvxi$*T;R6ZwBD*XNFVAvoxqJB`rV1|e*5Y7$x*(D;acDT$p9)Y zr{pJX)~C;QHhZi}9WN+<2}Q&o5x&qX|Jb9SYx{riF@v)pK~h1SgO`Om;3%Z-o!-*A zx;7$Gr81-mgzo|s;lKiDq5vF4&LYTP0;5T&0v&+2W#oBT{^c)|e`)#SkFE$&D576v zRMlaVv8t2GFLiB6Z&oAPf*oLk13^W~O07)hamqu(ozT>pmi;etatg&DF4$7vQfRX? zM>$9IHT{tf{!||KS?6&XjDXGNtU@#g=@YocA9xYiHua;YvtGl=W0cT!2|U2XoW%p&QJ5g%)27?fs$3as z@|0>R;SO6^Q^+NzL_0~ZVYu%DKbiQZGYzZ)ep}%{m(^ym^PKZ=EjkK6D9_CA?ix|z zPi)G37&cM-1o{9VykAx_@`J5e?@H{54Z1UB4XU6>%*y(F$n!63vDB!=pTKA2>*Xo`imA3Fj!nZP@I&jWuSY7?ytz> zPAh1I0LWu82gG6mVaLKCKA>Fj=-+=_z6`SvPs9s~sTH%k8uN;Fu7V{HZVegc2aU<= zqLXniPNG;?6$LPoch7Vg;W2QGjXGa`Gqcru>lH$QU0nm08yk6>wYW_0CKS-eqMM_1 z#M!8YVK*qXjZSA8=XiJR+HYok{S%ZKNKoQ%g*c$~_*@)A^naMxp~rst|DfK#50*b> z(5$b1KI`Yd>#XunI<;(R93YJZ|6;QpO%dH7+6EHKQ=vXQc*~?#_K!Lu%O6=r%q@y- zK7Vs_w7b}k87u|%zRpd!UQ8eqNVL*oPA}}b(YAy8dxJ3{<=?oaOml$-;KAM4BnjlMxqGF|B#vi z^(7&Nk9yDY|MkcIUh-IB;Mdddug!Y?<<6MP9H$ogEth77L(ZR|{Uh=hJ}QK2cO@Hn|6mij-y6~;ZXJs_hOMZsBK8!DSCebCx}#tQGoOJ zuenQ)Kn9?JT;l9VD#m~su1#r1X6BKpCv$C9nb?O0iivY;ctNWeiHV*n$7mVG4R4M) z%BF)Bi+8$NXVc}~&eW&7SLxF;v=&P+uT~#RTmpauiFlcwQwrr^rcS;2?WbSk?KWW$ zX2tR^|DTI~@oh6+r?Shd-&mWK^}RQ1y4svVFrX!{E`nA`QOKBv7O@iT`S`z)EO|n* z40%N*%|@@vkdZuq$u%@n_ulywLIISK=+JZ)MF|0e(8O(Wz5)gi+`2vMDq>6xbJN&# zX)ySmDcd0S9EruEJv?3(4i4PnFF*iJf(Ocg`{e82e(S8ACH3-U4_V9qgT-w%T-L^)k}K&it||b1*Ly9Q@S} zeOaJ*3U=b$p>IF;K95uZT%3nt2>jszy!B-|)^1_r+kf(l?@Q3%C&bYd5Xu({V?TKK zN#f@}^G`k@0Vo-j;8R1^D({{7qdk~_Pb5nYIZ4n;(P7V25fu*#n3CZM5Zo-74O$GJ z4A)m1%r?0}1agFpiB)B{^-CC#z9yYOq(z`Cz1g(S|AVKq-tyb|FGz6D;C%&L11x&N zkk67NF}%TWqU6i}Q5z&Wn=aw3*p;D~G|y0JbDoj`1>)O+sM3Z9x#C4FAliXjN2ZV4 zete*^zK$_#Y<4q%QnA1SUh6H64Jh@==3IipGM5 zAgYI`EGoeeL#uy53*0K0F0{1H5ARZ}x0}&ZINJ9raG{BG7V@G=Fk}Q`-2|~YSZ}=u zEQfkne){b=)xJ|(vz~s_Zzr2|ACjFA|HlZCKxX{xPITJP$R`6vTFDglG&0B}>l&RX zHX924_zR{G1zsQ2@dFc+O1lNSEBiL}-D$dh{WtI2eRb1IO${Ly@V3Udf^0X`e;_9} zKL@DF=y~n;KWT5(*+B}GC$3nF(+%6RUI-ErJPZq>{?G9hQk0d+oxhnrIzM>49!;sL zk-;D+AmJOmN@R~4g2+zUJa7kz9XM{T?wv1$D1Y_lrdNjtKl?0qs!D*ogrZ|@7iVo^0#EiQ%kN$O<@udE^T#q`JdIbbjMVg2R_mY&Xr0}zJNWze z-+vAG$yo#R27CFV?N0*FY|q;M#z_``{`}Tww!YA+F_4bhC%#Yx4;Ba!nP6h~@bLi$ z&0HC5lOqqMcIEoya$99DBgYE)JvWIr*s1(%VvslQYwf)|{@GYn@_U!huP(sUPiAZ; zS_Q^yJEzh-hXawQs$DGG6zCt>N40SzCX8O0)0W_Gg~SdQ+-G zbO0875g$BIAX$Xg;mNtd<3@?D`!FL_!XM17plS0bScQ#ilCKC9$n#JBtj=t+wBMN+ zyLMvgz4uaQr)Tp&{q$pU));HG^%w=H%^$1s7Nf-y0N>p% zSb{|?c=8$YC*NG#&P0hM_`)f8kPt~=4a($=lWpWMxhlE1h}N7P9n?rdTHpvMFe$Ui zY;RB0-uPLA##-l-t~Yw}AoTILysF%c=H}+y&nD+S9GaLInrviwgADumJ!`JM@YGY! z2zUxFLh{ECScIp@i)XfCzF8!}vM+ps2a4tB=fF_1F|V5;7sxNid1=NlGp~}XWxGW! z&|2SRVxnZ`PhxLeZL_rH9<@_FbJMeViA7Q#XN}IDJar1!&%3%O=Y}R`hK?ImLcYjb zzT>CgI|T6`dJgyf4}Djp03d1s!hsils9FXR04u)q1s)_GCrhrlj>$&35@U#4syI3O z(M*&|X1XR)z+cm&QX@i$zq)7qxTUd*QyiWgtdnXq@$Cm{hMR_m>uYM}=I5uU$H$=> zCMG7Yum%I#OzUoaux99|KgBVgs{uWf0>mzee)}QeH@x`zDGfS`fG@1UgT^E1^i&id z<|Rs*apP_{0}XfDG!oks(t|JrhGRXf9DOFX=G#|$?6U46u6xj7=i5KQz;XZZKu?=B z*k0Z9$?xVq{P4r^TKAf(6LSt$2TfqE%lzP#S6(U4CV1t;wZtC4EiW$`wQl|Et6?+yVP{7aKriy8<-6nzHkd4JcwV2ej=sm@~RBE{Kp>+o8&UV8MwKH zKTyM977^n{@jsog+8aBqHomZa^zLwvV}sp(G`V>E!>d<^W}e&r&2N5__pW5(;s6e~eq;Mnhp>X@1N}SC{pjVEI;{prQ-Aem_RjaGttyP;)}M=S?``8Q zy_Z~i+uPP|w6U~n*R-JGR7C406mVGETFcK+=Kx1_ofWWK>73e*xx&~A+Z4%Q4&BH= z>PoZC{lEd@wpcV;u$B;Nvt*9L`17kiKA^>-2AP2@3$g>inIn zOS5VYU7N2No9*x6V*Q5l4ZEhsE>}q@fIyp@KoEc}+sgIXS!1)aqm`RhcG~>I`D|X^ zrM^GT_P^_Jl$XCcqo=S;Ah_GQ4?&h zciZJ)nR>B%x_`?@T^)c7WCj%{_2gYQoXZG7K>9brgz@eHDWj4?m*7fioqSs>%lX>y znSzO!M5wTzp1W$%uhEY@SB3m5;46*@sOjt+8@rzR9YMfRuxfVnwoC>PtO-_E0w)N7 zm8EN+Y#K(6sbHetyY8!F(`U~1cXXgU5jl|)f=nQ|+d|U>BAtjRXx}a&$tpnLa-q6q zP(h+MOle%=oY1UMgvQ51+C0g~3)$biRyBVJVnB9f*2=Ne!tZ-l<#ha834Fi2zrnAh zQJEn29)t?cqBZ+S*f}s2ZeI^jxecg{iBoMGS z4(2kd$5ArSl()4}#65tG)1+eCpk8u&;)*2h)U)9q z1fWmQzwh9103gu1Mk^~hlirO+Qma;cFuiZf!QFj_Po7<9+}{23g$_p#RFiXxcZm#{ z0mHkm2T+-?U|>)})m1_=P_^b}do4=~aFBorLgP3z?vtoT3VoqAzNP8)&eh<-RXMf* z?EqNDW%c}B2)gjamM?w?;4oAYsfL?LYfVKY!{nWx-tu{4-}#y8gVWm&-~9U6x^-Q< zR`sAiuQ;P8GJ)Xk3$C6J(%mjf_1NW2rR%Ya?NL2HpO3>$Q9?cxk&J{xYPQX+p`~V< zXZ`BZO4tdmf7jCkmK^^P)B$o%wtTtWK;yaE^JAB*v;BOAq~#ZP^gjQ=TQlDs*}9`| z>ydRZg!c8!859Yii&zZ1L0Y+u{67UJL>`Y63dF~+l#ZJ7S{e=fW+|Nurl+K92<#Fx z5<(*-bR{OZI)L(k&g%<%_8j>gy(fJM?8 z1t*kRLO|A9NSvU+IJC~{@o-kmosbDmHcX|a7Iv=6>4D-eCs=)sf+wDMqIjG02;5kg z%MY9mFhYS+a{k+ort`X=Klawev+DqWi7qy#$KG+SzOW4rarsxtkPO$|oZsp*1yVMT8=K@+l zP?{!)0Z;lgk7kvED|5}Etg-7ykG@g52>`f)dIDLTp3Zt1s)n9a`@q4$U@&B)X_-OM z_X`lP=VLp|k~FO>*wZz=_0F9?FXTAN(Z=z2F4lYXW zL4a_ZJfc{*PV7CP=%Z9w5Ns=$-DqDBs*;Z0 z0|tZSQXdxsAQ3Py1ZQwa=KG|aiJHN+s+hZX0H?*R=hb5du{krCRML^Yc|^<*!$MtZp(EJX2L#%8d@BzTMda>%XOUZv3>*?>3GEU>C@} zi88^8t^;0{T{7Xuaiu#%5$IJNnt?#@YI#|2W3&3L+)ym(8y+8$X#H_%=9)noX$7{- zfRKlBfvRUMDwX0^mQ6G=|6{dPL>G3hT?<{K&c!o3%PY#ddgmsRantcf;U+R7pkU_0 ztHs4Yz+Of#!!ewDt6HA#(@^jUATac;Dt7d4bLFXBk$5~AeaoG6GfX&m(!A?h6@8s+^YoD%q{kczcKl~5~7?gcK zf7=5DbWAr>dILrBaSUB7<-!0?qnRX{RGsW<(d21^vG~>SvqP8UaZmml&8RceFGwfB zwmm|VCTGj-M<2g^yY(a_NbcI5CG zXaE#D`uBSSdN>;v+@6Y3+?_%~9`efhAmo^Xsni9|)A6|NMA&T|Qt%Tdg&a-=ROVQa zPP!jM3=rZb#K4m_OpFV$6ZP>T)|ePYM#EvaTo${1{Pm4Zg}Qu=1x|xXFrM#51UMYW zTHx}CUM92Oo|>DBG6WwOplY2sDc~=8Dyv-Kcs$$`%Qp`_6N4}iZ)0Pl7ADg+Oe-xh zKpD9(;2BooxL9XOh?rBaje5eia4a_DFDxu+DtYk-oyBc7(gyv=aCHAq8=yJZzEuMR z=t-Guajv0ZBFYGH0Wj1GEoi6_fCP*k2=M7j3P*;D!V!r*?q_XDvnn%7mR?$BfC~d2 z2m_cW&P73n$_zive2MLmYSQL zooHpaonWt*MD0g}fJz=q1e@#3{(y6H(V$dfi}8KQ5W~YWV?=4C`w#H8f17FmkbBc5cqgBL9VE zmlEv+e1t$K8Ey{pqegnj=#NP96IN@|%8g>07GV} zgf<8Wcb+Dje89eXcFXx7F`C}VgttjnVNMk^50n4+L6 znR$*T-Lyi$6LJ}0eZq#3(EA6$YK|0!eNsi6(>F{oOuqZJExb6j01w&g^$bn!oti{x z0D~B4m>Ux3QWUa5!Q?J4LBl6ZfGG+Rac5K`3+d=k{)kg9gNAX8pahV7WL_yuH$8yy z#LHWOl_UTGkWg6H6!ua|cf>2ASfx2)v&E(+wt2;RW{tuqFf9HCYrjnh3`|Z=MMVVk z3Q_nV3%pW-LkJVg!%4r_rNn8aRHXE3B+f)UAz&~Z!T>Lm5vG}-cPzH9HzAqDe8d1o z%AN`PG?ILuuT9P{ZO(`b6uYz}!Ho;G&ojr5c8$EV*pkpDV9LJAnWP zh*Z9$RS9s=GDLxkwZ!63cfv#%FOw0bpU@1+MlKG7H8RfIjLa_ydlhVOD1@sRnKx{; zo<4fiCxtvfTySIdw}_s)fzp6M6=RPKGZemT&j<-&5T_9XIIi_3Z45==XqbSeMM~-5 zXd<5xh(v%urd^b7y7wVmXf$zZ!ewA`h>P27VV8vO3tLoLMO!4Y*_JvQGcvHG273x> z!qFuL<_00hmnqTM2qyuJ*K#`n6d2UC$ruIsSp>8AU5nApvQ z0gqpd^TFxN61IsXZ8o1&#mL<;t2=h|s$a&aw1mLWHVd^Nr(SuZp3TY*hP2+6{PUo0zuR6wCL zC#)mxqgR6z!(6-p?SKeFwIK$)dXa`;2*JMqaHGVUTAC{^kcvps&GOM_E>l$46G=0J zXAnqV{ng(2gEkSxah#+{({z3B-tf5hAlzN<5)RTpO^irv2Pc>6(nTl<3oc+D`O#GAToW%Eml(re~bMN>4{qEge z*m72XOb4*Zk9W%)6v+Gj%Z+x;__o!C0U(Rl-$D-96b`)Y@0_zSqsH$L3V|>tx{6r# zY;R2(LgdF@ZuiQzxdaLr5v{;j61D~x3(AgjqPtD4{vm*x4V){7XkV*`O&DIG^{hq2F#d zu7rtGRudvCQE0H-wQeTs-!D}Bm0o8xyO{jEQ#%R{?1>y;W;}U{k1CLY(SXW>-R+z` zj0vzENo*L%Q{P=J9m~m ztkd9l6QW36F)CNfr_XHIer}_<2nv|llxcsy2o98NyZ!*nc5f7M=$&&l8Y2eciFOZ$ zL2^2T33V&IE+}AO64p^*tO;SF94M@vK6N@4Us@@~H+s!v_IA-3IDir7*fJ2#KA<31Se_z0|APR8<1P{K~daU>WNd+>SjVA{|h77r2R>1-Wh)U#;(K71RFb zet)mdC_oT@f~laA@+j zAfG0Qg+lMFZzsR*?d@A>l%WibCIEma2SgaCv6w-qD{dlVJdwLp=ybY;O2*`9RxbjR z!O($gmravGu4_29+=>)n#WOjlQQZzq z3NsOUS*-)DGVJm!)>`7y&yOTPlnLl3av9*IbuR(mEu8Fh^Q(pKcBk61 zoFt_ZVc3O+z+>ni4giL;yk29J5bm`*Py?!~IBg08 z^cpZ}%sT2$GtY5bTWvq}=}XgI*xfbN++RTe^aq43uZw$(4Q6$FkOE-|P|vv2QE=i= z7mcp1Iq8?XAH7AG3^X~dc^v(Ed2j@blb`^N!M7|^Sj(7cDh;r-0Takfz`k?}N`dWe zys8|sTkpXEQ#1sBcYt7_z$Pd_)Sc?E1V{sPJ2;sHqiJ|d@r6v>+uHRpZoP+EKrsUT z>HuT|8x#m2$7nl$Zav)@+H_oit#gFa9^&RiZ^CqL>NdI(TBo8wGZnMU5U;qXK=5#MG z!H8mTrW`-JRf~VzDXu?BFnO{cuns6SOuoF{T;=2!1Lm~>6Hb^}$I5PdH&J~2=r* z5NO`wKOK-iuwv)}5DjYqrj&V6=4(X0kZx_ zBN#>I!#V{{H!~4+yqDGSS0_F~vIh(WgCV^D{09W*W$5>c9uj~B5~O>;|B1N>SRh-# z0fDGq|Nk?B;ehM_;S-5Q=V#|;bOHGP2+qyU!?6#|1cUnUYyLyN0}fxQDEC_6rvLx| M07*qoM6N<$g0?pR5&!@I literal 0 HcmV?d00001 diff --git a/assets/hero/chapter_array_and_linkedlist.png b/assets/hero/chapter_array_and_linkedlist.png new file mode 100644 index 0000000000000000000000000000000000000000..376c1da626f6d60c029f640fe67a3c387d3ea55d GIT binary patch literal 25882 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 BvNiw! literal 0 HcmV?d00001 diff --git a/assets/hero/chapter_backtracking.png b/assets/hero/chapter_backtracking.png new file mode 100644 index 0000000000000000000000000000000000000000..af259be6fb82b3618db3f31a9fe7a3165aab9aab GIT binary patch literal 15078 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 IM6N<$f`3c>LI3~& literal 0 HcmV?d00001 diff --git a/assets/hero/chapter_computational_complexity.png b/assets/hero/chapter_computational_complexity.png new file mode 100644 index 0000000000000000000000000000000000000000..7e5bf9eaf8ffa6a94f4ac2af50d099b0efdd2320 GIT binary patch literal 10586 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 literal 0 HcmV?d00001 diff --git a/assets/hero/chapter_greedy.png b/assets/hero/chapter_greedy.png new file mode 100644 index 0000000000000000000000000000000000000000..2ffc334481cc1d2dd6989f20176014184a904ac4 GIT binary patch literal 16716 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 literal 0 HcmV?d00001 diff --git a/assets/hero/chapter_hashing.png b/assets/hero/chapter_hashing.png new file mode 100644 index 0000000000000000000000000000000000000000..cf375aa7cea7b35265dc2c3f5b410e7830139794 GIT binary patch literal 13355 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∨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�G91beE1L_E}E7y)Z4xD@aGH6E|6|i98w4nT7!Y2o4xfQxKUz>K(&zx zAXf5zk&3cA990aXbK{D%y}ev^iJ01Zjk(;5`7&3WG!PtOPNYZmW1m~ny{C^+Fns5H zYZFC~G)O9{?Dic&*Fn&M@4MuD&#WAPX9F)32Wag(ZUaAU2eoRpkX@X*bmWi^;%Haq z{cB78g9rQ0-FoGnH8wo!I-QRzn<{TtdW{?e$$Ny>231cFjE--K`I3r*jfs$Fg{zYa z(!l82H>xUZQbGDk=ZiSF4X{B`((65T=iq@Nein+WtJ~Aj+G*mZL_T$IsCnzQ&VYe~ zAbAhp`ZN%#ZJ|TX$A^>aNRuS?kectKYZ|E*&?p2y4_#~GH9D4y)XUWVU8-#SXys~W zUGPw+i8ro*8R+f|`HN<85G4O8C#lnQ>P}d>;fnYm!Ab&U2!FLUvuifi4zon5OqP|~ zJ~7`zd;H5LJV&ZD>E-F4j?Mf?enD7C(Kgss3V%+Q=bn$*M;dEv?5li9LFwc#A!Zw% z5umfIJHL%K9P1xh1*UGe3;C z;T0Kzq$04AB-PR$q`?3IXaQf@NSn$|?zQE7)3^M@V%%?yAmbnm4$@t_%SqEg8VJ$@ zFV)*g$96&PNuoI~j*D13LGla@gt@&@swA+Z&gI%6DyrQ}GR>3!2`D%u@8D`7n*-HB zgQdNyff;}^U>iPy{6V;4qYakIf!Z2i{LLufAPDlO;fXa;sYZ;|4g^6E1VIo4K@bE% h5ClOG1VNCg%~uMEKD9AHU~d2b002ovPDHLkV1oCZY$^Z% literal 0 HcmV?d00001 diff --git a/assets/hero/links.png b/assets/hero/links.png new file mode 100644 index 0000000000000000000000000000000000000000..a0189f949ce0ebf9c8400a572380ccbb68a6375f GIT binary patch literal 135133 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%0As1qRu(!WRj`l3VEQK~U>0pUq0Yz+T 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≠{BY~tnm&1*Q^h~U>jB^wCeN$?^yFw4sD7%fWdk0B4)vvqlLObnZIA8SZ z;keTa(6Z$2ZdGc}EErX)g;mnrg@SX|A+HApz#z|=@d#v#_PSdtIZ1W?=mNQ~$F94c z@EaAABhjf{m-C&GjXerS=`wfqWN=0-vLxTBZ=Hx@ui=@YSLp8{9Tf9-9j|Hu`k|Ez ze1N;|Fz&9Zr5ry~MQnCwrqq2qOhi7ah*j%`5Mw;N7iFj)qf^Er2(9r)t7S=VtVmo4?NdnfwG8<{T($B;gLF)o;ST!+qsNlqn`-3c!=OpP*w!74@m*KTN--k`G5|y+M`4Dho(d@LwIy66A z$)$?D4=~KJ5^pWzK|rvRs0OOAHD0JH=;lqcUVEqmVXxshjkp5M$SEX2p%I5v`$YYo zg?mr|4k>t@PEi&M7rD?-Kty?%ZaA_E?e1;6P;n9AdNH2VR}R1AB*j)Y1nPraZd}Uc zHht{WoXzXa;Tn)l?=JNpQXt((g@b(eAY&Vb_~A!HL)CwbooTxs_((=AS%o9BQL&(O zU)W^KUXo-#$wmUOpBc@&_Dm%@czxX(lx8i77mB7Nj%^4b=9zXpWp6$38vXDUEB)SZ z57x#8ybYm&+liKit8QGdY3-Im?wM>H+}b2^=H32CQ|y9wbTxajsrTVJ`!Pwq@ESc) zkk($#x3jf{WX0EjY6i%O5(@68e!v;gbjqFDvg=G`3h8Y2$ck4Yl0H4~r~ z8btkF^qi#4ra)}~dRe%JFijOHUJf^#tThW@v>JWg^$J@V%*@M*0ZGKCFCRTvYF4kq zw8W=RONFpu*>)}-gKk;!a;00kd`i-wZD6l8fWtjwMc%wq@3*!Rr1Jv}b7IzCl4N_$ z+UTLxYOi#*Pm!V>-U)sw3M|(Pfn5nkV;D|R7#PCT3oCGYEk-MhueUPwi(eBC{P2Jl(&D)nG>4ud)RoeO}Lw~ngd0CeKPL&Y z9w_D(v{hTqS<{s~P~xC9yy4U4)lswER8f2CY>%&Vq^!FFc&oF!*Im17uUvZ-)+`~r zL7#ct*^s4JBKoUS*?_n=Bf) z)rDgrC(6L4Tk!*s_|erWd}>O?rwuUN|CFSC*xrB6bCPB>CzK1&+$k_6F{uiw{_Hcn|KR$-xV=xh8;r5?!oO_Ey> z4QjPgP^)e3k(-G%>}tIX6;4SyshW$*t(Ter#+F(Lus73B!?@r)c9}dBl_Vb*2y?7Q zH-q6zlIFBK+CvM;D+G7-?qgIM(b>ph>kuhHmvjD-Sx_xG9PLc2_nJxi_LcX7zh=X#wbKgHq)= zNl^xP!H-Fz*5uj@A?yL}I~(|Mc6UGDD$JKM>colJ^&#kRrg?o|+Bx&AzOiHrMq^M^ zhyskzn)UOXCCO+{{Pgf?-WgcXi^+#z8Trbdaf+Pik~)|+wnje^w=Ut8+;yIl)LUf{ znVAVNLRGaAOOoiAO5&T@WbJUSGGKNO{CLXol%qF!XLjyMDbxZ+TJ?q> zxrx*ocMpx$d6Fz0r02D}%@;*RD{dZj2z?68M*Mu81QLD-)>?jf_gt_@Xhuf6EOMQ~ ztPtd*WrT>WWuun$gT)=cROxfxT+XV2zVaY<8%xL8-KLMmJO=fCt(51NqFYt70z z+NM%ppiH_l(;9$v`=GXml2^qZe$fPo;^A~Uu4bt|T3z9p zt0rnMnCW8tGMeR1u&(kmY2U)z zZp~mY!>{~!%KEEaCw=#Zt16^gj-z}I%SBNvgCnkKBd^pcfSY z;UXJwl?Tv$z?ZQUekR)hqS^L*jGs#+(~3l6O#jZMw0!xcGW@CRF^Kxi2v(!Ga!_a$xwyFOVEsJ{0rFA?Pv}d-TLSJL315jtnRWY+x2Up2TU4Pqdb`$ol zxaZ>HeVN_eyz(9gYcu0WX`|^#leK}J7P)g|wAfQNk);m}V=+QhMweBGi+|LmtM-Oh z!GDh`@q3iZ&Do3hXph5XFZjj#>p#`U;jKKY;^KekFYe5~P2kZCj z-8%}xP!I*s^`x^CK}0Mhr3(-XJ6(Y5cL%;EgnQ#Tdl=?rG9TFL>uwVloB2~oRq*F@ zc!?xBB}I}gUG$22-5up5S`Bj2d)1tz;y|sWnOPMFdL{KZ+(i<#l5*1JD3WNEG*zK? zN3Wle^!QAA9H4NUu_`#F2J=a?4pvy8gLP-B0v5qe5=9kr5f`rTc9q1Nw;gYP6* zB$9LsLEYBGyvN}zk|>pQ^+gq&UP(O;Pk&~qm9!UJ zw-CLO=95fS&@1U;^Zt4=RY9qwJq~Jj^h)}lbep~IXf>Fbo%J|CTTW8DqgPVJ!A(DU zMcq#lNz_W3s<7{lUP+PU&n&$LwY$lrAGB?b)CJV zX;|#RreWKtF%XF3CR&Xj4U`}iYAG?&1hEEI!3*$2@WOgaJ!ubjj>7Eh^8Bt~5BAUO zyfd)zrPJ3P_DK+5I{mBS6ZT0ETk?|Bp3Gk1wh+XY{5+}Y;5-T78SXgvnB4(9!yN~u zYmz1K*B6K@ohA;J(|$xr5Kpp_X5SXB$wt%$)o5;|m^xWe`XPCo4>o|d z+B_7kr>+~c!&FXf09_3vCEfk<3rwMO zYkqStd7fh%KvQp4JY3&9-De7=ivH&(;-Q}Kc?Y_B;NgP9bCG2#6-4=wc(@xIKufQe zJQSVuYVHA3DJ!ZCF0pZJ0398Yq@+z}>zhoaoKx$a5D&L}X9MWxD-R?kEk_e8#Z)pU zi{S-viTkPzpqcj#SxB7j&iuT=R7zRypC{rn!R7TU8$cf)hbs!W%%JLInOX&>-RE)? ztQ%jZY9JCy5Cni(P+|8$JlmrQK*>>_wy@K!# z0}hZ7bkS*w3{&sGU0~(_3G(yIwNgwyqbR%v79~gsy6DvE85V_{zj(k-2@)b0luxZR zi-M7_SC25hgG8Y9XdyBz8hh^UcFY0dk7nI!J#Vmx?7yuYFR>^=`~{b1eru0KB~`3@ zy%|!1*!wuFK&Rm4M#%`(HyMK7`RWBt? zVR4R5T;w%l*Hl~aQu?glD`^UfGd>$|w)=%-80FUeOck{_(-b^CMfoU(zU#YhFZE*5sEp&-m(v%);Fx*MvY{ZAy6NNON&o%Z?~BK_qrWv$ zqa1Wn&KA?|S>K&7W;T?&AZ1i)rq|(z?s9n2{q$q;cxF2qjVjpoY-L~jp zt5z}8rE=GL#C)8z-P6&llfCZePt&XUczmSM?2hq#el`8@t-JT&V{q!WC%~An?y7n{ zT2XCSCip&z$>DQ%@NC&1je`9YX-hww1bMaD9|Tly9-Vgwa`z^I+?Hab&|oukd*-d8 za*~|+*T4N=hz_Z>o!doePagV@qQUUb1m)0eqJMfm1*6f$^4Wp=ygd=Xd@!wsVh`-L zQ7PA~*2^CAePk?xNQ9vfA`}sA1XWQ?(xy!$2x`O=s6=!`7*Q9^rah`@6N;25j7b7S z))~=p$tJ!11^%0)w2G>gvudW0+*=1%LPX)6~MYog)0sJJ0YWhJ`h zeBwMp^gW+JuVvNlsC-wqNvTq9)aq8V)iQg4$PnVfd&q!83`YPD0XZV11rU-d9`7YB z1O@;!ALHUN+QeYoj$4$;fZ}>_a+(PUjHOYOoJFUZoTr(H6v~t7%tHhMS=^>f3gv5} z2p&sC;Z{*hMB!Q#VI_(*%(*0r9%e#tQxq~$NJO*gH${0a%1AU1C6ARTzbVQyQKSqS zBvDTiWr--}qR3=Xs?)5zk&9B-nkeL==uwCCGHny3(BFzOn!*!N_?;+_C~(S@&nHA+TVYF8VNpUyM^au>L`X|m zWJ+3RVo*;I?BWovM3S5k6OQe$gyepOaqWo$=WX;DB& zY;<^VPEuY-OjK=opkQ5Zb9B3EWvyjl7bHG+P*fKrJ-~HuUr9?ABR!d2TZdR#a(8=b zVo+Uxl5u>1Uq?!WQ&o^!T4hU4eNRvnBRxi5Y<*8tab{0eaC~)fZ_t8t4wIJA8qGpKfWSrJ{CdNRMJ(M`Cf7nw4v3W)UGhUx0~- zXJMOEQ-_I$Z$(SaxI>JNi@LU?qhetX9XnfegnV&Nilm~AglP^QJcf8=e0z1s%CVV= zXsm`?xtU*_jYeEfPl$L*!-jausAQ|0OWBr%K08K*XjpcPm2_WNnub%XudPcyLQFnG zI4n7(r=hBEYKLlEZ(~nKJUuErQD=*fJ6L4g##V`QVP&|RL}74=eMpRcMLsq_g?B|k zcYdy`lQ>gpeYd8XcTz+nk%n@dV6h1pqF)ngo49-aJ9Lus;Z%de|h|Ta{Y#V)^u^~b#TdTX9p89bK$p%-@J9Dy8Wt#{FH{+ z+rY}q#r^%@f3nG}SXP71vHsvR>z07x?8Bqb!r5=mvsK=Rk~hU+S=9c`p)jv zQf$nr{>oV3#W(ZPFzvQo+P874!n``P`${^rD?d;I&Wi>uhFipkmilKuVZ z{?ggsh5g>Wry~9P{rvp;)%^VY{%>CU`n&z8kN)7sa?5@FvX=h({?_=Mzr6na{r>&k z{o14E#^K%S&;9x2Px1Wx`@{R$;Jc&#{rtoF!TjKHZ@RjcmjD48i%CR5RCwC#-Dk`T zaU2Km?_HzE(HL ztm<+eL{&_7k1rIyDoF}qPK*RRNKd{o4<6i~1EpDe+!_GIm6_-UAl3)@BLAX)e#N|e zkQ7^85aicP;?;N_NJ7G<@knv_IgY3JRgqNu7GaTTY*j-M6Xa$03rVQkgbBz!9w8jQ znv8`)(O}SPMw*u0fBksO7CRKS_>K#I&16Jc%$>Ue-p<8Az9`!u?dY~43-ad6uYt;Y zj&L;wz%?BlN-QP4FDQ9I96E<;!}=H7+hVoWGj%;s4Zp@c8k& zRRy6idl~#ag8}K8*qN2S@_>9%V1|a?4W`0~c6-~kE(&#Vuk;1HRx5*VBFU>EAeQW1 zYx%KIJRT1@K#2TIE2BO`xAW(rY6V|D$+;5PyTb)ml21*RVri$6N_+uw;%sw?#yM=I~XAsM;XYV-0D3B zq$Bp~-nDBUWR5}Y0o=H~b^^HZtV_2gm#z;qLv@@kzsPeO$BQdnPE)r{!qub{y<9lX zZ>lvJgea(0ZxCgb>-A45==Y~CF@&NBdGUV+cVHm{*3JOEy5s*@hD|Gof5uom{>>LJ zTv)Tx8w}ENn9mxwE(@*bI9m$f>$fjmYL^$PWVO13{++y(!aOfX3m}Cs*L!)b^XDmm zGs=`})fQTXL6lXzrxAb88vx)G&G1Lz2>s!e<~;bVe9a*Tc5F{`-f`t1hni0OD{HTb zoo~LnctLXU+71m(d@8GP#q!XK{Ch85lH&K$?9xy*LxLBQ$&Wh_xDCBGZQ69q?ywn5 zG!C61d2{Z++s7d-rtaEWkXmX`DM(l&GLHGDpJ|1}?*#%;z~{qn4cmr{aE%+cahwfh z-1u)!dl~`Ux%0JqALDnoUjqwiGo-YJ0vH7c&YC@Y_THsx|MMN=r1<@qz!D*xk}8Tt zF_K6e^U>%Fky*%xw3K^z2wHOJ)*(ph_k;#`0-rCe+l1d4GP@8^tq&Au-GAfh(T#(; z;J+~}{u%4`uH2BSe%)4(&)7CqG!(!v7wx#Tyvir7&AuJURP+j|YnY38CBbO0cu?X` zBzhmqx%!MK%(c^qwAcq}t0%&!JCz_QR~PEXx-9_g9sm{_ey8yDB`7$18?P1VO$sG^yN%0g;6>%5&kc==Zvh@j`gh zCTSo#$vHuYq6`7;#8S>+EJ!h0@COCzG&*YKrVxA;5ie1;|&n z_UBqJg0>!m)hSP4C(nxkmj#kJ;bdfZ|K3T7nDqp<)vZs{&U$943ZhmFelKs0)2C0I zJaM980Vr)i7Yp`3U5KnP#5^!}-i4fJD_dYugN}{MmoGo!#o03zn=~oixM+d0W%E-I zr^~Z45n1Up;xqrp$~T%6cp=%lI>6d2$QGv8ojYBiCp2V3bc1bs=EO-UfKSZcW{2|f zOCkITYeuHACIG!ABIo6svuMWXCanjytI_i8sWX);R&3q6$>=t18kD63PLunGg^spx zGQp$*IOYi?g_Qto(MYydKeJtWEa(IsVbs0|o{)c#r)Fg-g0ElS>qI6Q?Z^uEL~6_X zi7kJH#?8*19J#PizWn*}+W;DhmWfmVyFT9hKp+`|#NbQp6n$1?gU16ssX5ICFjNMU z|J7n_8K^+jb|+4p>{r2#@37q~L7xoSpOjOPBJIyL0FjqV5ZnM*@#8Hd`0-Jh=uSSW z!X}zpQ?L)ci9`-_#|?lA6itml*TfGTR}Sj+5!0a8Uo0)nD$}vPa*IujLSo><9!O$B z0G}}KL_%NHC?VQqDQU*f%ob!;qub{yU$287)z?;!GNl;xp4N>k<_D3LJ03%dg^PP2 zF{JKaI4FQ=5f)LiNt2LK`JO*tw(R*5ke`)Vpx2T3FB-R|0G64^IgpYkzJo!EBhJyF zDIwa>dDr^5daDgw1ND@ z)k9moQqu_FCMrGJPqTK4_!7WgeD^IOg#3hMA+gaGlwZlC_k$ZKfMw?8UHBvr_u-2W zN1NY>qUf~CjIvYvPa=b|qbY!8wKIy(#JB@ri4o*5-LGZLKF$2|DV%<+1kzxZoCXj7xonC-giH>!H&XiiBl@)RgsvwXv543yCQ z)-x}DqtHSS`LKELg_Dbdd{Ugc&nb+Wa}x3&7#51~E*P2zzroPrJEiz?dC)mSOe_jh zHutOD!?d$vg$oX1xKnNj(5z~iD#DV-`y6oqZ<%}N<-7dQX#s#!%}Ua> zh9cT`OAg@Cr0spj`uZCMlti#WwyGl80=V92M_lN<3LFY3ute^#aFXCKE&FAs>aYO7 z5j>LI(`I*lo8T}lUH-8XWEx;?n<g2(3g1b#P z@Z!m<9svOC)U<$6qqy|!NsEB5V$B4q02{bvCA((~rMJH`p{=Wnjq3QS{?YSh0kE3a zE#+UKT>;_OdiHBH2Qa=rfaePUiX@Wa1^hb`sldVyVln;}INOZzLitFg1pufBH*X4M zBa}NMjS2e&04R4i_X%a7ZtFBjVRN|_XA{-J-_>j;013d!+S^qG)$O%%Igcz=lgOqc z4Oa$IsY0Br!9N)>Q2^jzKA(!9_GszL4I5|sR2tDmqh@wQWvxJGq0rlF7=?I9004Xu zDt&j1-zPOTssy4tFC3oRA&YsMvjx*Ix*7Tf0C1Gix2GuTm+d@Lbb9E{gAQ4)HD?;e z{iOl`z(G#FU*?ah1orn24X!=W*W;DNT62c+HnUCu060j~-cjzREgpU?MSl*NLp()aEUq*C!m>Cz|M0ieS8cD#PN z()A5JlQf-wIfnCy*6b%{c}UVuG9L|b43???f|Rm~YI#|Zak)}6hQEhK{i zfXcCA^#}pOoVs>yl$;`Z*~oNf1~TUb0F}dc^m(0tVJ59Hel=y5K$wH7ErY5(>Udk5{&cI?b}awJ^54w?&F3^ z&%S-4#w|a|QEyR~T|bL8FiI?`OW)kzcX{TRH)9TPdNWaIEJHz2mhSThZ6Hb{LmocN zX$f>4^YAq9%n?z@7=Vc)l=EeM8T z^aYU8&5TC1vV&wwcF*hTa~}qQ;+aYZ2?pju*4p=l=m1d@$y{rMb$Dh-$1D(qDD#{Z zM88Y%tW#{#oha&39xNJFbwi8B>3L0&5}?^eE4y?;JTX)h^MFb8onz$ns;g~4M4uT; z&7fEju%sdjMD*3V9@nq+1rdEQy}%3+6f4Pv#d#ni0L=#7sJeEuClXHUuB=4SU!<&Y z^@l-Z8ah@S6)P7TAc}~xB*oS|WJgG6wXtcmU46Ie=FRK3k|oEn>@+BmX+^#4F7D9( zrSCn|s4{FTb6J&pH&+P;Ru+$dh$u6iu^@xnETUq{V_tY^66SNOGkZ_I+P!MB8j^JN z1@EM4)No#`t*NQ0es<9aiV3v}7*YCkuh*S1BEwyJ@?=3f6^Nus^Z8`f%QNH7oz+PQ zgJr4?zw4J1>cro&}r)A28=WVT30LI51z;-{7K zJPogltOBBq=jlXZtM_L^R*Y-!WFj0o9i-EZo5=V}aUyxrw(S}KhE*@tq~Pz;7EH@w z`(6Y@6-00D`&YHE8|FEqzq-+~e~Mxkm{9oa+07v@=Ak+ek#xe)@;3OZW)olf>lY}o z?_V~u^7B0nuU@_PxbqRF)ctleLOV{8J)uNI)JP&zx1iqdJIW+<1oAFaR@c3K_0Bs2 z0>abZcOFDUl$e?y&9O0eDU|?NifU?H7dEeamK%Nm7Sgp$EE5qCg-PRZ54`mBX;JU| zyu3s23!NY$BBGef>XTdeykX^`3;@t@L9ou*S-jYrk8hk6u1yXk4&A_JJO$Iwm|>ASyDu=2bH*qh zv@|DWWU18xzS~~n$wI;qF?c#e5K*K|c0HOxvxR`E8-f7qr}{2=z_S9 zxTSNGI3p5qym2=vp@|m+5pfg8EAQCGf*5T*<>~YMKCkv-FSg`qf6wp#{~dpA(A#AE z3&Qd{cjPu}oWvM&0{*FEV-X@@-h%N^3m(|EmDUv#^7k@#8Szh~=Fc8LeU0QVq%O}N zhkq%qE<%*<^I6SC@rM8b=(DK5{nTBa< zsHe)o<~jRrJ5Xft`?t@WH*bv&644jL13*#%10c~3LdaKaN_O!`xz@puDC@U8zb#0m z`Yy1jXBtPYzvGjwZimJ1@;zU?c^#x9iU82CpzP-~L|H05(j-)xWC8ybV>TGFRd)$o zYkzGJ07kQVGQ0>Finpt1DN>Q8&!z6j z%^!&WuBz$+@VJw;K*%4}G$AzHz`BTaMgCJy-}QO?%x8qe3KIdOiU88mP>L52EnNO1 z3cw^p1MZ)pJrVyNXQIT9gn%(1G;zyi@FxA2id<)3y?U}_doHBb)()W41^{US03_JW zh?<5posWbnVbl;1LS#zEBQ#abh;8nY`A_e@dgb${Lvl%80kCiQmidmc)(0VSkYofQ zM6T4)p_lI1e(KqSr#|0PDFZOe;VW+rY}QPGVSsqAm3F8R0*20E36V-Hf0~w_diG?K zuf*e@|F|ZkV@}qhOpdq6V$DIRWUrDMk+k$KK_bM>m_z9|A?gmmyavMPch44YTjx)Q zX2r8@kWkVXQ3n88=lZe$%m{X84*t8QW=N!7JrEL+b}v5;10h7!93AH_p4%SaZ2%m; z=T#sfuHQ6~g>AgIza=jR5S>mL48n@PJrEL^uo{F!q}rP|T|fv?v+A4Yo+|O!Dk`Dh zZG)uZr+E*r_Ybx1b{5#|fg^G_vgO7$gf!S*6o5&jQpeGLFhbN!Q?t!7PZ27({l0lT zSRN8e^E&(Qw)S`CAFjq_Z^EhY+Gx0`<~IiWh)f_xJNCU1z65NQad8 z%z)FH7YGD{&ddakMFiT)b6l=ABZKjjjI4*S(BrCDrs_~6qYQ42h)nT=M}S0#0l>4+ z@B)KU4vTNDI~@{>o8}AzgF)vPdDg;C2|9!)_3iC=$WWDxjCDO04d)OJg9${L411ne zff5}!4nlsd{)>Ge5ve$AW@-p1=WxwiPygpFdM)oYzr5RWiq-hV60 zQJ=PqYt3$D7!a0L6o8d#`sfTpC08W=fbyB$? z;?l(MhEc{(StY;C%zTFlS=X-Kx}1Wrq;v*RsOpOkQC$^@eXIeY)8=O)<}IxXxiI-$ z0wg5{gH~rS;Ea3~QoMZLPb%;yZ{E6o<$7a;r*A6|r83FzIVB`q#)W!>E>V{EgW+kv z60*^=xF{FWF&_va$oW0nC5!KhEK7nTO9mYuI+=RqF z20y7$vrimUg_|g&nT9R87rP;m1h3Ps1CTs)cTfb9oz4U(hS2PCkJgv2neZo7s%cP8 z+r1WkDYGHu?}yRXwUk-#t9(_ffso&@xhAPB1J*t4-2!sa!gXqWI;5Zxt%dO@W#4Ua zZUCUSdqu@e<1k$t4%F$EA>dCMXH`X+I!!qI3Oh;;3#A7PNapc7DMozLH|-8h5Y901%p2_Pg;~{CD+d4?b?j?{JNbDA%$HbyLNrF7IFOp*2jTQpP@gCOuAp zd~i)UL=}VTWdWEUZ$ntRHslZmHdk>`4Jm5bIee95bs#w}4rS5~cY-3cDQ^MhO!%{u z=1r;r**E0$VE-&`)RYSb7*bhOs#ccn>%UV6Bqj-apU==EGWE@B*bt|7+a7;Kg4Ha#ukH|lj~02rIK28mHzH60?O8$4M<0a)?0Ctf|+v}B=d>SgOjF90(- zotEQue530(R`Q%ykMLA)$|4FF=nRllp$MQr#5a0Hbg!0Tft<49WD zp<7St7>a-sNHSY2Zdcy8J{R6CYLJt)ZI^82B07vBEl&oJGDGJ-^1SnR&ktnz5E$N0 zL+2od{?*l&#xYPbM$}_jvYN?Z>!dYUN=oY1IG~P<-e8p=pplqAZ)MKq(S-x@3(Z14 zc$Co-je6RlYh$X1j~+YF1w}#XLJUhUzGFL%S6e$T8{bU=&Gm8r5y{`$897t5 z7b;m;!|c2sLq9a?P&g53?>uN^E;O)^fL5EcI~uib4?Q!Dz3G5?%-Aka(t8OTF^EZs zy#QD1YX(Q}8aBQfLRv!k`YUV7p^}-!S}4U!y=en~ndjecGqdaaQnS?RTr@}@l?eqW zwQ{MK`_iTJ`szVS@v_mNPe==pg43?-IR}+Unn-)5E#SH}-f6}cW-V-n5@yT;HyX9c z^WaaDp0Rsa@~bw}`?`k>q$wPP@X0!Q*|OtB&=CQt}T4?LE!QlhADxIFOr(MoA->Zl@xI z#KG8+vxrbc%9dtoDbqY4O7hRtr9yOY&=YPL#lv@;nTxNaE;_p}g%F};qGr>Mt!U!* zNV(%kh=UXI^jr=?dFu$%k3T5{CWMeUbw0)LfU1>)it0)p?S=Mb@ely#+3vbtOMLky?Le@Y&S z<`|ish)ReKIM$lc;(WFDY9@e?X60KnP(~P6b-rgyPy+`W}E! z{zCSAuu3>obT)DX8ene+LI|sD$MewQob5G{zSD*_9CV{9N}A8?Xy5d3!(i|*4~M{n zkk&N5QWL2(mGN}F9=A0p-I&cmXYU^{z`TMQUI-!au~t^f{Jz7R;0Xqpt?(h=Ihf5s zi+cOP5JD2eQ(CFFT$(5R;zfY6;LPim4nhdwSw+YXeaWhS@jlK4xD!>8C7z4f95hiv z2P?7J>EMDyvsQ*&(3gU$U}wa`SiA!y(WLPv5M45GIx1ko76xbDkk-{DRLa9ZoPQx1 z5f}N{bxL6;UX~j~mjquAaLB&pUJW&dk!V6$xD3q`sO%(){aGyqXNhO!;i>>azH=7e ztL1WMLE@2C8up`U7Ejhjiua;OHN{NaW5N5j$YX&Lqi3%bO%OTiFe40b*q|O??G`%- ziB=E}cZ4FrHh1&p90%_&`hVv2f(02)a80&BNkQGGqi!=4&7BHD{*shsjt-I>%f%d8%3>;n=;us})q#}6OYz<0nDx5@=X`r_v+@wk7)vZIcn3n4#77LqYk!Bhy8Q zfQaAOHeBVhblQ6Q@lz&0m|fEy6vhfyjE8Smq+}NeNi0k0+xqc8W8Xm4!Ky&E-X>&e z&V-7<;sYZQ+tAf|X+KPTebog>RwioXROJ8k=`o9^+omN4w7R#8Y1?tXlz-+?WFrVk zu&g(4!xctAkh7;&9X!|&{8Hf+^L$HQK0krj?5l5F=e%6&yNyI6 zi!B%l664a^+k|-Niy{cIw0b-JzI)H_y$^l4-}XP}XimO9W(P&hPxOQ0S?wK35MdzBuc>?YRRcP<`$JXCVR>;Xb z&4_d>+F=2SCp53wcxN)?QSZ#N`>_@HaYZELfqLjiQ@gH8W$xt*2c_5o9Q19V(=R`? z#ky{z@Nd;)Z@`Lusry;LAGqvqUmvpST3QW+eVQrRh}rnI8Dt^sJX=xm{MGY01xuH! zZD0+lG!~B|EJ;!@9F@Ye+d+lIMa5h;i0j`4)$1Ux6tvO{hJP%;et&B>4 zLp8D?lfm06ju$*G7`$4Kv}rh&c7F%saOUd7ZF4M0qp>fPIU1S3T;vEvf?>xlYX-h> zJ0ng;zg>jHBM@`>=0P^g=(IFcj3*g(`^1hNI~F|4L>g5ep8f(ALsuX!#~Es4G42@J45Xhsn(xiOXun zo_!3xN=iIdJ^rZ3RVsp1y2ji0P6kOmzY=s5Ugw#ctyxx< z?!7XN_#3^Ca#-o0fBJr_t|q+^CaF>R3YII%7TNGeMtb`pL}r6KfF&ja{w34tq?f8R zIQHTE+J#&;-2UU)Kxc-q| zfs<8t6_by@--x9a{Fb!?J^T4&mC3D|DK zZ-|~@TBO2ay4EIYX3Xya?qoUav>i{4Q{C`;qd#81c8?M|$;)Ic_4o^0sS&@@c}lEE ziE2~ofDrZ4%^bvGhAziJIjq#E-5hkvPNWP*`JADH22QXBQ>;LC{#ey z%+j(GhYK)f*eQpVxa=xwM9(W>DxN|zka)qHUm*Q+kO*%s9NYKq{Jg(nStf9f`4gxx1|~XtJ|%q zNRu2p<**WV`mF)~Z)C=nE+9%*H`Ep17;R3vY9b_cn%-?=#{a5WTnp*q@zPwvM9nHj z68fRxR1l@p?l0BgtFBI0AJl(Hf0GOhvPRM*I1096-- zTzz@WXAj{TmAfc%Aql5S;?T@cQ@ozC3`sCo62Hc(82G% zPSxtWB2rZH)dS&}Rvj}g^y9fd=o?$|yZ~n`qheqtEgHO|J_vUNTO@M0s7xxO_XEO# z;t4=I@JyHA2pqGxLD@J2iwarM<9Cm5s>Kf-}7<2BfjjpWpLy;NR;w+jTU@nPzM=+H8-qOxp?Ch!KmDqJqeFh=NoiXGrX&vVtfOf)d-9 zq>>&A#6pDL!g=r|&!_H*Zsj>bqymb?Iys8pHn zD2agE+jv{*3T&#Vth3{r;yxd@@JVp~W5;Sjp`MydM8UYft)ru3D@IDv^7$a5Xx$zh z9+r9CnC12TOuljlgKiLs&9Uud&&OLCh=!-NqwQpa1tUc{!U9YbHKT8^0Q;of5J|4^ zR#@?aQr9Q*zXa(-{?`StifC+ZYkj65j$DgO7)J6sp4TLb-nFi-t~yyyf7q*UOu#R) z`szR=xU!o0k9uYz8m>D@h$lx;_f`xeDPOu<7>EQksxeq8>+JBjGg(99C_nJKK!UT? zEP`6oBy`&;qo{j7hU4amKcX10OFQ@N9&7nCNhKFVLi21>0mmk>=LIJoV1*^3f3hUw z5AJtoK_oPX14Klcqj-Iyq_R$(3L+vRy(p;^CFS+vMUdmzVP|}_ciodklL#Qv%Su#8kQ8W(hfVPcVBFdn*w$*oDFQ^9*5rxZk zSmX66WeJyMi7>stGtfK_mW(tI5m7h}Xgnrf$(aI*Ki7-?mgeKzOA9<8BBF3OWsSBD zSB}pw~_k=vm?+XCWvO6W?4!m?oDF41BG>hlIYfh=>TtKf=3H66SCY zC=$xd(FjlBxq{NW4?0^uO$QOt?@WR( zQzh0>6te*|l);R+*gFIIz*PP5+ZeR8kG7{!FxODP5^>!ND*n9 zdLmSQ9waZ99g#9E?RDZCMdRb%f0dqr#4tMmq!pSF3l)Q%ugetJZGleZ6bxl68ZsQb2M@xnw}>DERK+f_W3(ZnPRoG#>s&B$kq% zTY|U7XgKQ021KB0`SP_(*YE0mIXh=ne)bgBUumRPpWkxOir6tKz_q7Uuzmjg6JPw3nY_VUoaT-6|+lB6iaDZ z&;2I>8D>obN#zTB_ZHhy9LE9tdrt3+Qny{QnN6&jrgW?>GbBSal9EP5tq2c zrASGGMV7`x5gHNKNC=)J2pLKfi_3!q@!~;*n0T}Y?IK|#(QehA|LOPh&@|~&)1LD^ z|NsB@|NoYMy|sJy0T59d4Zo1XJ2ELtjHB6&K`@KY&Z*hG7etg!J9p|plv&nNkVx{c zOa}((;Io*0u^ozxCs{76ve7SSbUTD2?Y45G}5Bqm5*MfS(Fanum;F1CLTK-NmQj*7`C`nZ`S?_2p4_n?cou@ho&A=i@ z>Vcb|E+Hk7aynu4S<3Sj#bQI>E&ZS{SPEPee8qX9%jlx@bf zK`(&X`ojeUU53DtP1NQwebx*BP_YEiOzi{e&a!YBkE9?X%D%(a;0(azuWugOHOBnq z5RTMe2Vls>GCL}K4ff4pP6 zHaF~uovKI#up<@=h0FLX*_~w&cUluEmoX6F;#rQU-4<(h&2%;TV=+flEyOp}>2x^U z3l>D;@#}L}u;3_FS`(jHgk-AWpIs#iOF%hdSg5)F-Ip_=kiWj(KMdltpYnu49WNvC z`1KtFrA!`sMAQPjoHlOX4iJ$@Y zwi%$5jh!_ZB#yq5N(Y8&RCZ*^69dv`_R0D_^^s9Wz89_~*Yo{pyrJds2KN5WGN@J7>vF;!zJuk}=|-i|COscdb1 z6ty-sRv}q==dX*n(Ltp~1`guiiUNEtR;AK%oSf!wP{mNOA#^z$aymn9cgV4A( zsINPUq?yLFwY@3=5mCAw;}IOaWpYI;RZ$g?6Y}c@14XG+Rh0w+i^ZSvA|mA(VgdDv zH2H~@`74ac8#`auB6;P7%wHlR<&me2o+fNfo{SXe)zB}?ur?2I`Vu3Eez14%Ax*_m z9KgT#?%u7b%gj=5YG(GBxn^onmOU-YGAb;RjNT z2o^P2f!s8N*Xd zS06rW2Gm1y?HY~Tlo<{|wYBY?L(xyH66*X!lJq<(($lhcX6f8EpLqZ0tSX~X%BsUo z8Ugi)f3!OhL|zySt!?k<%%K!C3AlnAS>KMMpqRRQ@d~96c8e&X%+C)jP#HMXGV&{1kssm+B@27t0)ak6f0+U;&3_c-C+i+ zdHKgO2z|ss&0hiWfy*78A@CfVl~q<`g18tU=itqbj`nNEK!`%ETxGyOXgK&%Vh&u> z<_&?W@q(DU$0McLzUxFJBhjXFe$x8j2lvjXnySP%J| zSrZLk(yFQ;PlzkaR}X^dhH2q~!1?(s!EKLDgAiX>zZ@5C!<|(tA%EseSIw~?g!oR} z7>G$5rOz!G+qFdCg~0bWMQj5hK4I7!et!(Ka4k;$2WA*F=9Wn1vW`~83Nn0e)2r8` zp=g^vRu+arN*;Xbx$DWhApZh8A-+Zd*BZWWgvvOwXUUMW>HdRei5zi{t;W=eDn5yHwG6e?kUmVsa>QQ#LG^@4g9{88Hkh^YrJ}uTKy# zF$!O-1wh<*W>-A?A!-T&A>=TRK51C^(f#V4$1cdmju;Rk3Wi1h#6|+b{K#0hAK@_X z?QR9PkGfd_w`N8Mu7^5rHA59=aT$gnClUTI?r=cb@CQk+G%|GvfHATepv7<83POAx zfH@AH(X3nnwb7r}!#l!Eb8c?f+9kR09xt1VmYitx@P~>cVNqHPT+TxfzcL(vSCp~! zVhj}v{6lattC{EEGaTn4yUj^y=!OeIE(5Q`rdd)P4&xiAqd;1lGKoLvqH^;KOG|?> zaN+Ynh~Mm@1bpDItXIh}hU?#r9V@N)0{|z3;Mjl@T1~r2x{88bH(0RZ?n}~oszl?hh}9gnV1ly zfq8r5(P<#QGV=5LLMlEGLZD~h0_#!yWqNsia~eE#{0yMza}IQ~t&KhLx8CWH)LLJ= z#F(6!Il-8o-O$*OrPl`qEBaRmoY2C`%F7^x5FhS_U;(VT0}pX8DsPm?t|IJ#v0bfQ zE%ti5-L^qma{-|nk(yj*wOVb~2Im5!(U`h$`lu1qZY{Rr#aAvJGJp_5e2Zb=sWUZ} zbxk2022lA?$|4X#T<+PD>fw$| zs@0m5VQg$33nFF!miSy5i9?{sF$n0BV^w6vv$p|!M@nyP)D5=5vVc5167wg_U4oy1b2L_}ZryfoDEgxVSDOgl68oO{3DL(`Y0$z<;N&i%gce1{drv#eBp z4AhB7m?bhBqqNL2u%w3!Ku%qKmfEj~2FYVs`C>0!3_^$+gqk1B3~vs?j}s@TR7?obCG8y*Z*~8o<~9{t*6hNtx%3uH2q78}GcOy2AL|b-%Z~#g zgb@Bkfp9Z3a`3Rlhei$tA(2O!GQyZ>>Z#V7j-zF$Mn0WCFaN@5E>}XaH*NK})|=)G z*N+5$l#WzT3YKNL4K7*2p;FxowL3F9f-Dh!7P3*jT(_}=7*^Uru9FB#i;pm|P0yH@P1W4VmIYEUl(FUpk z5{|^gf3GI9on%Ci3{g;(+-C>a=Ar=n2fC?}UFJm{0mqQ+U}E;O zduEUjl91p%im;GGI3du3$0|b#f;DY8R3)!tJOG<}PzQn^;z2vmiIuCG$ak&Ev&Et1 zDS*ik@Sn5-2^l3p0ph)dHiUyHKtzV7uU^!fk<*|qJ9}+8q5;3SQbGJU=-tv~%|ftB z80~-#IS-d#eQLK@Q=Zlw>YZ`Ybe*+c-$h^`&0BPC zY%#)M;h7JwtE)d0dJ~|{1dir3-_Gp{sk*dTzIOe5=@u}Bkq1w9I@fx4E?m(QyvoyH zYQrD{Gxl{KQtm)RiD`Lu)F>$H06<{mTdI!YqW#^%^9k6C4}Pfrboo;uyUmY;$@Q8` z*4&Dc8)a=l{4p2y1Ply!Vb#L!)?_oOVN@@q4B3sy5;~M+B}#zgsnUIUQry4NjBx3D z=5=C0roM~pL^Xak*WoQoG|nlwykgZd|5PzLz9wQr=f;o zH4FHg*qrC?iMSYqLi5=Mh$aLiqkq*S-_5E6F!5CYPPxF%fpNi!?<6N*A9AfM3pJUK zB0r_XAb8exSqD6=-SL#p*B~W*mJGn`a#`@NR^ zx_d$3~!lawCy8G8eq-J^0)&uYxq9FS#mZv>I=%&TBstxH zz}egtWhFj7GaF2DZcEQC&CD!aA~*5q>U&oU$+GbX2qD4hVFTZ~=0QiA+)M@_CMTnI zhCFwUEyLy0;y_B3jF>ZP+m`@b000W#N7O<}Fb5fcqZ&~HAz*Zamv-4);GDh!u*v6> z(Wc!%J8G5YNws`0@{`ao?aCcnnpxnCc)MbQW?-5eA7lU)8&SnL;+CEVVN5)ib>H8m z>M8&`-8Ztvm5ei?Hb!fr1vPBxR`}I18zeXf#*Xh>kb#I(;=r_SWA`2a`9@S2osImN zy*mq;DGcKP{y)o{S$P!tzlYJMmW=kP!Tv#qpC?yw^ zWegG`MIjf6geWDl?}J&+%z4i_&+p>9`M$oIrgPr+ecop|b{fBM)CJqLcqN(}k+Ck& zd59V*$4KsyI)Cm=%WPf(BED(qM@DtMAi0qnP#`ap(F1qW0{m6QiIe(O0E_Hp@e4_h zF91nXkEfvd8Xi+p^Fj3N`4`zlN=ujzI03Dw8n2XynG~m=Iog+$Vs3T2q~h`1LqEG0|KD(?CaOB z(*mp(ZWJ}iDFt)+uC0^7;EizV+=Wo%ma$g#t2(tiwJ4{~q3No_7q#S&10i6jT4_>x zE#~ggROqjG`2JU~?qv7M-a=m!QG(en+iM4Wf#~hjqe{V`u=m zkhOo+PngzXUJH=VEM70ehcKrNKci$RQW!DZ7)D}gxE25}At#KcWfG0!dXMh?(Ud6* zPOuk(rez_6N&=Kuj@~cE)!9f{&;W*Z0U?Z-(de^_N1wBI0@iSXi?;BZ8Fs1fgk*IX zttDW<147s!#*glvd*Y)vPfo1Zx^8MapD&{I)_Npoy0}+1)=&Y(aPcZ2gs4Fnw!O=W z6DOWec=P1py!pE~4OqXvYk3O&5@Hlw3z{`Rh-yro8hv!~?WT`EX(AFK#v(*?5&s}W zn;P`))TvXOR?p*|I?>UW5QE|D^w<-kGG`%WNHxkpF`NM9@h(c}A|xXdEx?4R$_?k- zZOE6oUoR-8dEW|9+|s2WglM+fuUrKH=5ioJhfHu4GK`^mIVh&rJuj5zVz0!C5RyIH z!OE~s)8p_F!*T058fk7-6?x!c-@OM+5NdExm}NXw{t=>Sbsp52wh=`8Od?>brO#EE zYk6gn9r@^Rl#vCv2%=FCeXBAIM8CKm%MM<8b(75@p~lpp9`e%RFbBXptqk;tpPcUk z>{z}>uPv)ub*9!LC1kOp^y-fR(J!uscmJi=oAHzHPnDx)ql_@`oQS-*k6+W& zyzi2+>tN)xP`*`*h@HnTT*08u=8X$9Ie}=Ld2KV~q~f&p?WgIYWw|cQ+Sv>FvCt+e zBe^DYK#0VbCu1HN-?_$yBG4DJ89XB~2SW1VdACGBF1)pX9+ZT|40-`6jRSZdN;0(< zP(pRmrO&lWa4Q*!ZawyHx?!U8*xRW%E5VYQJ131o;pB3*W=9c3f zrN=Xqf>os|hXR>wymP^}pc8*rc?VTXmXt%nClh<(zl4T+-L@u)p=D8A&ArH5&!!-R zFwEV+g#YSv>GkW)jT+!TyiEZ>Cnli&Rqz#-ln5*Yl1DXX;VVRKWu4_Lg}?4 zycn!~R|?sl9Ocm2u?=qxDvPYBvxqtzAcQc?>dxYC4n27P`sN<|huE|_iiKYgI&&eN zN`<1jnmArIkyt*es_?JygleQQ%)}c?rQ)5(6_5psr_1E@g>&aqO+bpw%*wSBAw^&U zP`wuZsrj;9JN6%%=1?)6osW0y*m_mhXgCy(*4Ez9%w$DI;_l_H`eQ~lV{xgIViMHh zss?pPE7$PIf*cKo!?!P-PchqH5&pBGK@I(2llS^@ z?VlXYJb<7P-_TS7i$r5)O6><1JEuLro?g zpYWR42RRdst@y!QJ3c5)I8GBlgP)PtPw1uUI8A1gUN{u`4aPFpk z+RHY{TD8RsMFSQ(d|>a+Vq=QJIDr4}oz9)kbULdU)v3KT*3!@tOEYQ>VySf+dnziS z#1dO9u~j96u}h^v#V*04Ene8+o0+$$LkknfRZd|qI<<|>FC_s7-sFDC~z(oHcnDUETIY*2r z8CO$N*w<#ar)snULgHEDsd$zf%9w6RKoF!U5(40Ip-$~afnr2TL3}md`}yN(!qlp;rsn?raYys!&o6fB5u%D04_{VU1w`55$J{;@q-dD|ag}}W z%bN>1IWr-9<`hso7@L78Zj#(3m%TOjCqWP)AY|KKe17wArw36sWo#w_CdmKZqjHNE zX%Ju59_P>bCMzH#fNM2QjO-CYaU~L;}-mOQyk{kHkP@zL4wCgTlyA zZHDnnXS}`wA|eH|-~RO6ga~n6S^!F1J^i)*Ykq&fL7jAnu7Xh(WWFnA2@w$~nCM?!D0JL4JGqQC)(y)nO+p*Ara}-A$(3b_D(hV`GmzL)T5~Wk5s|EoSy}*6A7d8) zMs_x(zi9!$mgo;OL^9DbGr?oEDkO=3F$-e40m0DjXa!QaAA4_cF(C4AMj;Vcf=N^l z$)!c=R;gJV1f|vf{oH}o&T?D_xc6lDcgk}Ewv~1R$(ohZ5s3azV@ORg>&uQnnAKq@ zf@ARR_p*Rg#YDY;Cf<@ha98GdZIBJoBH_1;@={)~vUrDc%Db95@}bSi%g3Hd-*HhkmDl<)W6Rs&7omXlbF!xKtQoR3@sc~)+a@GJ zBP{}2-I ziYG7jrXbO@HiCkeTxCSEh?sH6%;<@#7>4Q)DqEqqy0Wm) zS6y8>ycqIe8h>~0Fpxr|J-mp-la&SvmT1i#vS6PFfl${>Ti4V9v&$L*fX1BGQsNG* zCg!qKgzR!*WzM)7pKtj5%52n0V-yiPngY(@P!8jeDkPp3+<=28Rt$OeaE)9prQg`Q zv)GuTFb?4VduQg(ooP+mX{S^dYN=L>4qC0M5>;!fYHg(UwJ5D3#1^3g;2-S-J>?u?_gR_ z2&xK0DNg*qMf@1PXe6gSMJ#raZ1xn;;5PkK|~)aKYqOAO8_n_FTZf1;=(mA{w!uZ zdu2&u!DLW?v{Xq0u-%DZa>iS5@!y*SAS_de$QKvKewgBLM(0=iPnKktm6h!C@7s5c zFMg~bp$8~HDZM2P!0zd~jc;EJ)j1wtbrd4**&WE+1`_wQH7fk;w{ z*NK4X9eZ}o{i1)ryXigqbPsd8bx3BxoJ(GWPK@-|7hzHOCc^yuGXT|ru0?%8g2*UY zyykvMNg;Zb7lKGyvFj!xV2+5qoPz$9m8tg{@Agg|IizS=j*$ty_$-*rmN0GIG&e#g zQTD8xYQuMe{G)v_V8~2-qe?mWvVED~3n(m^0AOe=h@>^>@nsdpa5(jpJA*Z+)8%p* zc?6DcexC?)jbEsxt(ar=*}X-7c~Or_X>9+y^35#+Q+Mp82zK%C!SG`jx2-(P>UduCn)$V{q= zul5hcR}S-Q^oWARslqtg>?jy7T!g@<4J}Or$w<|)tA56l#+PGK)6>&O7Ufv4g{+Wb zIdzh#Ejr|K?V|RjdqL%sCm%jMZ)|-2q_VOg%JiH#0R5s6wc#eqj|K&S$}g9!!U{xK zzKB{cv#6k8T-Q!XA70k`{nhyp!Q?kPMSB#b+t3y=4egSR!+KNttRk!@h}xsLA-QU` zUyN}O9j3f^B*sqQr{OgqIcQ8%%F4}F(4iL=1qzUofxID@G!tS-SRqoyz3Nec33WPj zA>M3LOS~SmMtCAfPBtbtLeI?&tr22!RZ*ri3h+4V7t^b3IA81Y*6>nRWYJTqRJ6kO zC*+%SNb=j=;S16#SD`#kbl-(ukelK`3ZKo-^G(z-Lz@VHE?rfCRK>MCQs71MqKp zf(9azgs-l4pwEL~b6s5v0V&ZslHn4(i&twoORck$kWA0pw{InZEXTq9l*PI0icdAz z5oB4-*M+N^R~&#Z5*|gCTi`A`d!S|Qa4eElgpcZX^L9Er;aJdI_HwkkjE1Hr6+xCJ zU;sv>3z`?*B4r6p&NK}zn)PTFNJLTRM%=n}xAFf^z|J0BR2YP1U?HV$-HdjEAA6Aa zLJ@#Foe?kvZHrbB+ikxMut}1H{)@AZm!kFf+YOz9+4CauZuVb!YXJU>cjv>03v`5l z0>I8s)F{qXb2lFtJM4(uUHIv*^nta-4F`1un@_}Jrgu1e*%g4RoBZj&&+OeBOeKgZ+WIE zBu!1lKj4o^0ZB@OGK}%GhdorxwFNI8z1&|r3`DOCTMr)0aTM=@J`Gq|IDZX{#T3pV zA;ecT?z12mQ`Q2oq(JSK1pn7-&QH zUqv|#_!kCyp9sLM*8(hTy)bHxtJncTLdSZbv2h53v8X407CBo)x2%!^QXmns6Vub{ z+A_ui;AuBTXpAh_u%Gco<>O1r3Qe9B$jbxilH>6G*&O~^lx}B`x@OM3H_8FIMMQ(> zNL6EQG=dS$;}-(DM_g4=kp?+&=n$V*;%O|;Se#t7E|Z$-L!!F+L~SWp#w9Oq*m9(4 zNnt}qJV;kkD&8-oi#EC_n9cOYnyT6|v%36tt`nx{g-QkgZJRM4gfXE@TC)026*tXVb8RhdB0nv{gNAEQG z{JzCopgf~f&j*JQ;h&8KT#l8qQtXhOm$H7Qs_5rbg#-Tm(Eo9#5=ngJyl8B?3e z8y45qouqzP{YcMmZT0#5{-I}#P?~k)rt@jgtywh)d*%Uf=OEh*xvd?J&v=VoGaNC; zDwf+34C9D?mRmb_GB`wyO*{|Tl$Ckw${R}ZGV44dh&~w5D>rxYIRBk7b-9I5+UklH zX%(XZomea6HsBoNJuM;NjzLNeL_6fRIST+E>r9$(Xpid2d)s;w)L@7b5G>PWS{I`_ z4j5brZ+S_c5##p^qE|#ecq__|HdP^^Dhf)ov_Ap6!6dQrEaYYi|C2wP3mpX*HW9Ll zKe6QQgb8bxO->DebJNA&T#&TXlM1i-oy=+ zTDYNQJgm=|Il!F*a3Tkp2-g0|Spz+7t+}2--qape7EV+W5BCGnFG2W^uElst0PD;S z${+n8X>V!u{uc#%_g1sMMZ;9Y>KB+!90wrI-T9jw#9@>32M+Rh26@^%$$dro&qY{Z zX8U7F*pkj8on~-+Q(9SY`st$$`zvevgKdV<8hA{%xgeXqlQT1?C-jK3_I;KFLf8;% zhGJ|~?8AV;Ks&I$Q~mPet4g|w35}>2C?KB-FkwZiC6r0}sGEuC+JcQBB)pUsTrVh~ z$qu0*n4o~HRA^D}G(9Kb!<0B(KnR&e^g-9sazIE}iL5O($5qw}P={@VUW2UvVS*+L zu)VqEum)}sNKg`zp)|7%goFvf!U5b!3)HdxwN@v}t7y6=3vij_W&pLVo^0uQzMTW3LIyvK@Y& z2tr5*m`Bj5WYCzGdnl8F6e<#{={bfFg_xs32n)PP=)jv})gOvV2qE(0 zX&wP#0yl;NjHKJ*X$BSv2Q)@TRXpQk$(17{(|QZiZN|Y^dMy0c@(@CZ0xX*B$0zE! z^qlpj1LP0rCY2C&MAHeh=ET^bB9VFpNT+R!KnNlFU^AgZwi_zq==zLwvQlt@5E2?f zKRe^`i0mRG z@Rh}>+Y`Wvw{F=Xo4jjMOUrv^$Lew%+Qn=&cNXCPIEJPq2O)%X8}GE>vxG6aT?pyC z_~FfV0dg61$W4&dLr*7a%> zJ*`cZs#P^>*RIFNp`jFKrNkZ;34(|{Vuqyl7HPadBw~aYY9~eP8N86#Z^U}#TAQG> z)w}EO^Wu5^|MF`&B` z5zUZULRRF|`uDG2A3Z-1`AfIA5(vqA2JKH|saShd$8$E2eCG7naoiv9Sb$!BxSye|3qF=tYiAI{fzO+qaJv;`cau zXh}vGXat*5aTTF?j?g`;rH}onu7eIuRH51Pl0w6Ey&vzOpPn9{NYl@+MR$> z1zIe^GHCz$AQKpq#p?|F)|J(}2xAcMhVybAi@x2E@ zJEqJkhaxsgsA!K)@zVtK4H`mLq?zX0F6(sPvL)x&nJS>Octesj!YTRVasU>iQYgVI zDE*^=ZP~df$Y)<(n4Ccd35AeN!>U0$4DD<9+_mXxBL83ON=RZHS{uY+zxC$LH48|J zDNB1W81Q?<<4_5GqOoLgUXna^?YYyF}K#vKcWV%O8A5=${`2z zCLY<*l|@QskDM?y3TnKz`F2$?$8h`**AIjjAd zv!`llzu%Ogs7qm;6W_Ht^9=q!X=8*(R#>jdU%<53Cq;JA0-YxeR1lR=2Av9DL2LX( zVgF$N1CNiSFl4Og1YnOUzxpHts+PmI_`?4ZfD7DbPMy`<4IKH3+v-A6#i2aN4*_^% zVPpXV2)lPv20BG;M-&5e9tnWesgj4(*ZxxuTF)0RSKj5aE%5n#E0K2$=3+>aJS@P9 zA;2uCQ>*k|s)H?U_?%kK|-L-1h=-ABRs$PUs z_Pp(^3PlCTI8S#7^S$`Q;p5Ds>{z3A?ONw*$UHI!@a%$dHfU2P7BV@au^#fuhR zeD$_3k3V{Uz=q@!cGL|9;sGxJOC%aHLls84@Xv}AMk)qO!0+^P05-}&t3sQhbrJMF8eWQfOFCAayzY+*p>|u{o3@V{#kxeCCK>Gps4c=x1iqJkd zRcPGh$hI{LL5K#G5TGJmYf}LJPQ)(;{qi(3j~G*HVUF{7;qn>~qeq{kM7>vpy2_eCd z^S7!)gYlR2g^)3oUdB$wE;a;Fy&@}i%$V`$-fSasC6Di)E8M@clxl9sSA|z?h zrb|)e%J9j^S2f3}q^y(t9}F!7{+>Q69*@TTUdgjrQ7P!ZH+nKMMlT28lT|@9VdC1c zrOQm;07a?Nhb}ls{_#-&{+3w`F<2e%4p=?W+<*6`LuW+B*lxsPu}(-!6?*so6OPCK zP`ArEfKk|dnaV?`i=5=2rZXwA_=P?swgn&rx&ttUBUG{YQTaLT-6zkSEQyp=7Vx7c zjX+Wiz{VbBkUiW`Bb0~EA(DqmZ=(nQGa)J&A*&JyA;B)uCe9?+$da}>O$!boWi@N! zM+UX*=v07Ko3>Y}+@}c$A)3b14%big_K1Kai+?qe3VH1`qw}LuvkDb=(X7M&#rovQ z)MJ!@Azv8iBqCbI3j%|WEFLR9F!u=}v}4)u4JTO-@R%PQ7`l8h(S}k+!zudJNz6 z3h(k$8T#yL0 z8-^GJA>n{X1d~iMr-?NZiR6_Uhgu@3h~Qw0C1g$x5=(3crKYd1|M%YabLp*@_nLqI zzm>FU*gzCxL;xf%hXp-#_UWB32k@%=UtsDp$H$Tz9T7J5N~Bw6Gm3F{K1f{Qg?98% z<%6ep9^AX6*a+^vEOZuIulCIqAR-OfzaLZ}DdmOAq)Ib-YTVPO_xAKrYM?~lCwJK# zEwo+TZ`Oc_G^CFcR3KN&OlZmQd1q}9_!HjSBp#bY0 z_#XpYfNcYuxrKe9TCwX~Unp+M){fRq zZ>G$rH4hFR8kcEv;>hZE%hlmO>zP0uJ3qO<+ z7y%+fvn3lrR7T@CG(_wF#|q!~UZ03n~3dC3Imgk#l732N|mygfY!R7R#r zxw?s=+DN2!2*@xlinFLCeCHB~ise|QpNw)i3^h1kc6YxyIT}F!crzDd%AK7aOO8{^HP1lty(j(HxIwGB>YZ?`mXLhXhx-ghPvo z6m;%QclYU?AXEfB$YWv+N@IC4k%(l{^7ZQvCxS?DJb;a?a-Q%{UovTJiJD2Kl zAYW&$xdy6pdE5>6<(tdUvcrbagCVkBgCvxk)RxU= z+a#31=z6)nPOj%L4k8j)WdNmQmry*ZdI-Mrc%co0#Xf)SZOuWHUR(B2b~TD*K@SW` zN2+S-($yd$GNw`SC=}p`RpT3P%nWUi&@;|yP=l`}yBekE>x?HnD9)fJH~yQYEnWlo zBMH_(ld4Q&rSvQ_y(l4R&`6NDQrQDgf@M-n0^o1b<$}xKEkAFD3d}1KUZ}uTWk-=3 zq;t}lD_b-d$m-toz7=Eu(RvRMtqVa5d>!rL*Es!) zWx=Yl*SyWn$mz74p3E2*>E4-VJ2dy6U$YK9;s@!Tx5)(n{@O-pz?wH7%6@hgua5`i zWowM*WH~LTBcq_6fH)gv1=DZ{R61uq&eGiK5GQc#J;%-Io_mrD-?*BzFy7a(b`fKy zMRO%{xkz1Fjz{G95GZB9-0(jl?+Y|{4^e=#ssjID-pbt;CA9R}>*uq)_%li1V*b{4 zkiMB3-1s3_12P0}a&^#MlgK6aj&13*K_P(!{qa}felQ$ssI$2_WWwLMw4YZI*tTb{ zpB-sM9=*iV#O?1d&B zdv>D1jXa#3sY>Nyvfy{DdN-12vkubfg0r+`A3e(Eq9_R)FGvM(|1AaV^ni#yvv+SV zGKO&+z`yg(`M_9)9gDFJv#lA79Kuo#L$lZmidI7!i5jQn$|T??hGRY~uU7;u;R+^Ua^pJECJr!5D^)XCm8f8s0451VYue?QjZLo?rg zSOg*(u#3tIHQKr~oK~};NGhL7ikru47P!jxhn67VUfL|eP?8~SBRbmKKr|4`#Jwm| zws@eS(JynuKvJ_!+QZ1^z~;4nRExtjG7mp?iJZ$G-vseZ*}9}D92VkdG_7sF)H?!1 zwJ}V>UJdk%U@E1LzT`D@A)HRD>bFm}c^X6(JdKJOR0nN%!r{;pLAnsF+P9@`Fo=xE zgd!_QSl(oeEpP|s+#XWZ!V(pP5iOi<1g8F}W`z%KAI0V~wQe;gFi@5;p~_!n$J6LR~}+33BIRa$x965E<6^?vow8?H#M7JvWffxszRu4fRux zB=Y&h@#Bf8yp5($t%uXEK?HdEf>tpqkP5C22a#cI>Dae%-=j5Rht7!prm>K$X7>l= z%o+ELvBdgLBx2~#s-Sf4<`!VOK${pRLu6!B){&+q-M#C&duKw=JZo3!p}vwT$=B0U z4|z2u5`Ed|ArJa`4uf&_tyjBb(cTYU`6J$}q~btE}&D3kS~JQM0s5NH4qQ3+fd-{x4XK$26| zKS)nOSrjXZyn@sr)xelbV?acu8-8^J$~J__9;9cU$cpLfp^;s+pAI0!(@~y#Z*9K^qn`{)w~)W+KvnGFIAY)?@^AjR0(Z zXhgxk@b<7}GZ7KV$>v1u__+WR5fN3N!n$E1Nw{RZEcV1_FfT^m?CkeSvT($vfDFlX zJr3!(dcMdzWxyatHG)VEuGDRiA=&mzxBy$?hZ6OuwjsS+Kw61O_`fAt`RhPGQ5-PJ z&|gJ?d`vDos?N8O(^vt)=Jit9OftSfbY=Ep7>s)bNB;g3#m%P_gE?hNJFS~QRc2Gr zp9xMr+u9q|(4uu%RJs)cLucyeyZ_B(+|`r zr~Flk(scgvfh!B^6#Rzc-n(0vYyk z7oIo%$D`}-9t7EVI+wqB|NiyzYqL-)3!Bl`lyzrrv*7JnT-i*Y3uUk55V zJ2T6SKbdst(pUEGEw-sTjsy7joYUKBJG%oN2Rc@&b+tR)T%8ctUF^aftZa!GBq%mA zBx+VRh7tvg$igL>fksUBA`1_oBPJ#iDq1m|Ng(*?|*#y#wYtU7+Mg=+1eb9CSt=*EC#cA4GI!--~djI zkG}E*0ESsgy!NmLlU7Yfx+kw+o9yp@Q@~=0bjp#UxMif*YnR2Pconi>6)}SqNdHll zW;7v#qR;mI{>NW$ou>B)Bw$x=49773#L?m5JoTShb}QdIoZ<+`Jp} zGLc`g#4J6}76@W4#(hi+MIMZ?pl>?zNAzUhQ(*KuVDVaz7JVOR6?s8ooE88uslKw| z`AE`?6o!%e_fy}<0?a&pI_6qc-l5sO9^A&)zg4S+6{)7pJNKyjlFjml7XD%>#WZdhFGYSZxQjuLTg)Mq)++_PB4)5+F!Z)IDrGirJ$O*v`x}FEzFw>=`0@W8u0c7Fl{~1<2tXNviVtXkjZm%0SJ7QT_F;Dm*c|SBC|a zEJqF)jF?N$KnQJkEzgaH9yvKW zZHJ5;4k+iugw)a@O+@O|AO5DexBYzP{OXDdA}{X5P5p=a4qw}3L$}j#%;|}d z;bdfkHbNBB>ODO_^&A7C9{%>~wZA7PUqF@&7mE*m1-Y3y%&)VYz7-3$PZ z00X%d?_35&S%o=|Z2+Q2dugH3k~70}10F123c^WA_oMAr9Po<5f{;% z0XgLN`T`;gp`%qB8Q}kLE68ks;Ede+lQ&m7yB!`oi!2oN>_9$(9$L##nVcQH3=bfUmZZ?_Ri|z;Y4C28sLyeOnpPZI$MUVtq_=8%)p^S>Kx_0amldASx}r70vlV4 z8!2@zq=Yp(fJ9-OjkI!j>fQ)`pmNph?XN71ZBimOBAr4W@qM*6+{U!HKoNncDb5QE zUJf&Ko4_0nuN{EXYeq`5CWhOPhW%n{J17-k4FJP4au0QNOT+O*)P+1UTQHZcfrh}; zJ*bPt1xFrt+&=XhG0%k}p0!#M0Dp7X2<6n%5SW@5i}b2|$3(9k z|6?F&4}=1QWGvB#TXY)AMVimO141xm22j)@)wS9Iz}f18a;ze9i&4BMgvu3DJBPHq zL7+6C?K|f?@zO}N4ccS+Vjn0n-M51UHIJ%}m6+jagMv5{a>?*oZ#h)Q)~1D0-n%d* zEYh)iEda_Lpk|dePfUkt1V#~L$3HYDJ}+@4NWiejCF|!$RajZQ^7BrbT$&Yh0f634 zUz1t7aL0+DL>ucVf~>D%kQIjBaupi0O@;57rB#i`ihE@V7?8rzZr54mtvuLZ(g})E z4KrOTLXp5V*6TqbVvu_t4{kB3@T_%@EG+^6Hs}+vL{?2^H>iTZ(i}2H0#Eap*9O2O z6j*@&;>XA})~?rd^_{K=cXO5B`d*-g!;)C0_9G{X)_|fYN=-Py0swB`aC2>?#W~o! zv}ABe36%BpgUB@_k95}TEP`A(l1@F#x0!G!n-jONfgqMd_w{k)1ovVwC@Q}UkJCI9 zB_nrBYscWmU3F3->Wfs59j&oqDOQ|UUtGvCNax~>63C^=4p>R4FfLxp;0}y<`^lMt zA{N1FMXo)y7C4~lD??iJN1Vr>Z3IQh$5P%|9le~|n=w3cxw@XEWrXv%|3w4j;y4WB zc2Yio(=Zz6JQf)Qo~I{`Undw2JlJ?cB}&04>8J<_T87?cvM57;iWgQDccmu{32 ziCAnTc^Z@=OBV(_FYE`oSj?fi;!0IzS z-yb})3=}0ZOG9Efo*0ReF#PFX_UxGdq|j=CYY3IW-DvrL7C2 zqM+zV1)U>0TTvh#BrM3F13@Pu2r4S920_v)*If}I#7r-OqM`_*x{B;T2Xo)n{CwYU z|KE)_-ubzA@AEy+|FI-uA+F!n${OfG>W*ELZ*E)YR1jaI_D^3hL*OC-=}yJN6Sq!O z333lF!c<{y{yl~w z76(oq?q@~^F|B^VRwUAxr7wg~oP}T5{Z5dM4Dt*z;~U%963)GKhEoe63S-@~UWlH3 zVg@=;X{He!Pf4IXizK{mJf6^MZ&- zXDnt6J5pOc45Sr>%ZMT{TJTL$zB?CyD?49dL=q9{jd|&Y4S{fA?a?#ranXpQKS(7@ zeyFIrI@|4nI-_QRh)50vD=*J}5D0(%9Nq)cM*k|1TBiJ9D3r4=idhCCN+ec^-|1P; zJpZ(E^79X$u8d(HqDHE6L8?`U?%i`A1QAhNHcH(@?AX)t;mN1V4>k-3X`&_%q}smw z4GkW)Koe2hHlBgZ`d$u)U$q2uaRD~S5E@o5&hVZ1>~2qac}|%WfqCgYKtvilT6=5^ zC5=f;1WvKuR{>SbV2(NeM_n&+B_C|s+iV+}AiN%#? z15&~tSGKH!meP_DFRq;hh*9r!2u6w$^vEKRI!<3ITIFSDyC92-M^7uDQ%1WPZLm3c z0F(Bt1G4h=6;A%}BrvTnw9{pCCgR1Kj93jF2#VgMH4vRB`xyLL_|8@CONJ!U7wpyV z+u%NhPW&acSU=nRNGb+pUm#HX`N3Qpv|}ih;igBwGdfao7cIJR<4(h(+^W)KhgIA^ zVqY;{s2CjhNtw7?nsGlJEtmaU){0^ieq$+|XaZ5^sNSA;U{`<@7;2xAGQ{`zaZ^)M z!`(Zfob3FfktqT{H0eu(`+88!@hu@ZO3JhF3un1k;0IYO=I+A%Tgk3qmkTJ^ISxea zGQglX92p0T?)S9Xlq7@Dxy9+DARGrnw8b#Q=XK$S0oh(2Dr#9PSSyIHq}r7L(7y)M zDY{&QWNOMlF)@q$l_in%@wo>j<171E_gJ34su{ZQ5st5v$`k=wnG=_>?u~4%VD;iR zVG*^aX}P3}d3RT=h*cUN!T)!$`O#U(rJiF*Bs;|)x}RO> zcjuH0Lu?0dFOWpiSI+}c8wYSEZN|Ik;POzaNSiTe_Av2H{<2)Q3ovS= zUfw~}%9VZh?%klT8YBwi^qF=siAgD5dM zoFJ0hkh1w10PKa!=2U@%V6JO!++2#thQ2=C6-0^2Dn`yDQOpL+AEcm_g>_3&80s3; z9l&X?Ug|fjoTz<91{aXPx^zP%dA>ZT;miPOXKHhEoe_~;egE=AcMwIv3?j`bV#W`2 zprln1cR39yaY7YWF-SYzH#ZJNWNEKYufLXtKk%IhmPKTyl_ZfDMMXkVWMpZ3(BdeTt+a0>7!mCY2xU7IL9|eGQ5Id; zLUm<3ZKMQ2dr-N|nZ^0fnfJMxn}K1NIsf{7Z$^B+g;IR(*dQL{xDhbvx5(20*dv@qeyPhBlhCW4m3!gD<)GHbH z*rr27a=ZmZ9+L;zL8L~Q1%8oSR9*dUDOYl8C`JIzUdXt&1V*cZ#u<{@gWJ_j#=!b8 zYJ|aI!EbFDAVlhPoRA4Wu;-mvR#H+}yvxLi`ySuu=ZLUEGB*B>VcI%n zHYHDrftJZVhjPC@WSfbXC7@2>s`?YKD z^G6OIJR(+GqpJr@<;OtOkc=;9w7yLe_deSNpzk~o1&2I#U};Fr|6&U6-pPc|)@_(L z>-vp>c2{(4xbDVZHrb>`ZTfOa^BqaLyuY4djCjEOAPOF-RcN)t>O3x9f=?6$n3Onu zZ2seP{Gj;<5s_Ms3E_I7AkrCG2AsWsLHSN68_5!hV{&B} z)Ub_s|0r95pBOfFhEO^m1d&d4NY&QWW+I)E@r%g?b)?j5x3dlK58Ic?2o%dOXp;nq zD-;TV)HtLF5Wd+a*%GqZ8g*cEl+a_#vcX$Zugtq~JskewG9yqf&(-Wn*YO1)^1IYz z^b%kI?o+tbi0|6Eqd=N{Op(`=!*+OUcn0kAdW&BP95xy1Ob-5%*{I;Vv|JGRAf_cC zN%+SoLE;Ge7agzxNGo3mqEIBkTdv_Y0Bw7uLT5TZJO?5@hg8!}G3NiFAIU3t5 z=UI6;h)9i18TigJsISfv3EMvx;{uj5U50OXh8*gYjpI-UlQ6%FoRXrwZ$FeKKuG$n z@*w{RGa^XL*>?OC9cM@2*zIU)!^DUrkrUu6S%8B+3a0cF2uyM;EvbH6U0t$E$Vq%m z5{Me&vLQ%%cEE3n9RXunu>w>VrCl@{B}?!^!jLeKE;vPA#C0h>QGTMZq;Sj8lJZ!H zr*%At#1!X3Q*hk+!pnhmYIW<91r0N{wK~(+TcK7;aVE$sEt*3pG9a}U>@)oloi=b= zioLMZ09TrjOJE{F*?XdCWNe1FIvy5dFF7!!3ARIv8+)(0qGEnxSq}b{mWKwIa<;e^ za_`zJ+wb4+3c(mw4}qxC6Vu^#vj~_-od^xwTQucrzF7dIKwH0m{kN!`3ZTfc5%uep zu&eg`$=UnHI`OyuIjEo0y70xTi;UUz#?YFYnvX3Z7=y5TND>qUd8|PqQpqmtpE{%{ zM$~WY&552ii)xwpDtWz2XzvPbIlw@ zyb?KJ2B)S(M4?V{Dk+P~W=~&~0Cf^VuQ6|nj_?a*lAtXmh={1^7_9)hEVsi6kA-MR zY;M8a*6;&a0hG}D`bhU|BGzfw$+eSzKoW=D0;>$wgw2aJnc#m}cb~H95mCMJ+zx2N zsn<(D6m*jO=am3$aFwJ9b7J5VQ;ZpqPUph^A}7pg1|q7PseHdy3KLzcKoopJT~wE{ zDyymry22NcyGH|=yIUgwWC;PHu*(FgVivFutdzrGR3goasjT{DZ6tgkO)JQZ*nLr? zd4&fInr{XZy1KMS5R93^3P2+AqpYf`%F3$Bc=)1K!TyV{1&NZU5YVC-g5cZ}6Nu<5 zdv^}vL=?sW{6AMFV|F**cf1dj^JoT&0569PF4}`WZjH2@6G&w)ikN{nD2e_zW06Pn4}W{cxMC6?D`8O|Kyy+Q(Cg=}s+s@}R<3ZGj*^>Z~qdH?Cl2KRw#lYpsXhJw= zR||!`@f34lYRv3q049gcVgM#dO^CX>4K*6A=j^ zvj@Qx+8}RputfGgXtbuwGSGp@Csel8`-^B40TWMJ0JKah0$FKsX25|oQQkF6L8gU4 z^u?ZhrX4tv--#dysUW{-d3OmyI+NxLmdN{gj}n+turtxlYGDk5AjWb*|IoGzSEZzB z0C2yXb5x0FBuchjDcXGqgo#W|=>G|KcZUJ!v$@YBq7l$b)tYVFm98*6G4~AI6Q0EY zObsY)3PvgM@+FU@iD;y>y;a+`tA%WL>Il4$zHGuZ)*PMzQv>OtnHa4{y^w~%y94rT z9Si?c&{(USg}9+|wOYAZDD=&Zm;2#~-W?j;5}5<~MqS1WNPlv5D2*VvH(-GzXBhB3 z!+^d^Lw$X6j)MxtOXu75WVQ>Qv7SGHTUr=^zl*-x4*H#%2u3Mpx|b)_B!?y0ov1G= zYc_G7o@I6PxLbuR$N7=XVsSIN3&i6|&S8+NT580rbZr&JwnJsA}q(RO^ChdLO5 ziHHI#nJVN{N8o4ivWfpCtf8L6JC0t5TPCgr5z*h7yu>Y*-S02&y8>aE8!R--oP_`8 z-hhU`QxecOt8mF824G*gG!;b7(t^>G$P3CSexUZ3Q>lH+A+AzxDpYZc;T{bcs7s#> z7bqH}LP&R`ozB34tB5bEl6&Sf(Hsw5}XmvvCFMem&Rr z>P1$F52Hy(Vol#PnKrrh^!JtGl0&1#3p zww$jF+I`FffLQGm>a+HL*t%^Ik9dfPq@ajrRP4nXHXhOd;IaO3=l9HC76;Tc#j_Ge6zn`p6j zSmZH;qjoU){XzJ43`BmU7~dZiU^&}f(@%UKfIDwMIA#ZHuzqB5HWc}qf?;L^zv9aG z5B`_GyBK+V+=_^{F=$=OVm10BG<{PMCGq^mUzC&})aITA5sYEN=$6nR3q5P8 zMcT9c@F4IewhKfcZ9iiMuxFW2P0SJlq_iTCTG|vL#EPl{xe%IW(%wI;FQ27@5CD=9 zmU!?cp*aM=&}U)ZZhcp`+X5Se(d<+z%w?OA>;eh5qPHBr5)3J(y{lg~azZi);g(s9 z*MNh!?P@y+skay*s$HsQN^GdTQUnp4r$=eNztUGKMneDF+Uoc3DgPxQ zk=Oww>I{W%4y_UBo-A4#%XY6-qk>XY}Z?uDH_Y^Jlpi^4Dq}EPGnn&dWQ>J~jj)^(0Zczys5v zKp-&R3sOJ&?Bxxpkk1Kb%UO3ZFU#k9@xq^fi2nerJ2D3%BskBU#RpKc)J?FKV!*wDAkD3^_^l(Q$YyVOlPko z!Nz}Xk20rZN0N}~!Ql6RZaX<-n ztnYNKA53FJSnA5~uajJ5zy_{A=RH{dXQFmS5mG92T$bR@V zGur`Wq|^6iaCKK01sl&o{c4XLvCxPnW#%p|%&)w3X%|S)*z{EVN8BV++pUetXmb=% zg+Wz;KBzN2*1Wrsl3D&P(*uR#&dr=R8AQDpelSqOcd$}d`9D?U6?6v)TIz!m{NL5S zC>jY;2SyV}RG81sX^c9PC7bu=_2<_Pc7;+SpX_aJ1yL`V;TuK`rorp~`BPR79boFi zv_2XCmudm@Jof=`hs|mWqAre3*Kgct4aG*@w?j|cv{cO0m;nG&d%c+03gw~8oZ?DNLnTS=$fk! z?omyXkT8-nyx#1Tr#D;3h$y`oSX0nI%(a#>-^Ys9i2!sB@dJ(E431g+*i`hS1cZ?A zvSlAEe;VO2CK7C(E$+o$10u;V%8syN3;^2j{l7V3svgK~*I0)?COfs>+D>Xqrs0Bw zgdKw?rMwp+O1F4jkK)gz%i?Xd4O1Ezf7*{&+m*LGpNchEY{k)ry z=N}3)jO+rglKW_GTa?(pDvch)kyDlAze+ zh@MSZ&e+nL4oDyW3`>HP(4id&i5SD-7e061auAhD=DM(_ zK@Q-U6~Q@tQC6CDo0}qRWa#ccTdzk5Fjq6cWj9!124LZ|4=c92bJ5TP-KK7GI-Ri~ zBywyupVrWew}_J@38BEoOakGFgQ0gEf@99HK_OiegbT9)(?=&GB;>7eXt>qo0-$#_ z1(&|CcV{s!g;5;9|Mzyg?X=TQTV-@QHCh@>ZAEpgcPu5uh@~R-C1x-YB$f~&u`jVz zya>VrqGCxz;)#TakW@lFG2zh*5}qZ@*diK6-P?QGdwvg{&dbbX(tFQ$?)koRLi2_X zKX88Uqya}sm1?cRlb6pBt|!L{Cn&M+d-x^6sFCvKbx#x(6#)tFs(Jm*1t zj~j$l9ql@C_!L6V0~ywjJI`G0ZcA@~q2o8^&&gOEt)ZECTdyB$us!MDU z=r$G*taMtS^jWfobnh@$CZbVvI5No&-DrN*`gkE!)_v!b20AwsMw__Q`}L~`#TYy% zu;(>|fcoT5(t>@fX$u(T3+AK74r4 z)^~F2K>^@r#H_5z86acEY9ER~JbhX~VY=0Uu@Yr5qi~0B9ezP|cZSlc5|an7n%p{X ze?)Z#|X3SefZM28FAA^5PiuK`;UswXnJQeBaiY zP=-MFWDCv$-`YQ!Iy z=20z zA(H;2QXSP)KCC=lLN&G!3Y2{BM`%8Dr*>k0C_v2BFLuEORO>C7e?J>TcnG>OiB4`WS%sDNEnFIoN*kGpoN=usB8Ip z(_dzgeB<;&NmEuOEYP2tcdvaYKARr@*98g;)m!jo`qrf*zprGy}L(mfe9acZnA^;D)vVrq%##mmm4}dLWK-vYjk>&%DSa}Wta-TkJ zM&}qzP>_*+4OmHn5gm++YN}Cm8$Q0}ZtR_-!}4!QtK)++3W&??FHLB1K>%RwNpHO# z^P((yXrH}jonsX62V>t{(bsy1>BX$oVE<3P;$Eu(5DWuWe)^~#`;>YUG&1n0<;U9*$V=cOt&9=1=rxG| zY;linYHCTPQtbhF*wtB?>FK7(Xd>CU#h)D9_tE?JZEf!#4PF+YG`Tfi2Y5UXeG-`J zM2N`4yy`qOGvcK4`?~{xAmBHyU0}4WxJWJEU`1lCA#v-LDl4rmdd84Eri)o z`2~@*u6K`QG8Xk$gmc%yo=?8cMTC8MCEXC2^4V|Am06CCx4LuOf!hX6cJ ze0^69O@z*^Gy)Y9PF@swXYRj{f|SZhjA_b{mI1V^1~#W@4r7QN0VPtp4oJHq*8m{M zL0BWrgPyOdN4ry}pb7iAlXi4p+=FB7zwyrL3dUGFOC$^cEsFq1H6$Z&EwN5mmX;ub z)25jLX*I0_s=6ScdSQRyRO`bRlM@YzF=M72bV3uh2@@txSWIMVe(Ctk-o3pv8OCt{ z|GuZ4t(E0mYn^Nz=gN#yr$se8P;|1hVTp9WMn~v?AVGyxb~Gf2iiGMSh#(qx6~uJu zpe<_s<{EZu9 zKosM0L4Lf`N|(uqoHQZ^wd7#{m&4!}F5d>m5OA+h2zGw z)khokfYT#FVUkgAal1ZqYsrR zVKJi(SOe_&U`^hl&F|kVav~*87t%&z@#tbW>t5s_Jq}byZvc`NN|P?NeOr9p?)h!i zP0t%vtgdtzN2~2n)nFOTAxZj*l$+EzS?liZn@)T;nyCvIBUwm=u&g(Y;b29h9c&Sn z@A;M;w&)mABT7h{ho7@#1vbsrB2C8hk3%MiT8`%c;AB%%W98fjYm88toX6X1w?Eb* zaS{(e1OQ%4X~eT(3}iE7O#uL&hiOeVY=EbJx&o5r%nU!jwM;$WMos&c9rk8m0bcav zNz1~Sc}(P%JnYFqmJoTQhpD#^nZz|dJAbG3(v7C;P#4pSGoSn3-g}J1@f^VX`~}e) znQui+m0?y%MHWPLOzzuC_qwv3j^U4xXX;0wH=6~kXZ^M}o9{bEO`ST`tV5EnRqBy0 zI<=jF0uUmTkU@OObsqCubM zBX|*jC_+xfQEzpB8KkVpGBanzyCfuCmTkcFhnT$#$#b4OaOXpJbF<@UZz+SF=UKr$ z37I450AN=u253gBY7e~bMQ!cj{TgHj#~~G>5wY+%u%`24qz1edsgRf|o)PkYnEph> zoZ++L4rY5X;|8Vu{vaoNkD=`Jv=oM z01+s^j9577m^TpUtwAC#6k;fg8z~Z(tFX32$iIwg(E`gB1G$uJ4XkhctgCYM7p1d}b_5$Wm-bhUvbCHBnw+`D&gbC8$N zIs-&8f&if6&Lkre=BTd@78M2Cj+P=O4w^ZY$BI@)kMbgiIJJjDKBU_u--_KJg#4zF z03dfF0BH3{5?>Pu%#C!;q7x>$EV+Akrxx-uv{IE%X`U)1%<4qpKx1=rBys>TxlXQG z1vth0{xZa^E);4<`f(an)iwx;&)B?_%8V63uitm0W>%mKL>{^8?=FGN3Yr8Eh4CB` zB?{n5qu%C7wAmB;#bQYb291eKLA*3Rp8;{9q6HzTGLJ? ze=Ue|I1vCuD~BXVMe{;k&A}?f!s$8uq%-r7i9PTNaj5fw5HbYEBS|*e^!_(ys4IaZ z(>U?pQKni0MkX~yBXhf}Js4`*M5Pakm!Gu(*TUBjhez!ogbZS2ARl3b#SEf2eLjXa z^EgIk>#7eH&6?A8z==O?I0&WrLRW?2aG}B1ju=d3YA+Q_8y{1n1tH{blp>l5mbDn3 zc|1mB?C-r<<#N`|YOczBJCyOm#}#w@ufw4_#Gqp;2tN~Mf9hd)R39OPs7m6E6ILsB z_nveCfT{crk0B%|&GseW?+Axpfy8pC?=!>0>Ior){F7vzQm@5#!UP7+E%@Dmj=<~l zATf=-xSfi2gb>08s}qSbE!B+JKPhrh+=&iFHP_Y#t2G(1MaU%4Vd zVeO%h9e#hYrRgfL@Y&twoam_8MRW%{12dMGRZgU?nRo?9QLD@KH5!j`S{Tvi2h z?G6y8jUNStX^ns}R16=5Y!H$Oq7_69gxPe5f(%1*?izH|T|^ROUj;%4At`BJ4nh)j z;aollA%qa3Fnfr$z=RNzMMhB}2{AW~L@2_g&>%~e5K1vMCOjC~MdZa&c4e3ch0YjjXSj83cj}g?o8pBB4@xLy z>6#fcXZ?O&=i$_u&iVh(|F;pT#q`-G{3pj;59k-BxR@9BKq6+huUmA*tL$BYJ;aHK zRKsM#|2lB|0O(iIoS3peO2=~9``NW1A|lO_%}VvoK;)(avc z(u+37kATW6k&mJ{ZF3LI@Me=BBBCEmHfUVc;x?di*^>Z(NG^inr0Q${LOCBudIqK; z68%-bevpy<`V%+g)Q)Aor8C+gwWOHx0?Aww_Dh!vzkIit3ji#WPJ^Up(Mj=F$2m(4 zAS%MNGmueDL&E~d$gpTPs8lnTKx)R6D5U(g+4-TEc-4$Tb#9OEszN4^jchl}crO-)w}`s#5u^kjV(5n6yIA4ERHD2b9UZ2YN8&X;br3 z5UGZJ_bJH9v}TbJRH8*oAiY5Y1VPATKLnv`o#RpbZirG(dc#rZfphiK*{t~|DqIa8 zn4iojlA{XJa}CI5GD2n)bj=|kp^6EVH!b zU|DYiE~W9E*^bh&z=w#ms(Mz-5|t#Rg~T9?(J0Db$r`j`L31?LafNLCQCeIS$VwYB?(ZXCoeQB+Bu>DMl+r#qbLxw>HePH5HUIecAF zx%l%rK@eh9kj3CbwRKw`J{$z1%IPq>`TeYGN^OU(JvWcy%^hf!X+tl-#zmOQAT2&0 za8IbqCLxE!RsY_BSLZz(45G^EwWy`3dG>aYG}gbp@}>(k>*6_J&TtU@w@A{3wYjdz zoDb5Ap7)`>-?fnIFIAN3%&u9pm#Uj zfwn=6ih!t+Y<)S5N;>N&zkB!Q_9e7Rt)1`e9vo;q`Emw`$|D$u3=H-401(~-Lmw}Q zNE@t^pS^qc?DN4eTH{pyc%Q#Aue)`t@#9Igw1zBF&5Zy^V(y-ho^jKN9~bWoV2=w# zR3OJlMZf=z=9_QZ-nnBzYh0b7PM*WBAAMQ|O$xkkTBFj95f!J}iSOJl02VI5Lram^R6~naHZ?qPgS5|X#t&9S@8yXU#{i>C;StoEJMmAU zZcwL=jUOL9-Y@|g)bm9HgWLLIvx0~;#bCfcc}GK)EEiukJ~}*gYDZ{LbwH!F0*P1{ z^cO~j@8yY8D2PFEUtAm(I}#%1TlmNLPYGH&P}k5|Mj%rPxgB0 zmbSm=|NJge-mHoRs~Lew73Ln0iDR&c!$Bvm)d4j-K)%e?UUy&J_K zQi1c388Y#U_y}yU0vKNn`VE~eN1rqMt%3S-^na^)wrl`iPz;5+nB$^m8v~HZkh_JI zVIkX2EnXpCHow#VRi8yrU8lV{dcB}|vnsZZG(uU$Wo4XpOIfE*K_-?fcj6DkyxTM6 zMzL_mXQGZn$wTfnV?e6#c%ZOOWo6ObAVT0y0btQXdP5r$w`PLWQ}vPoSR78RmY9>& z>}AntbUY}}6-)xQr#j;7Mgt_*C7x>N2~v{@M5Hx4XGhC+g7RI*jT_I7sP~_`7Qi3$ znuLEer0&YNx+)M6(T_Z3yEQ&-m=xg*rcw=wQ~-a{uNVGJ`0`Xe!lyt)qztzxDHkKl zBk7X@e|^F){cjyO!VbVOS;SUgYOPA%aJ03laKN!^9jFC{>t{fUFfY7$b9Ih15K^8fOiV3IgdwTUz3up{qaVNUa3g$9Fg;q; z_sNso=+=^z`IT13cjg@H>gzW~f=E4j1KK7WH=?Sp01~p=@y)o7_}Q5X{I_0nnL$zA z@TR9t+d(a|vlLw^uEVo1M%CJRKwmzzdupRc(3P^x{R+ z{rjtWpf&Wu72{ct@s@>19fr~c4 z*Q~h&B2t6nGTXaoB|k@4BTMYXQ4gb|d^dH=_BkAPTtj6e25dDSD z2*m~c_@c{*fxXSpF1-caS3+u&9&N8(1tQ8lPVZ)4=3O$GY!1NZJs|oE=L#E?*8c7g zG^_Hz9oQZk=bW#H)M{@(t%M46+y;?X470>*-w|A|(vUBc@zvBsl2;oWlbMj$2BJSQ zZk!6m1+NT+zG~Rr2mPUaot%)EX-m_GN~mDb0&R6BlDyoZIUpsuH!s}0+&jL5-M%~h zE^@v)8;m!5dF-V>3*WIrX?l=9&*@-@5j`~97Ao`O)ssu`#awU~|JAF9*-RW2278h35*1nig zd;ctmWMw*N&DQG22t8jL-!FP>wm6sDCiliT|+Z zgob;UTI9Ih4OZR;libQPv0|4ulv&MOu;O;cVml$|hkWiBko<}cojvB*-%!`B%cg5X zlsggy;)%;tq3ic*9+2c_%Hj5Y*SP1A%lPz_qw`u>mf0BdAV2v`$%Tq%{A5MBgw34#$PqK zXBR_Ex{7%qMO2344fTo3L(!7;PDsHtZg8*=fO&ElGPtk_`N(5kMN6TO3}FqBZxdt4#D3I;(EaxGz@4gJJ6JN>SC zAaN$NyjaW60F>2_D_>-@?V)zNRzI?L@2*XSVHm)llbrT6cdJbzO^g?c#cEKRg3v)F z4iU6k!O#xDs#PfpMO4tiMMTlT7AGAXT)YjUgH|gzh>b}KVhJc>6aotBqT*j*QZH?X zmNe-}zVDppH)KDMbNRmSeV;dyiUA`N0q9Q)I5EY!%^35chnqkoAnU;U_ix|6`gHY1 zS6A0@u7b&|S~`TSM)#+N0H`BrD|Dw|hR9|Z!RRdziAUL0NMSm7=hdfc-j>z@#xW5I zN7*)nB1>BY)uwJX#1i=YInFgA@zf1;ooua#_v%{)F%gN$5m7NobE4|}t6>1Pcl{s| z&8iCnZWL_#bWi5Y8Y0q(U)!P3=Y2f&%wx5X~TcVMu8G#6%{OeBF;(Xh)^LMv~kj zMx>cqgBt}a^N&GfH2ul3m#GM573B+}?Q{^cMTD zAe8n_{1IsLfXE!wH9-YcX6enw4}*y4A0?5{P!JdofQaQ(XtyvL`2dV+=wc&pfu~!sh4dwl%j7x3#EyOSk_@8ZR~&tX(bJPwI;u1AsmNKVxG04_Op6rAmL zOtQ5z=$Xh=>bnPn3ToiyA|80-8^jg&ECDeG#SQm0RO(5@1{1_ny!+6rG@(RtAMHQHgXi1iL9J^hW5Q7bRpgsvALsqB7_}Cy1cB$`RXO;0Rh2)S|+o z?o&Ew2W#)#YtQrU`}qfUF?gTn`5nmsb+MTs!&N=}_=qFk%%`*zWH7r#wW~z>Se$&@ z8qcJS4CS!myMl6d6B3cs)V9`YjNlBd zfVzI23ernWJ-r1oQh|zLRw36~5D{gnta-qS5eh=RhtDVcApLq$l^`ObyrdkcfKGcZ zEXPQ_iEyL=lm$h&F*A-13{jZZCn7SK+T8)29EIf$jL`Y%(`Avj1qfkgjT{Rt9W5Og zw7&y#Dh@CgLPWB#TJQ&T81(3@{-GrTnNADO7_YTVKupu zb|1!S+Ca;|ht-gj>XYT7Lo}pxQ*15BG)g8QW4p?bnM#kc5~J!2pK91Az-BPD1bHq8 z2e9+@>nE>Xw(%Gv8V^cPGv#-yIH<|Ft=a0GT!^gsV$luAlr6I#vO5~@Z7#*AycYqt z0A*O-T0XE`CUuP+Jke-e?TtT$5WdI4T#y4kc?tOnUCJQRQ4??!G}1N+}D z#^_ddLI^$YS%5QEB?U_#AG@%7{t@m#A);&*XsJ}KjLGdu_33nz9a-}A_eY=iAlDk- z-E(17NQ?bvk?5siT@5Rfy9=F>C}vQ^n1jXuALTnqYKE{x7C#!Y8} zG?m6eD_F7_L`0;MbMOTmZ$$1W7-GR++4Cd!>X$L4kp;Uci$V-iA?G!phzzhZ9*>Ig z9yK3L1JTdg4ggqw1w>-81ze!V907QbBe1lCPWG0?uCt&k0nguc?W#bj-*K+4W1&HYXDGIFRG-R_Y zN+gz@3MbC9?8c;&<5!?tMeEC#w?Skqt_l4MPi-_>%apg7xf}dDx+393^V{b%D0C4^#A|e_nGreWNqNp82Ic8-wSt6p}jCufiS1oc* z7{Qt@>Sj??;t&y0R;=?N=ZY53T{Ry>L`3vU=}P2W@sY)+p9~#2W?>OhW%IbL$dCqE zWv$bJh=?dl1TAuIXw}2#RTGy!pQA^L>~CT*p9SeMIRI3+kxeFFxE7gfZU(7{i3yHG zB%x)`-UWlfU4mAF6q&kXp-Aku4r!|QnUS}%9@$hJ3b!M3Z+sy2C_T>8Zz7UT{)EoX zU~t}Wr0!lQ68iFMLz>Ke9_$SnkyW;U8JV+MLF!TFZ7_g{NGj7hAH56iC_w7kzD~fg zkOS!o#P%iFQ(o@$N(s*j0{Wp@=PCygkyLg)7(Hb|a2Z566OKeOiTK*z$0O|JC38ZB zQug;*2Z1H4Z(yl5!Qde|467gt}E=wZb*B3j( zXfF+bJV)`Nw^ujiBbkb*s}g{DLCa;f9UzjBQp7C85$qn;(M=`ZF$ zoq()cb@Sw0%lR)8aF=Ucxw;pGYEw9Krt11O zw};z6^qoo7LBHl$B<9m1b#0AWxSJu)e{?@UC>ShJ9r2Pc8{j5a)OEZBL<;7xL0YQ* zaB4(t{&}T=Y4bm950=Xuv-)=zW3^ipCtc4Kc+S8T=3-)-u+Z4YC zE-V6(REiIB{AEg=SEWS|F#*3ZL4@YS!2l#Oqbd&&igd`K(qd#vYjKzw8tVczCWv9_ z*#e-jQt>-r)7p)!d`*(6j^cxB+!j}K8-B`T zf{JAF4alV-#ZZUgsO?tEVnf+XJgFqbGkZTZRet+ZxpLNJ_Nb!&oCboKAz%40Fq})& zuYy_8XlrHJ_!fUtQ|ko~DFV|>WI|w6jVPJQJsZkP7R>7T+M&6ptEY85Ulnm28&%!m zhKPvLR5@!+Q8N`;-{;EDx&80+&f}R(HglA7k&IEriz^@+%gK@HD5SxGBBC)g-ixE85&;y<%X`FRWy##8w<8sa zJ<4V~b&PWI0;P31*`!_|o!?-Qc)YM9Up)_u$ST|&$G0R^01J+1Gf9xeX`E9vL}@jhpffViXs^isDnX44MoJ6PDJ_gw6<~uwi3OIlc30m z_!1cOq6bA2M0ys8C@)I74P+tVeY^%s<5f{p-LSoP;p(L`T^PT%lPDVZqT9S}OhiPo znN(fZFu$*QcHFO`Owuh(dLgnYhZ97Uze!anr;rO~a>RIKMpPWihM`jt5K-Rz(;<=e zeICd|;}tXO(8LSS&<+g@q(MY^bJsv3ic}FYl~TQ2SzPxQ@mAnqo4_rUtd)@o9F-tJ z)zpEkqI;Mj&UP~8^fsBQWmF~#XWI*_Y8A*T5)V`u!{O;=n;a!x$BEqddZ!_Ck8Dvp+{pC@@iU8jIc}6SwHq_a>>%_eJ0i0*EF7C^MqShq}Ur z02-}EMpfo0&JyD7LEn1|)nDs4T5XmFZAolLx*)$boFVP4P+5|eWe?G8vLeEHO=%OMzaX%c)e&BQ~8L~k6CmEN@mWGY{8l`k%E z=V47BlUZ!UK`2J?{B^tnHdg-q}p!&v6J#UGDC8>8o0~(SNHU^Fql_vcBH?&f*7o(jd42wXfU_yJ>V_o? z7p_|MqwfgFZuG5NcW688+R98sG`7km^WMDbwa2jJX&c=z#QmGSI|*$f3gZC&pUEVX ztx3~X8;y<8S}n$XLELb`y+RcaiWYZNkh)M8RBFKuQ4mE%Djq~Z5EKy+#r9%xZ53}; zP;=;^hzd2hpf~G=B3atBnY=go|L%b>hxz7x?^}w3v-h;UZktpLl8Tbof5xJ6c*<=+ zPLHfgKoe0G@r55Y%28)}>(u~sUUA!l#=)Z|1bsShH)Nsa<^Y~@Aa5D~yT^q286u)~ z6%QZDQPS9VqYa(sZ40TcgTYWRIFQ9ylF;n{rmqFiBM(H>0q&*S&E3ypPPXBtjb21GOT~LQ^ylQAatB z@2+v9+bBy`&F|9h$K2#vjUTK?C{zghN)xsL|53386p!V~IV>7kd)f_>pT)%A(PX#< zt2h*^J2(|2pcZPt&_c*UQP4RRX1?I=qF&2yL~BPj&HLbBn%)H5tXQL%l%6T^lAcI z>mn^*ztu1A1<5TK1mvHz!T^2yfk-A}H!}cdOi5NpAomm#@0sYj9Zl7d<}dY&AiMnY zCr@t6g8{Tn<3J=8e{VsPLq#s6LXqgLUS{G7tK_^PP&`A{Z*8h;ZEmituL(-M+gh2n z;moJcS3MRL>8FYDF6+UKL?pe2fhk=a+2pyOR>x;`0Cp9C;?QO^ja*jU+8k;3M(!ax zx#iEFJ~?w}Ll%`GS>zZXOO!xEnR~R3v``jag8(dZvpN7%0?xYYEs=N4(P-to?UGjt zD0%t$9?dGo;gpCvq~TH6kMvMit$+Y@24ITKS>5_Aa=JCLd)bj(uHW7Pr~&R2csaNuZVWY#bc5gD!_Ja~eN)C_PT837il>7{IhrP%CtK${mi0ZIp( z2)DGV2!DbowuVCcY&TMqt0S4b%ol4h08>JjTZ%zxV7n5nLS{Mp!Lpdu(j+XWHc7Z6isyA6Zsm0{RY+k~V z`a~Jvy)bL;%$1KG+z*$|owWBTU$YcT?;7^*m{-ppq6`j6iEUjLb#{}v*j>I6CF2J_ z4$mqJP8{LO{B<;mNXvYoAW>|&H+g<1sSRulf`~{$9y^F6rkDCaL_|aevyA8EZ+cbb zgJhwv+35ulks&k&;Pe{%@hzXQG`2i@wx4ZRva?8BS4Qcl2(;Txox&cZF0;0d+G+ILx#j#b+%MXuDeh`#e+O4rus8 z?agOs68h++ei$g{c3)68bA*Qrbi^UyXd!W?UMPMs)*?!$DCEL#&aogOK{&$qOF+_5 z>_|VmHxLLlP8b>}a>8(`hW{x=48W-=Sn0&?;rm;;Y8p0^8EhHo|Br4Y8B4STU#9o36iG+xViwLoV zqr(`ZaY2ZLh?5{8ad5YV2-9KO_oi?8eoj3#Y1+Qu@4esh{|{?!^@Z9*SGXk`d$24V zam(m+&5Q6CH(T~A6v#}(cLRq24gr7i8vZCPB294yBaujGa;&`+%`{~ugY;zXtvd7y z*Hj5Lar?E5Kd}d^V!mDD@y(hbHuuF}Mzswarkz>?k!sEI{~E%*~}fGg+PbqE03CU04TzYWUQ%lcbYYwIhbrUr9tnkwWU(>N~H+5VuT zJvNo=Z>XGs5^BOz2U3z}*KPs!ak*;)M1vH3>kjYehg!0|{h+_Bg)~EO&y2O-zn2{g zqA~&+T7^Z`kat}|U{7HzV33ZFg)d(o6H!CcKfPz|oT_l7sr^BFECix5oXqi!Vn%FP zCbtzo2>QPbKKA70Z98h|&`l^oaO(fdph`5}i>FHWxD1QRvas-~d!k)(4?KSSM6{_j zeZjl`_{z!QL_q&NR}((IGsfynU)~8aAzN-w5RLaTtO1i2d3j@?067v4hvzh|Jh8Np z&a^h=PR$Aj2fGZASJ|7JjZq&Fjqx$4rv_#k0r^tv7!YZWw1j($6=3(+Bs+l7M^6>f zt*xoGARKa^R&N^!8Oqd1hxQh%;Nbg)f?4N$I31JByNm=Of9Sc zlt630orveZG5ggSn8bwhr$3)}Kq-Cu2~dH>B?4I4_WgB`i|?u=uemV-n=YkJ7|M2vcbx_90vu9U9HTjA7LFQGpN?x-Rfj#x0e+ospO@lPU z9S|GP6(defHec>{K$NWLl6BN}^u(0AXZt`cLS8#%3epKdKo!IdcTCY?!~jfG8_iB! zo{lm+E2g6-gem=?8poFHpl;MJUJg={b;aYpFo9y60hp*31fbrFa%>t}Ipu2ubwjxQ z^5b-nk}Mi~UZs*`yoIy8dS|u59Bg9%z#RWfEeSM&y0QJylaE(HT^hPTM5Sy)HI#;` zA{kF}v_S8U6k!h5005C2$a~vaxvZ0|%8gYy-=SL=^}| z$AE~aavR>&fk**lKfBB?Q%IJSsF2Ar(^bija5)@kk_sU}a%pBbrcA&mb(MR$?J6>_jajjOyrg z=ALu^zs1aY9`}CVIrsa%)4#xBOMY@JAG?i{p&R$i>?|{9cYPLw)q9%2*~5PYV76dV z@_B4{JZc?Jj7x?bhiwuHrrV7dZ+C=r2u3%IuKjyOqZ{sTi1v>58kChOMIcr@Xj}hv zoU=~JXU>wUG=zT1Dd6M)8_TONZ7JOmf>0DaGq3ODQKO~}Yit}gF+acepdLQqa)>z8 zg$sgclNRHI1xh}Jd7Z3ssturLPmmpXLeRI5fv_eImMI{Go1d&goAgsMBpO82>0Anw zxg)v^%PZVisB0RBZ`jlrfqQ8OO_wQkxAs1sg*K@I|5iklN?Z1y-@iZBIJ98;s3pUy zCvz*BlC7&;N2}(BrFfK0L}_Nsm{9%f^XJd^?lr!9R$Z`eaUqD3%o}6GA|m?DzF2HV z-x<+?&t8u|HF8bi)MZn9ve1r_%*!S>B1$v+)_@i+u13a|5dc(fK~vIc%<70Jy@mu~ zS3RUElabkwy#k(*A!Gc_?G7RmM}~dpJ$8xNc6CnT2Vfa3T)>=_>_zVe5|TIOR-~#_ zC8x;pAuYl)L4TL40f-cXQYTb-VXJ)?dDNCk+VBw|63)f#fL_A;j?F|a!?UW4+w`fF zdEsL%NJx2Ju>6XI<8>Ff@w$W+lR+w2dPRRNYC?UZ||1nJ=mAT9+R6?(bT10u;7&2Q#GBC7fG&5`$N zlF;adE?`!f7wtE@IgGS$9r!c=anxnO<3fk5eDrcRh-5Q+uPprystkcdQS-)u z5|m$yRxXX%i_>`yJnn;dN?U5tG0{i6y1)rMh=<$nWPet%f~p__RXX6aEES0|{h$Oz zv(ZW)#DfwY&u1d852fg!jDz`bf|5!X{-jpcfynNRBCBdnMR_4gf|fihd-@l4GTGeQ zJD_%{iy{ssi~md#K%l&-Y3$kKODzy3%6(>i38)j4)^K}-NLq^9UlfT%j#SNg`n0L3 zsXSo%-EOXdJC!co_p2UQ@9bXNPGjsi1WH8aN)QP{aT|u=*Mjrs&u=QWii?VZ-L38_ zQfuZ~Crv9-ob+L-V>BNq5xZ~l@*?3>EGiFF^h25)T8VZr?6S(zDxFbRN+cXkG9cl2 z!$;RF)s+ep(7N09q0{P0*n@jHmnB3*lmuQ&1tPgHBN>3()R9)9ogu`P!G2jHB9e*6 z2ebxYm;oD{PM39)lY5BTp*9;*>Y9nvadA6~(#nM&j+y`rFNjDC*`XgV@*RMG_byV$ zw@SLM1QO79_U)Fo9bE{7m>L9td)!BVA4r4>bk;&u_y z9$c`v;6{6J!wMoQVkwG;5M&3&q_r9lxL0c#$u>%IWrF=ob1xe(P*bU z2Vf#HhY&Ylz2sI-k1c$-<^0T0krO14tcp`z-JMsKmx72$KcOO6(xP?H+rEdJAB7i= zZwbGc1`>;J+_=(F*(JY-OB8tno)P;EL zc|re*rz8D??4Z<|bm`{JDNkGP-w)SJgzO4C9y4D`Bs6;#U+V_5t@R?Vf}-gkSIqS1 zup8EZH3Sphj$FC%QMff+Qz?Ce;wA0vtB_*(3YNLTjs{`bS3A>cjWl0rzQ zegPB}am<=`rlqB(Cfs@i6D2 z6ADgo15k&v`F0Y#Z51Gm`Dz3A?p4p>224^KGZy9(%!F`UHYA{E)d{G0u>(4B*}#}k zQhcSD+;cz$Y@8{mCHuAy@7`}?!3W7nHQ~}#g2Er`|HgA@E;O;YO3MFlZrSDQ?>sp- zI?!Csu{WB^K7aB?tqZ^6pi;6fhvCs6XHd$fOtumm{-h}AFNLN00?O~|?2JZx9xq|Y zKx4x*!4*%`OEo?nsQOLxj=N^ju3qL-5s5^)%6%XrN|6HN3!q$P8iurJIIPQU{9@8f z*41bva%wxorsyG}ZV=APp$UGfOOE$m+JX=H_Umr#v0;O&tt4?a+_&QtVl54~vtCOdzKk zno2Xx5y*^6mP+1!LofMj10D?NzI!?04%~RreQ=ix`pMk$V*_Ron#crdYoV#Y5)c42 z7vga)>zE5lR(fff_tQL7&i0Pzq#J6@z5wyNrYyU%zYw5mD0SY;d4g z(`^s|@N8o8;CC55B;-1Lx=z4W=41$WHLK$&33GM~1AvTA;tc|%c(Pqcjgq%(LI1F;Q34IlCv^fbVZ%6Hq-#7eVlS=;EWnQF2)>1ZIBpR6X{p@m0NpbINa-gXWB$GhL zGR8ZJh$QE!t6THwAV@0T*t^frrlKeg;Q#lMyv!O$)M!m>HHxEd#jSOtRYa@^?m=C( zU{UK<;;dR1qG0rcb%5d?s5lTI#f_pka8%J~Txcue{NkQzW76g(_q}(1-%APaCHI_r z?m2fV4LTu&5ZRMl-cL#y9ath}xh`r_DG(V-qB$CoW{>`*Z^afP*WV`+m?i(lQECH5 ze7~WPr_{yt_~fWwH+(msGDsxYpFOccrcBdlx}ZXB_vO3j6xP-|M<7qNIgT7^R{{AS z2L(`((dn1ffAJ( z?nFRhN<1QE;&uQq&seJgk*m^a5+W#O_%c06G3hDPlL_-8x};o*(h99N3Id{GN)o;q zv6i-5WUJ|wDu|#e_pg)#DJBj5s>_763yn8ZBIlJf__MhY1;S(tzO#>2eIZ!3B&Qw` zWNZA;wxALTk^p}rT!;e80Q{sM6^oFGwJAs>e)M$sipXA*TGV{264Le! zJ=`dqH4f}doPysR6$OMUp59UN53%bi5F&ToY6&2!pilpBV@qWd3KQEv05el;_=9Ao zH;$B)wPn|~AVlt3)dEq8itnG_xZy@&Mt0JH73}~Ce-bI5B_-@oin~@16vq+yYup$_ zEw;RUyhSQv0hVC2iD1Ez1VX|^+jn&KxO;S%kMJU`zl6{k8`h{=Bd*4|SBQo&+3An~7RtzYJb4&Yjs@=w8&-~%%ZVmqa(4E;+ciN5CsL-B zLg;k%*w(EYH@JJdRn_F=h7HTe-omZDef(eUygF6Ax zt#gBS!uI@ua;d0RKX>-*>+D1j5<$8c0Yx#ypxCVEszSXIA~t=xT3NufumYmWwFX;G zz@Po*<=kA)-3eerr`}@SicOgr`&NK^7T?hfnMC08&s@Iyx>08k5|pBO+q;HfSdGDut-ZY6klT6e8}jC--zGno<>Z_PN=O((MS7G$$AteZae}5(=ZS z@wG4~-aFHz)$MbeXh;V$8moFE<|2tEFk!B1hkB*lPZhwLP6MFY#*^D_bwKnP1^Ckq zy6o|&I1*#$#H?d$90-$sTfs=@wkNzTjPR#D^(+e<(GR-q0OD@nrni+D^Z4o@5n>;v z=DQd)6(kgw6ocTDTR5qYv-iV?7dLV{pS5xWk0&<{A+f8ovg_Of3@wddHCvPZXoEux z)Bo-WR)kGHS9WIr5REXJ@RMO?0Y7(GX?104b*T;j>#sGY6qpsEB1db2pz!BhuM2HA z6wk7Lr4XF>9lhRNyl~;oMqY=@+j2c;Jg0MQ2t`s1!p30dYo9ZKgpSaLkcnEp3_p3W zW&?Pacz#{p+(sFhnVIXmW^EpUU#v?xdNfPAckP=90Erg)+(Fpf2~unpj$S_&Mz#bg zmb4TNf+aQI_;m%owVTf+c=^q4-8{LMJ4uL=W-h9AB0{6YT(P3kX9!en1;Ufi2uGz&fDCtVem?FAH$@46qYFJhe2GC*eve2ovIT85D0y zrlARhIm50oF!ovves$b$LKHca@fr>|h<}JU!BrbiVf&U#=A3wNc%G@ZopEkK%{a;&fM#%l3jfZa(5o)nL; zDPzTdiK8>(vV2}|k97mrXJ%#`&1((SFeGRZ4wn9O%$W_{PF{jn=Wt$Yha~9GUt5;r z1(>j6Fd%qoS2`kGS~Nref)=RMdDDTTKHt%tu6>8}{q`phTa_K|%-sO%+6uGetzWv}}n$%(HW5m!Dl@QHTe&dH=icK=(FH;JX z-ULhtQ7G-W#(}TZT{L@BW_|plwQsH*+Lnp(Xyew-vEw)E6Q31?5F$hRYu5x6Nsx4v z+QMJr2H)&V+V~^UpdXQwvqHcRSp~ct!6JlXpV_pQEm9a`42t_k zkzp(D?jBsjaMu9AgA*(eEHpR-2@?3DMHAfq7y}w$5P~KU2noRwd{DZ(>+jn4`FBg| zzq{Xi@AqC@tiVdG1o_T%rwfPwCwM28r)l>jJoG&$Oh^^*S?cnZY%>cLgzL$;^|OWAVJfgR3LTS zxMp(7xl?C5YY__P1SdjQ>giQ#a6z)i{o?)m`;({$TE%kBX_*f1K z6V0k>Xq@|Ompll~qA|#ZF@3BcBwME3&peWuIXg01#784;L3;X7M(2u07=CkJcRZ9< z+6<+|nE-Gml@x@T&(%kW1p48y$}0TdE<~l95Z?PTl{3$tHqC1WQKdeQulAuTIwgo} z^-x~v{7{-XKY-k7iHn&_CL=P~D4Fz)MgM;jn6Fr%Mlp}PJOE+Dj)`76B)pYc#oa%ngVKqZU=^F#ftiKWnHJ3zfbLXo(jrAiVezZml<7GK4WnlRoC zLZXz&>e82#8-U4xZxZ@&ke4YbcUmk|!q_k`)X&qjU}LH!JSZhZLU zWNs+UmVQ@VyT_i9)44HqlNmqC(P=}!q9}tEFdD#~9K{Nyq~HgZ?vRpb#BZFZ zN`oQVId}6RE2hDbP)em)a^v-f*E{oQpfux^1yB>y@*$DZLX_Xp3BNG*T~yczc~qzX zLKtPV136ioMlGH@lLq-%D>(6+fvRHztJ4dN{`BE8VR!qPG)PS)7o)PYDe=y3w1kQ#XR@X5_dbK~QA1c5tP zo9XDt_)hqv7^jJH!6dry1!3_3fL?&&;`1Xbxr^ONgN)j=ub{&(3OJEB2}D_T2hi1n zNVFxrJ0y`~?~^A_Zoa$OC>B95*S^Jafu3`R5m^w#$f-0V#^(X`#4U zX&iVX{=iu*R-0soY_<%orM3S0m^lEXFqH)c7%h<_!LUizHhbQKH%}f8*&N3s2(h(q zJB;$9cWD}5_|EK?T zK|)&&Snvxzh67+M%v#j9#VppI5mDUQo1Yxj1h-BW@n1?QWlr9DYbuM8Xwv{HcvcgR z1Im<2U4$r)!DnXH z7Oh-GL86>HBV+B_ca04A7w5i%^{XcNd}m75zJ2jIlY!_QOg<~}XS@a)pxgW--e^n? zh&srtc{>|lv0c|zl@K0jr_aRWcRao*EkbeBl!-7$H!Z^p9M5p$UrhThUb^M?`+dGs zx688G5NUH<5U%^))HTo~T&LaST|kAjSF%Z)8(u$7FiNi(-)FN6aCNyP!`VvfFTEhP}Ar0`F*~+lxZbWSQ}{6d48jp zZiG?3^g|q!70hf}n+@65|Jt?YuI9u0cP(l}R&>t}Ll*HR%68ErONOW{y(5gXr$62e zDI~On)cCk0zwZ-&H7z8?jbL*}O@5KD0s!bLB|;iArU!=X4FrzOi!o{uCc2gh2nWY5 z0Wz!9s@=6~t(xbu;BVx5{WE)@Z=_7sQ#+2~EtAa(hFC9;8w)86lDxgSajWmN|IFtU zuutL?Fh45%LyLqsx(WCvS0w-_p1uGQnL8xo=98O&!18IU7+xY|VQ5+jva$_twyssH zcKsnGo=31|ZUxji(KPZH7K2s#wr!a@(Q3Ct5;hkkw(yd_Y=OpSPWyeQFZoMDO5v}9 z)lA8J5&pY?KhRs43)NZLxFmbm-+np*7g*kCx;HiI>gTLh$SG&hg55ec^YF83Ktjd0 zAXw&wAdC+gYd5?lzDj=8>5(Mw;A-I_O^xg7?}@-(=Z z2E^oNs;{{O;$OVKKaItc5q<7O>;+g{HF3((qeC+G(=SkRq7Hy-*@>b6nuoFnrUqvb zrC~Xch>&)Xt-01x>6v+-$u^dvUDfND`!AtoPLJySs!s|;Wg{#lcm!JwaNs?;K%$qn zOr35G3m{MRG6DdO0=}x&>tZiNr1+WCCP#9{9h*$}i!ynz`B5r}94sCf3PLmh4l6>C zkO-1pEe9doT9-dx{(6bnxs$6^NorWHGNpS|Eq*JDnNq?g-W~VXKWl-WJ7OUndoEQ6 z3?!B4fMADU3pEiITcLsN!zp)O5p9x_>q6?9zMS6N0 zkS{np58ehO+CZX|R^$!UtCwj#|9a(a!}?KSO~*7fdB8V*WMkyR;#sD zt=glgShYipmZH+c45EltB77nuVg!jDA(hy~h?pOQh&^hr5HS+*LE;N(BqFF8I_bE( zKEF@>-1hEy-{*PW=WVRbjiPhK3JN#h8Ds!53r?7q`}bC z8A1qA1}E*8GOM`c)TZqZp6=1YsWp=X)ni2Jd@^)zjX^WkTsDS zXkZypu`+%VsOU`y`JGV&0P995o#BK7Br}FR)vsEGJ+q*G9U4IWs@K7H6{;$KnM(*M zCi6%hfZZnoG8NslpyE_Dv_NO0aw9F=UD2r{5}J3S_)GqskwyL)=s#I%8^f$l9Pb;2 zx>gXS5PAHo3f(kQc5LLv4}yBr(OumY7o^DJ2A2u`4 zY>TJ$)ljH))CHm#l8gjhSq~wt-lQQCDpZ#67xVGKP=y&yOch7CX|F;4!{{fYk#}cr z979SqMEqcIBB`3s=h67^{~)fl12a9L)}heqXfr^NG_!e9Ik_$pta_9&-H3Y?07!NE zS4j5sKe?@rqKRR|rAs5!yMzA+Y((BhFVy<#OtaN1qu|)?WgSzp#Je~Euz69|x?SmNFwJPxfI$-6U}e1JO)@fQ zc=1AcjgvJD*XD&$smM;K(<&oUsyz-JYaxw90G@(k(dLQ1@qsO^SI1(}tE+v!jnz;D zv+1hpEV$|>ew{Kev6xyuZnD6w z%s_gL?>us#NO}y@d+~A` zDB7-h(<>k?L!-%+DmS^Ofw3Ya1)DN*G5J)d=cNmmM5L!1+8)K?yrsP_Str=ctUvbg zi!ISEx)#k?L10i|I|foaXlCXJmx#jO@v;C7sF71EQl&;s+)XZ3fs#2Vj2$|tCWF)j zcSitH(?;qjSQC;k?$Sj?t$i80<{luP$=*v{>FUKP$V+ayLPP^1vWZf7ZAEr z({&O$QHO7shz0PtkYMxLwK0dYV$0?Lz*OXrk)eO1juI+0=>r8DJZySn$c>FiiLcWT zU+Eilpgw4#BF%5E1Suqj;~=(<`a+(dFA$mt2nLR0QDEly8eRMQ*SmxKO|rYJ48H2_ zf+c86to%m0EYJp~WlI65HO4IW-!R*1g9-GFyZFrcZwd;fEn zFQ03GOjtdOA1d}%au;+441?c@nyX?F%`#L0DvJ1MkHDIrqi(jrZJ*1%u)GS}Gh?U2yZ_g$o^#n+E-%6$;q16GD_iufta(_u?zg z$fDpzoq2cdT0Fi_JyLld?}Dk$=2j+Wt&1Yj9f%Ly z|L)8XIQI1bNrfA|I}nV0-2?~sjjvhX%pzBV$0~3K44~urdZ^lW5`$dmwUmb^zpHhG zI@2=Zx~V5$NCEgCFf59seSFQtIq?JKHK;CEj`QG*O#lamQ8P+Pyk&sjK4jGCK-3q|3I5>1o-gIt;xj3WOVL z14)LLWdUEwi>`l8ZOg+Vful{Zy2yh|pZX)^$-Gzsq{v*rW&r?8cN+>unnJH8k|loV zaMi7zySIl|viNPt6H${F(-J~Hvv)7CF@;ea!2kE&d9^bgRJE$DdRME{(MM85z3Nqu z(3C`|v5+cNLcFaiB_XC2ELd2G&`6pfA`%-L)48e=Q&Le38XFNwH^fS!MS^JccIM8^ zy?6e<#cU^&%)RIP&N<)tep!c>ij02xPJh?3mZYxRza|lC z8NC(;AsM2(nn+!V+pPeEHBJDjIf$_2Ca&m7smx61PU_2-rBF|HD-6QK<0xS|Q^|Q2 z#*;G-{Whnek74d2B#H$gcfsbl^0GzBWPQ?@q%0GZJO1I*9gx9@ldR}BZxZ@A z4b%fo6m4U+Z8JHyLp9dc>z8k=HcS>e9*G#7t1%7AC7isU0y3CHCw@qsgnl;WiHJfq zX(WL2nNUsY`^TRRlZ1{-A_g~Nf&_|hW|0?f5~*n6ei3TPfB)q|0*C+s%CKlpMB0?F zGaHdLWo>IFRARmH^~+?M z>*+8wGiiSl9QK19p3^>`Cm$gbR*iMo5oIv>>8{WD~3^eTTDD5H4KYpr<0R zGZFL$TeWZcxsFW%pSL#agbg9Ob?bN z*BiK)Ytj@_#RE* zm2yO+Bf0Sxj8?4RdwO8Sy}`afCd>ZmUQa&sK%DRHm4p6%U7HH4Kok+8Q*(WO605QL zCzQn9$lgnDcJZo(0VOOiuk+3gwAFV78uIlKfFU^&?Mu64S#I}s)S5N-k|blW)pR#$ zY!J=X#%2k_VL})tmTuvh5mH0O)k_Z0Kx}1Ii_d;*C_6ZJs|f>GWJeTKoy`J-bSUP@ z3+yS9XLN7_Oc64s^L3{kTH8{b(3WRiOniXLY4V%IK z5%o5@kY9j-jB0E_gqZ+O;iGbM`eFeJRTVA?%!XJkS1blmWbACx*ln|k4Nn@gFdQw# z=;N^AH))jxN+hlC>F(~X1X1`b0>UB~I)g2U7))Zb3lSyGacAJ5R}M_xd&Me1p{Z>Z z9w5ECZ5&t?)0gatpb$Bhjm5BRbxW`m?LY{eM|wKDdvqCqg(Qv$AX26{5UgHW;rG|o zy=WK(5sJ86Vm^R^IWCZ{Bt1RF!eTUt3&z{w@)f%tR!ay)Nq0}r5naw1uI$w1x`8ML zsy5{XWq-Rr7%bOV#!o#~Lnly%MJUY$MZ@@pa`&V5cHbT`)Vt%Gnv$VMHLshv1twBL zgr~lL5{TSh?}0%{8}u|ToeaXZ)!o)ESI1v0N-EXm#+@hz%tgKZ@mKcOm%*TH8Eht{ zSXe2`4@ZD>g8eKMZI&6qS99xR`EA~dX8!+()YSZ<_-|5g~F`p{AKd05-io{^A*K+lh$6CuRvqu|VUJGC^9A@#zqVXegFz z*EIiXrLZ_oAWSVOQj6yQB@foypel)*xRCAp^ii*yccLg-_v{&qfyOrC48nBJUDS+U z1g*YUow-nz&~(ZPRm9=A3G160tF&5ij3>)vpX?rs5KVFBu7x@h#-Q~k=sSCN8TwQhg#rAzcXxNY3!Mv{&hBop zyJPAs6blu*amEJ)JHS8`%nxFNsMy%pov4T+ilT`1L39QPA}ZKk=l(aJ-{&#L;NJ7T z=RNN^rnBb-^ie1qK554-G}%Pnt8B4kRsw!W?sxh`4>!_OYUJ~r$PD+QdPzUXbc*(d zJ|Z(i00M)Y0OV|TJd7usDbOb;Y^6|9Xh2MOAp}HZDcK28gec$#o(jcUEI_(;KC3Dt zGwNN~!j~xhgJ7~D(6Fr&MccJ206hh`F(Jylb^W0M`APvurQFC;jsRQ=WC=fru17SS zegJ-QsH+PZ;0g77eWRfO&51K)vB}yoAoFRIEQL<-EnVB?bwgKGlL{y+c)TF{@)v>@ zicZMtUn@HilwBS%fFJq7_>o(JN{JCW8$sQtB^Umr>#YmtUtd@fg4W7z+qQb!+lA0r z^?4r9|H|7rek-2PfAVmxzsMxl;a0Htz5 zooa3HCxM1rUZ3BzC?~X*`@qwuPgmkAG3ti~q&fF;f&Pm-Z~LzOuf_w=msG%k#kWcT zazjR8G9S5mHdxXaBjq)-g;1|U&xo1@(aNc@ELfrD9e_XU{oqDJXfFHO_fJ!);j?9Y z=HFfgTF4#*{f`0zHncD0M}4Gbhu?{Jrm0{+g` zD)n#-(j=wdK55;chFhSyB9pegO}&5L%8SpWaz2ppg{tOsY9z3{l;nl59 z>}x<|91CJFlENJ>b}3P!um^uLJN2*{(&O&473o@(7h4KJYq@)sKbYEoj-?(ZBMJCS zNzMsEU&`hS=g&VV3?iamXP|TT>~ig5&w51z_=|9>^f$onImeK$su6?&(3&$h@~!RO zix;5G$zQZ<)kHD~JvEHKd3FB$`4S)^`jtrGLfIl6Itci?YSDuS@q1pUAmg|E5`H1a z0yS#{5jqj-+Hj_kHFUa~076w=&`l^Ak1rZ@;lZj~N%q84-I9RFb^_hn)`J?$Xa6Za zH}DO>Kic`&*j+~j=qcC0vgKp!!kLyxUI37T&`tG3ArWOCED08f^DdG)F%DiLyKyQA z1s5-NK?RqLKbSq`p9AoM@yIIW^1$rY9;mecZ39sH1OfV5w8{^m5L>Ad8HvLMxD4@F z%1$AhB9_|TloV|-@ko-t{2F>B1?jxUlV--h%(BrK#lb= zAm3z*U2G8~XvP1xiCNhvA87NF(g8J!*9LvZ*{3?lu!O#??!TMLj?R=(Rf>VkBx2Or z2colV-&Q%$t1eV=)Z%7>Ohk+=Z?$rHUl3(b^MWAC0Ko}ChHANol~nL8iMdZQG-+85 zO%qTNZnv$kRxOY@h?c5b%00cz^|JUv3Fq+{HnmRlS=0e7DeTE@eU(Rn%wYG;qrRg@ zCrp54WWPPc0RTe2=GR*m}Ci9uqg=P83K0S^emWW)HC3JSO0eFfld7Vdc3^b zS^*J}%?J#@CbD-L5S3vOWzSu|J*3Rp+b?UF{RS2hQ5vM{48Z15ZYM0H?A(`kPTsyg z%xbN(9ITxoB6R_HK1gfP{4p~QTgc>Z=s3_*<@TAACx=zC+yupSoj^qNcV+MPuvBfW zIpnX<7^W49AOlvny!-Nc_hHA&oU03q2^2t9tGbJa<{B!MV2Qp(2y(bsv!*4((3z`9 z#r##O^jpyU_VLOE%Z0su56|JWWQe&I>2Wyl-@LW14;eOhT=}~7kJqtW0MdLCR6CT(Q<(=u41tMgkdBalTKFw8KyMJE^;gQqWs*J*9W3G%6NMR+CI-?o7`2yiZG#bMLwTJy#p$EZ#^>o}v!fhIq+yr?7q@XI52;@UWn5 zTd<&hc20K18nf*9O|SkkqBHXeS&J4R`5Hud08P{{1`^lr0&he7ri4PQztDR6tRIAg zNehp5KbxI>_38{=3X@a850VHY$YX*a`KnL1K(t_MW|drpsnYOe-+T`3W_#oH*JG)N(6w~EvdKu5A~^ass(AVRnp|%*(OSa zjDGq#G>P5kq0~A}YLu*V?(FT`6vVPLn}9G`ME;~gCA;UGZ+yNyl1=FU>fozQ3XGGs zF;JytOPXNv52fjVN(;&js}x|Vgo(DmnNLHZ9qir!lSiD-&N+7>XGUKZ23M8p#qNJ9 z0{fOB03eoPyuW0CsXJmWwqaiU zKhEp31HOT9w}w(dKtklnvotzy;1TRBB5~@V0f?C^qt}v+m%kR^?X7ohPXlqcRS*eB z8(`CL-#Y>w)K0;Ptnm@?9}X=*O>jy)x459O6@S|ECvEhBiQwWn3GA zNSqSFG#XUBq@@dT%UvLZFibS*F$h;)z&{mM0aPvtVp(>NuVKRqwXR&be!bJcB^Bz` z^GYJ(B2OPW^wwG=UGQFiL?X!0(3qM4(gvDntU$5}X5DHKD-+H7jzwve^-;V;2Vd)N zz#H(ON2hkR1SBGJv%SEwzt7F!c14)J+8@je?jRbL%P9Zj~Rdb{(%H&y!`KJKNk-N7qyWAw&m}qQg?>+CZhEFsHGskF$!I$g|MfCxj59 zEkOq6I{!Gqb#%!DY-a6wj@yc;L`qQ-LI`2R>FF3f6k*^|$e&i<|M=q8r~9L!yR1eDXM-cN z?e6whOo8-=f9e+Tr?=1yMT>mV4@;bC|OOf$v^(U{;w3_LQ3 zmfY*sb=?UA6@R-HVa~D7CRuJUrFQ1u%PRprw0WJEH{J)vq+NUXFt-E zT#VEk-VH10X=zW1l~V-c$o2gnVJ|K4V;r<2ZnSpQnAgt7Jd^31`I)Cq^RnKFZzGKL6+G z@AK;3T<+2~{XPHxZxNP7?jN9-Oi;uXdG_>*%Q`CU?c1j_zy_7Oj!P*i4nhbKRnFC| zHp_MQ?XR4vU4U@k-kxjpv$VHqM-ssTj;mQA)+&GyLdb98T1G;a<8XeVGXu4~1EC$? z1>wwn@7d^i>(cJd2Me6}K?orvW6h=u$O;o9BYsqy#viVJHM#J)Ng8BKQxl439QW+r zI1B7g)5d`W5vQP2J*Si#Fhc%g?W>N7BFyYLkQL6U`M?Hk-K29#DXC8k_ybKJ#edP* zM&BE02cTY-Hj0r4qfE)&jP?KCZiQm-O1J?dKB&OB$*O3?GsGvGC7P_Fz-UpL5y98E!Bl zug`ZXd^5m~QKQEh@tJe} z0XU3QI(uu&_M%X%0u9DYynLILiHD|BU0_T-j8NkM#Fc=gOjFmnIecfo_tXkWEg!4c z032JN`pxAk8{^3hBBn~|XU;B!f+h63^Llq_uwl*t0CSV|$c)lG1Z0N!P!s^Pj)RnJ zQ|IaNBlXs2Zb-^Kwz)#ff^tPu2AB}`MP53azD3!kw<|ASpU6l@M$L8_0H|w2CaA}* zK&JG$))JDlyNvin?A>vYl#7*FTv=eXoA4V`bTn=7B!qc+8n3CKR*V@2`HO6!wA@ge33f=yV!#(U;&_OH=Mi%D%2hq}i`g~!qIA`g@l0Qk6GFbw zG$}q*g;2<5ffO_obHR`gf2U=5z4UE2CM( z9_DQLCs9Qp9-Slp;*F9q;&_ATkB7Nk(&<=?1DB&AXzM?r*wZ45+V&>(~itrW8g zkv;BhMkq+1#!F9rP#gau=lz46z(X{=txoS7{xW6i`BN^kvF0KiG-{Otgk%km5a3rd zn3-Tg)-{SkC>5c>a6w}n#YlBrU~0V@f#lzk{_fq969`0O29RxbAAp0HES2kD^gr?W zZd7)L`NGRk(RRMCglWC7$FF4JYfev@z+f@2T+y~)gNa6Doq=wB6r)!!$VBP<2&`v% zdit8-2q63ZNCb(oPVcKepSNUv1vFU6LW>JZ2*Ad5ckgbLzHYC4r(z(%p&ip;;+@M0 zAmj%H7RzMno;p7QYr6L2yR$>>2%tzLf+n%P*Lx$z?=M--#z^nGvT3?2Vd9wMZra0KK)=V7VoJ~8Z!= z%j+!@6XQ)yu9KMPn4i~dP=SaoqTj>`TPd3TFJ~f@%p{Wl41ouijfdD=R*1<~FWQ1H zIE$-l)v7MK!65P+DGJsN`i3Vv>}GG0>03HXHP5CrN@b0H$Fr&Hcv>Z1GBna}tuOc-Faa*&dt;f)ku zN=j0ax7LRM+-Y&V5>o5ZQ>pOHRySbO;jgr2$b`Oz8lm9a@NgQO3a+Qo$)WQ=jUX}Y z5j6l8j<)^&ClckD_#t7&S>NmX5P$vgj)({gZ4wa&->L<^si2qpj<;`$u1D^n!=b`I z(Pl#y6qrYsF%sj!BS<1@l}BkotN?HEP#Xu4r&xbdia$BE49$=cQO(B}6q!wrYTUK` z_Ejgl;$H}}FJxzaN(%WiO9Fx>!dqS_JHMAroR37Eh9L5$Qt)Nh-{?CfCCAUK?oAyi zk29D&Xj)E}U-nW^A)xkW-o1PG46(w*y&@4o;Mvca7PyT|De9I@UTo-5-G_%AjsGNPHm!ZbmW71JKx z3(Ge#Uzy}se3ZA|_(C9IOfMjy+(VbVOJBPJ0chj0;U_hvUyLs^I=2;}QM5aUjI7xG z^3~C{9rO^Np^&Y*H!0O?#ecE6kRdx2j>_J&=UWkmw4KVt;xkLRPP9uijBx^hf(7wc zm8L9M)qclN8Z;Di5!>28TD6b8c{A(up!^V@byBJ~EPCpU>~af3e21 zpOPTtXEgtT{2R3zh>8RuUzFw#jnE+|Vv~KoQ&kWMFW|fCa&9$x&)%KHG!;c*0RG== z-zzNzT4_P6R&a)jSkx*`IDn`aR1~ESI7GxL;t-rQF&Y!6g$*$dF^w8yVB;8FXktu6 zktQZMBrZ&JVVt5yH^vwi3Jyd?OKI)9_r3G23M)u+bMHC#oO6X=elXHef)LV7646A| zXdeLi3!?~&75_(%y1I#VHwPjZIl+MM%z0+CM(D;v$Db^sMMp}S6GB>Ah6Fm2lPGf3 z4m0-1tj%b{q`uzxCM654O5M{F?31ndX*kcJJRv0F^mG@YISCFZW?-!ikn%Ha2*x-u z0lOST6~v{Ila*=+2sHsBm`pzL%oa#&kxT9AyK1u4Mf|eqz~({FLO2c7Mo`S0CV~< z5Uq(D#NT8lmc-eiS{;u}dj9zum4%S#k+aMQfiu0n{tovSrw&&SK$`o6mRh*R_6BFV z&pHD_TGM0O$B*YP9_vK6z$98@Kn+%eWN-cLTl@!(`L2EaXV-IokWilC+_`vgMeN4e zAFP=8sXR0_{3?Gm!q9*Fr%zYi?&;uOTq=kviCMR9)uw=R@?2Nnx@_w93*UxQG__Hs z#;!6TM0N`lCGEV7aC9Ad_2S8L{$CZ)?Rh!?M3q+8PjrnN#(S@vweI#qE40L7$N#Y5 z?MV<-5_AaFl`<&n!Ulw;f36e*{)uIq=v=H$=FH{E#$FSa>Cu|BX`JlL#`@dY(3BZ_ zbci_d+^N@xhJ%o12WCK7vJT2NM^A0RDoeU}=we%P<5Xu(eNQJxo9oXMqWS zh*IWc4-cjdRCIOS^N;1 zP(cV1-d2lHL~P$=@UI{T-(=7%XhJlM*BF8*${LF%k^z9ON=DQ;)zG_>kZr(sjsy@w zv`U~FXwrUT;sL3~0>tSN6)6scLSnHiK|kEw^4Uadju66wMOFYNDkEcq0ATT2h(gW! z(!~};g*-q&2*i>-UBH}#WV8_IR*OWMqjEF|iL|5DfLMJNgarn>fbzncPO{hSpMvNx znGsaaGz)$hv@i+G;kI_0aANk`N;=muM${u1f%Po3xMMJmUIJl5(kP+a=MnmOeg1Ml z(np~tLDnOfsrTL$tNF=pLV__3rgk0Hq#Tk$7-Ja)aUw!y+p+g$SCB}Gi9vfMd3*u? z(s_lxK%l%sqKF76Nei=PP%3-%xPfLP5kgp!b;86{MYN&#EJCK=`s{-lB$5gW&~Dv} z`~mOX!a%_9sWBlE1|=d)_Ob(mDE~$XVM#1w{SM;%jR@7*8;{<sz__3jf|f95xBVK=ZrwAj0QkI!suY%HuYB&Kdm?GS@jEvcxWOIbp+<6=j49-O(#l@DJ^l7 z9@yov0Ai9Fb4+CN)5pcE)EtmM3obXox{tbtZSFa1 z%zbQ`W0))Es4M0cN5p+65^+W13KCSAD}+W+$%MEC@sE(WL)aMJx9|HteLl&uCjG0& z)93d*&+qqpR6=hAfD)ZP{bQo&a8n456>;SExIK_wexg{MlCvAjL_vHy^)9=FrG|eW zhpC?YjXhJB=eswsyRV<_lN z_yf}_3&d0YpaO5Rpwxh4A-)Rgy~!kIo(}&?yD@d6>(Zs=%j=KbQUgVbEUATL^wAZp zS?)}q@9y1%1V`=W6{A5Z!3vrd7dnHc2>6Y}nyB}%4=9RAtdf`ff4~^<702Okr7utI zl=?1pY$VF*P!#)y$)k8kLui|vdHwpUSGRn(lHFNp%1F8GznxyE4wR&u&!Lm^Y#e?g zF%jcdZd30nLD6^-8l25yEgd7E;j4z( z`Ps^te_KAf-Ma>qr4+47_ybneF_UFVS^Qp$f?QfBAc>3&P*mu}ZS<`7bow*_dpx^# z?eYvUqi|)*M?qpuGh^WD21Tg;{91L$@5gw^Ft-}0--+6wgwO1sF-8<^!Jr5v9t(Qu zN=;;fjR%C*i$PJLr!hBmxjdcfr>1stxt1?ahir5@)@?^Or7SzES64vh(eP;Ae67(j5P=XG!Xzz$`p4awDJ4jEbfS(jfak4$0 zg`V{j`g!tQ6Bx*;xf5DQOht1T%T3rjv5Of1N{sKVkK5EQZg)QvMN>-E`>$dse{(3Y zKXDP>l?4w1!I^1^WERP5R#kv3_~y0FocEv2%yTvoASr$}k)Is(f11|sJR!fnrzYxt z{F7IECs;_0t)z~`A{OYg_1WWb_^edNO{?$SySJN1Q5X%R#t6}he(ww&l-IhTgc;&6 zt-1ds5PUgx&9MWeK_2a}NXWzBAXyHC=ZT zKov_=_ecQd=g(U~6uR_%!N8Lz4+>VM*J)8+<*)9UfpSQekG zD5LgfVB}#KU}rQwV@Gscz53q8@n*=V#mtuvr_e0iVyfKB2mp1vLL4=Zt}IBoAJ})G zNsI<^say#p8gn|~^cYBrPi_w?WEd8qXU)LBila^G6e*I$XVu1cE_HHuzmDVekPowL zsgribDmE=dC3p+GN4>!{JmkamxT@lIMMaACCpi0_5g;L^Q5z#jqVSS?oe`l|b`btm zQ!`|vA#qF>OQk3jQ{~FQ*lLKHI~G)UYVj~7E&o6;R}1-=u0A613gJ3_J4&~12T}00 z7#_cfbyNgVG|E0MWQZ+?5Z9jaK!dIbPvs{s(xCX_N&tp3YN?^3#1%2cd(@SGw7|bV*|XR82BL3=HR-*0yR{4SwWw)Fy03&?vedf-0sxqoXkT6y#A>fUHXO z7^($D6-SFH(_Ajs!jUOt?PMx}b$|eXZBrE@F*cc(oZQ?lu=py^kw9AB9LGV+LPkcq z6cNL-uEHTL8^bvBS4AE?!+giXo!ZfHHvpQYR6iQ0FalN z&UBsWTvhR_9S_z-R%! zrezIX0jq_nee(6Y=W8V;yzpl!<>)+O{|1W)3DBlxHDfI(+K}}cNUVGuh-J+=o0iibikANJ_Hc zH=31!Y*?F8qMd)9fM36UI0&TEC-sdeyEv&1LaH>)Vx_3?v8C4O^Vc2c&pTpCIy_)^ zY@U}9YgJ@1uxYai@?cqr!g*kNJ@R+DxB(UbEXN>(B67=uqNp&zyIa?4Xp3pmDBcm@ zNGYjU#aGtOqcHsDc{;A*FsBkb)9RaWkcY(zaWG-AFRMYQ^zX{zixw$Xs6<$N2PlG7 z)}U~4!w@R=TD6?`gts?u)5cv@UAv>Pt!M2p75apGnhk(~7E=C5pm)V7Q}@w40MyIP zO)2nhQ$Zpt1MyWEMMo?3qY@TKDY91;6mHmFgovSbttR+JZ)@vzH&oGKFgM`x`~5Na zRdhvDo+S(-bS@GU0W_2FN$E8sgAcsZTW|<1ts=tiD!ufesPFO)Xdxj@Z!-#~=Mf?m zlVX3$i*7rup?cOymZSmJLSL52U^IlmaBff+6hWA6fd>lDZeweJFJ}IF+tNgxr;ZKpx2#ayplRSPaRL6Gh3T zMt;`WD?Z;DcREjgFBSsuqk43KIz^`hg9=Yc{4XXOC^_gpuy^ObF@#|pz`rv)vpc(6 ztG0IAbz67bSBtRjyLBH8Sz79f)K%)rk_ZxK1c}z2xEfa+2@&THsA8*>(o!i634$No z5{V=3&?_^$@60@(KVh;v?>q1NJl{v_wS7dpI;?D%m3}e(a`O%dI4OF37m!kkzMg$U zrKOtIK3}lk6JKUlI;9Pc3TvPyI;bWujgZDn2Al>4hZ=YC?`EW*Ki_nMhyW8}=jKjz zf|SO z+y`?R9b;x4!)V(@m4fWKD&4fq_Hl@?qDT_cC5wa*nT4D%BhWE6u4`PhAWV z0u&_ha5bUoyq~O{7AD^R@W{70sTwQanr!0e@eob3?Q^H4c_ql9*310fD|@HkS{WC& z$pzV1qUm3#0URyBzj66)-%eClYXc!fc2PNnIrSim!3*;9FI~#WxN|LTx*4(wTUHx{ zX;zgcCk0Q1MZSf77HKlpmk?57cK@3V2FPRj%8ajx3tbmXXaf02b~?~zoJfUtrPO+% zh>%n*hc*#HiWla8vko#z9(f__V*16A$&jC^K`02(5=q0EO@xr*Ne4F+Znr=d;l1+H zGcKm5H{B#ccCDVQ(s7&=A%qaE>72Iy+{`G*KtRQ=$9lBSYTEXE*Ts;XbLcp#;86)< zW$HO1L=UVZ#%Ou^lw1s<_&1wmbBg`TK@PkHqef<(K;_j2$gdpT1plpBCopAq%O4?& zRJTru9@O1G&kRzW(eZQe9|jXl667IHU%R_1NPvVh7BStD(QHLRh%&^a2#{jco+2Rt zgyiH#AcUdWST<^rB7`W2nE-OW5zs^o`a72}rHKfmh#;A>H420fq7MR33$O<8Jmlhn zY3M2*!C@Fa8brM~3kSec6NC_=51lryv{ie#2f_q z7Yp@fGR{QvMitdyTr}f3$O&!$2ulHASS%qp1jZjyS=8wZqC7`Vnm2D9$Uivar)Y3z zt0@(Ap7(B#wm>l=qH?oyTY+h!*YRTkcDq4j(`*um^27~S3;ih?y~Zd5TZ1YBzOxS> zKu?8j8y7;)D(`rH#s;PEo91TcW-nv*7)as(z&+#p0&K5`VB-XcTG_Klw4j$?AoPFz zrf|#p21AxQKww|?qF@TMZyfR`V`^ezYI*1uH|y!E=h0A%`FM8rgIKUiau@(0!Siha z<~?Qvl_&z})_jFVW&m~RP8ob<#G@1v{8z6Q=H%tYs%z)QaZo~)8~3u~X^yl?@C$Dz zj?wXUiJSHO>5kS=PW7P$@eFUw%^n8;xq;ZIC&d%p^=1foV9xz1AX2n zPZv?N#S1vdXpb9;nAQ&ZHRRrt@dyaVFgp&$IPklOBa9aUx2*%BMmBYao(h^MuhEur z3BxioZ)QfGMevD8NwK~P*! z6jX``f(KC#DkxgfgQy51J$Y~qE~t32b*E}EjhTEidB0QJTf=1D_r34E_gMo1zH`ay zNa7IE9rmEQ*C`4yc!Psmrq^}E-+Ob$j9K4d|Ne#`>uHKWHj4j;)8X%|26Wqk2!mlj zDg4Rh92DUR0vN?^xBU;h8gn*$m6kzB1sTd&AKWnQ!!)(E1y+LK4o;jHbbDIr?zE?% z=QnsfKA+ETH!)thjgY(t%5bk+)Xfp=;hI>XP!otoqse5m+InQvhs7=LZ$c?K?La%1 z*dK&c2xkOfSh&KhLs^*5e0cZa4C_&Z9mbX;Epw(%pRbzcpOCl;%IN!Q4T>kkQ?e*d zEj)fC$*EK>>1REqK$IaQBr)v*(h}=M+C;;2y#Z_d*2S~UC=0`v0L*+RAS=8r9t7)r z7+kNG2Go!!TA>JjrVYh2=kpV!bc@%FVmUJRuV2p&1?ifB3Ma~_|Apu6GY7XtK`P50wBSnsHh%fd!*~QX zn5_BG&b1>Rw#HV)7B8OKPLvagT0hU=dbwAGrX8sShi)0Tq%Vr5&)mFzBg@=!ku^r< zGFn=)VcW;&A3r`hfUa2>j|Zw}aemK3^XQ;=GWv<@9kxKSW=c$Ii?rS-Jbql5JVFu^ zBWnXz8?*JV{UUx4EgLx3hvFr#wTZ1FJsVvUD1B5`2i{-0l}FcfaXLgRLJ4Uedkg>V zFANr98Jjbirj#tUlcZQ|Y^<&DC>!;g^bGELe`S;CC96dO|MN!<#Tz?fmp>;`CsNn? z^#dsz4%@d{hL1zn__aw8CD>aS9@1^x8IOni`CTrD%ckQ1!?B1I0{aB9Cy4f(Jc&{W zQ)>X&(sG(kIlHjE7fLl?AV?|4E_{kcmMdhhnns7^B~cCeDNgJIqCLx(qZ9$jfezM8 ziZUdBch!$l?LH4u3R5aYC-KVgs%bTDlGQOvH%529YEg+7$R*PF#-9{G{^DxPiW1G5 z1yWi7R>e+-D9n(`sv-a33$Fi(fO8apNoUa<$iFbzYHPGzM8Pp!c=Ls!X+#d4=vb`NCCZAbBLIgf0F%ygs(5q> z0raWK@^Ex8@&53z{v*>(O_@v{q{_M0x}dyXqd62MpoUs)q9`l9zKALag5%)o!sJA4 z&6Fu8I))xCmgQ6~>~JvN{YlEt+USDf^v7QZP!tP0C4~CTAS`gO^Gp!(2b|#V(`V$^ zm?%YBzl}VS#8`S*fNqu{-xwQrL2;8_zBmN6TDC;1-yNH(&Ivh+zl2#rKAB5pWl@qM z?WD+?LZK~D+sEb5fskM9%0qGHD{m)2t#+@|>h+v~b5Ic-x6p}Da!6RoZ7 z9}YLWtX9Ev@P2C?CDH0zr`nnHP+rfa>V13KHQUc;(d>UlsuHgQoNNTH;n}HCl!V1g zatI-W{Ee}yGoDTh;5CA0;X}wt8ojWv=SI4Yj1WS8=i4#F2nG0w5Jgpl7E=S@2^ILM*Q952}{A8_*+$XR-T0nJ&BUWa6&ZhS&2%f-e)8~NSf zqYw6(QD&px9%pW-6UPH~FPtU|6Njg^ltu$EA*8}gOuXaBAM`$T`*!&Q@UtuIJppzn z3?AM1;Q$yY`83jnz=RM|Rk*=NZ$B`j%q&|*gFPNQeDw_gEG(P?H|_)>gpjJ?*)i?t z;mc-}6&qX3-wA`k*VO}_@nAr_5rhyzsz&{e8BVUDT8F24rf;fS33ojcS0#nwAcPR2 zHiJev(JdU>d8#!4W5)b3bq)0bSfHnNSwaX=o#5T4b4}>B>K**gPp`W(hGvEnLI~+5 z?~>W0K#J#?bMH=zz_YOh{#RAITq5Lid-t!CFcigc{8!PIp!^Y1Brzee3r`@UDXT-> zO<0Hy3{1|Iq;Ye_!9-UFMjxasCT+K;07)y%{*@LC*`AKCzzH0}y8ryTTx#xPC$ch#!jAk_dAP`4w%rdiaF@>Bc* z0JebNRPhCspjQb50Du`6&&BV``e$kn)b<4cz*@pnWi6Pi=$y8@3gEJDVIMF6AO{YT zsj}u2Kb0CatpZqHO~|MEZN5gx0OXqEdZp1re6+hK+qP{xljO#BCbn&7!r6Cg_wTn=`{Puf?$cFI zRqJ$BccikSGzuaCA^-qDk(H591ppwn0RX5zc&Ps*HBhJQ0088Lvb?(Ff2^UNd~#Z{ zzPY8Rt;XV5_2zuLnYQrd&E4wec3orr(Ab!s3ZIe)rJkCQxsi&!4ba2YGA26M*Utl} z%&8{BJkV8BlJ2`a2M+Zy&rR_M*JX~6wolItlxIgwPY?Y2_wPT5kB^VHx3|N?Lk$hh z=jZ3g$450a^}m1r9^HRxYinO$UmqVID<~-5-{0Tf-dA0HnD1%;}r>c6i$IXQVvgoDK{Oo<9By3=9qp4cpw@^zZ;FE33)K z$T>N=w6?ZcT3Sa$M8?I%`}qa9y1LiZ)&Kfs6dfI#n3$BGUobg2H9R~lARr_xEb8Oq zTUJ)y)YQz#$n4Dmk2ic;g=&(VJ1 z^l0_gX3<2EdyRYR-fqnNv~{Uf`ttnP+40u$aD=Cxv$?#ty+*;>GCU^#(B9+3>5WNw zVSKR7>e7U4W@7*ElC8@vyH0^!IlP9!Q$Hobei95zjBwP}^I{l=}?=K2dW`A<@8I#udyudcIz#*A(Y56wB=ge(dao~z}!%7?RGE!7e!hjRCLD75rSn+7@g z@3FDk?SGLkq>+8~%F4Ao@Vh-3@X7qCF)Tp%+fmC64~?RoR`xfVJFVTX+iF6hNqc&E zY9^6@%AP2;CWr@Bc6w$rmIDcZUf0+n>d@)sKQCwmbI<##m%ef=YZl`C9uD$ySJzl) zyP&bCTCJ@(JlA`Pa7vDi zXLc@>6dV4~3M91t>Y)T^x=q4`4#{EoN8DkoM2i{5gdl$3gCC!1GZNyACueB8VA@C# z(iRY6z>E6BOWe?srT4aW0EvaqF0VqpALxWN%Zz9+7|^|vNQT`E^o7nQY^4i7Dx)dr zJUWvQ!p?xsFb2ZS;6f$?)IMN4F>txG%v6iIuM3s_XlivZiYg0sK!!$|mYjVj z{68?+!(RlA)(9yP3iSyR%IFWFU`?p4XWf_I=(OlZL6B{exKOZIFv+{J zP(6%f>TAir)O18E#FGo@Fi9TG&1kzn_WnG)rk^0YPYz@+wO5uWriwa1uZ#!abi{n7 zJuBziZPRVGO$vWEHD*Gr%+`u~M|mD^)IxG#u4518Fl-`|yq1%Z?_})Sj#wu=Zy379 zT;Ohvt_)T43*O@u`b_w@?JxcV3U|C--9yjasvSl}ar)Z00Bw)IJpK(OY&sI}~A0RU` zy)9lYbAS3l5%E3~JWew+){x;ptikA6F1`hAsoQW`_P6Smpr-(X$GM~joBk^U8xRdUb9=j$yL zdDlq6T`ck{Ppwmkpt1-$V%R;rgDqr;NN^z;qlUUQ!xEkIAsr@=)J;#D^p3hDwyCm7 z?q2|vYG>7=*$okYzqxsg0m4f3M+A9ZQ09%_N#4VB_utX$FPB35W@v-;n8zqKqg6Sa zJbzy(X|S(fFAZqtb2#}+GbgQmY>vE1te%EE7i!LIVsfK8?{f>z!GMOYc3p{t)^3UG z5x=ffDU5MD< z#&w#jw8{6gZ1c1ENu8E~s!*YL?gixaGQ(e;5 zRk8q~*<#|Mzk?eIjsWddTqIwTyVf|pg6-6?IA*AqOHIbhq3ZD!_pxS+Puu%}aOun*Yhv9777gebXy_WBYYpHpRY^me zm7BcYpXL643k-ozl`J>JEg7XzyXMG-W-d2(H^w;5pScK@jWb=<^wPxkzqWGIvsdWe zs^qRSt2afyZDp(Fmr~LNzD)-*iuc@{^Xt#7C#SRXuKN2vL4W?~q?@PA2!iz<=<&yC zxOwj_!+FRuwQSH$8l);#oG{djI?g?=K$Y(#EKyby=KZ5{?}*lL-|?bt0y{*gj@^o4 zUPNrjObxKsb{sX6m6MVZUviaK5N=u3x2+^IC_*NXr+?o1JlqF$x2+XtybyC(a;x2K zDnO`GWo$=4)wBizS&{(gYd;iM1fY@zx#&UzV%R#lwM-ScaRv`-OS%Ki0UckZPTtPW zAwz!~tGf#Oe#Cn3vgiPi8SUkzRgBh zW)^}tVUhz+tyjx@Hhb1lLn8HMhqzwb4JwN;EhYamO*tEsDK$=sxfz*t0c(KU;W+;v zc*Put_$yjRd1l*BC#k11S^HPkZ}_e}gstYxVQCH_7c%)=g70m_pdOHd+V%>ucbwD~ zUwJiGg{Lh>Q3QP^S8K7t(JeP=WJ+h>q% z3q~z#17$0io~=)+E2YR5i5n_{N47B9tb1V#{A1$PZXJIoD|i1sOd9dqMB?0rZ~nQ2 zmO~!@sxRI8F~y>OIVL>$8AahCvKxzEp+vQ1@i{G1y^*^-!=|Wq#4!t98DXZs^c}LO zGVV*$J0Y#bjhP5It>sSX=bfxB09|u(BT0<>#lmrKeKjoq)E%oVrlbL0G=?fr2ocIg z6gDuSecPPefa=@g)Wh1#THwh{7r}kcOZ181O!;StWqF)jlHq!RK@qhLwdytQ0Bl`mir_`$BsTI(E&cF#I+XmaNr`%nHvtB^81T ze(kVhPg6?Y#L#8-I+s_)o^Tq{BLBpO_SAr%=s98Ro1XjWqxsK4jw*uRbN%0&$|vpq z_(hPEscMI&Vk?yY9=Z}c`)*lP%<#0})Ye>~?+WdWscBQ`30Wh5ZKl6L9ZxLi<(z*p z8TazO4S5e-aH=mbPbQ1bNsbRGK=+_^55O)FiS9R?p5RyQ>sdm$qDFe||9l+eUTS@9 z_hrS=xk9D`t7AfClHf~|Kban)m~=gqg4LX8mu{$=>?RoILsn&E74$MU>9YlxVMw(fk`*0C8bz@V+Zrp!{CR_#?c>=2h&}K>jq%<0ePZ3-h+nF3G=7*@IVXsv z_FG9e2f{Y6iyn(M)Ty2e(MNk{y5{S>4iL0X_M=ow^)(h1G(RJ&hx{&4=5f$d(RiF9zjna7rACR=u#qAxBdHX-$Shu z|2%%t{O@QY>9%~`nV4t6TZ|_zM&;OF9f!CLA{K1P&Tn&i1KR4uFF}pe@e)qB%xPUo zrsSW}goh+~*1g9pi^of@{p?W_4eDF+6N(m)F0Ql(KstGmpeT1>uEq24X?5LnFqo@e zTvAS@q-Bp%!c^WUnqdD!xT-tcM!g-1#2~huFGX?^a)jbKO2LX~P@Mx9klXG34IgWs z4IV_9*8C#J$K74Wc#M>=K=42?e)O}3&$5YmIorZboSkQofK0(TG=_*XjMp%1%8!jJ zs{3W65~-4eZXcLD{NB~c=YOkK#wA@~oFI3^XD?|$MPWP8Ug_uv*if`Tf1>&3v)aMI z`hB!ButsKv4+_eVjE>*}$!>POn^1O)er#g0pn%x{yDwv&Amr30pu-Yg<~Y7?QkE2h zqV+Ig-9Fqe2XfTU3dDfQbTgKfsn}mx*OC;fbs{WzQ!~L)l&{xf{Q!hYl{*pO+4yO^ z{t`sqt3JnzBFZ3hcmqWNdls$AR{f!TAa7{6wm+pu&*ZSZP5+LBBK4NrJdlOW+rg)= zFlS7K%{E^-Wu{s$B_O(2zGPonh3ug zquk46hHw3#2s2|`;dOSXyQ3B-oqI!<)pV_H*-4drBTjV`H5%H=EL*{CUMgvgC`BoH z{XKBmQ#DPI)PGM^UgPb$>)@#Wu<)e$MajM!Zctz$qVfvJ3kSoirwkWrv1`D>ijOd4 zm~yf0zJ+sz9kj?hJYeVOY*5XY+d2&DKlM01;MP=A@oe?7h<~bSmbtHd={VMIF)52G;+}1?I5IFjfB2+$vELS3Z&Q(E zt>7f+*g$=78Am!neX+RIMZ4#&Y&tdM5x;jcH$)!Okxtdj{%3Zh@3sEB2vDP$x~@S| zwOG{^92?6R6FdDRfsUp0op^v)-^9pv>O15rK7Rra)iDN5sTg8jVuN+;ku|Q)6k3ET zt*XD+LXE0fx*3;2%cQ-x1?forE?MFqGrs&3&y-vI52u-&ci7uyFp&VUCd&ut;12I7 zb?HG`iQ1_;-KMgP1irXCQgB+M$c6+kh7___{fcrmh?VDm{&v?qp@;$^K>gJmm!1J5 znU2|`Zns9&n?wKxAU(nQ*81=K?e^&yI1zTY+wJcIR=MNn^Jp?r`c!%yeV5*rV*Tl6 zQ@vYUPLiHFL(+Zuh9vA|L*0kP#@S0)TwfZgyd#RW?u7B-MXGDCxH9PwGFj7vId zB0s`8$<~+1;{fbGg4*|ce6zT5+V(1xcAP>>qvTNNR&PK;-8jl3}hiHH#@e$7{%)r z%))XLZy&lvOY@uBH^laT)6RS!Hw+!@n$yWVld&JRgchB7O@k;jGaPDb-48`W)6Kl{ z4^ji&M(%m{`8equ>m05R*UI+k=G17Lc0vuiF+O`IpZsVpYKfS2q4xiH=w^-MtYSUs zwr93D`NHO7XwP6hk=^+`zg#@Tu_#Xg zJHhnog9P{3CL4O&z_L#t1HhFc`juSP!J?OVJFZb<;66a^*;Pi%PA-VuevEQCXr{W{ zYtDS|Cr+~E3NZM;l7jv5(#>&|tL ziGVkFjMX8Lr*Zog_bnk|HbUKgpY8E{givEMcx32o4Bk*RcrY*OTjwjps%_+YA!f8F zvW4=qdk9)rD1)F0>_gA#y1l{q^TM!Oynkel&XJ%B8Ph*g52_qhnqmopZADT#tcPLa zZ+X#2#|0RzTvqzUJHYNE?hU^%aK`=*$e0T zY=Wg{Z11>17a{ot&JlnTH~hMDUV9&2y|PTR)wNzAiYU1C;OmLqDSk zLy7xl+TD=C``d;8Tcm`f7Z=DoC8t!_#m5y|E)(R&TK5Rgpgn-cg+@IJ zn6EdI#rp?IaZ89C7nH}i-;3l<8Ya17zL7nZBX`(oAvhNhE}548pblNA!h_eWu?m&B z40++u14QaRsO$6isq%PSet<>-jJ~z)9i?>seMep7C|hqQ+J|T8TFecXgo0DPj7PcO z;#kyfF}Ziggr|>%8oqKsS;;-g-wNl&%U;eV?*v7#&p@ix`Z<7W)9ytC8H6j$B zG)LHdGaGY=(M)%7bW$!QjfY#8`q-v`^o@F%Kkj(v6sL&)w-dhJ#yC5*SA5B4OTR;q zy>C>`Vhr!()FdwudtojD6)O3lcnc6tgTL3lr|$|Ep{Jv8^Pb>o>4Vmtv}KX5tXq2d zZBM4NGH+(SdFA&c9yI{`tpyU3&*g25P6G8M{w-t7m)X$PW*_s^$`9!=*b;4QpM(7* zqiF2Od&-fiwp+c6Jp>Vzr6G=gz`VG=yH5pP<>R)D#k3<}8_*ynBwt)4aZDJz}3 zjc)ZBDDMC;uN-Le_0D;JW#C0SOyEEIW`6rm4%#=Y|KbC6OA&8~Xx-Woax+nGtZSgb z$9Mx(=evPSV;2L_yAA{5qw4XkPnU1X9&rY_aeKRrcy|1En~aZmt`q6@zU0DV#;C`y z_tA?LX5i=F>CEk$y^V%(bSadlZ4+Acz@qL%)QS(;dYq)0j|Nqrpz=3eGMOW|-L^$q z-cc2>%-sSh`%zi3yim+|lu&XiF<>j90gl{eQ`5%KcX$|!QyG+$+3xJ4V)}dW(}^=E3U8CsAfTW(pXr1BWsvyE0!`<%V=&ZSqm;`q$rhcZlXG~Tt#m)k@OZjTv6 zMlrddW3TTBY=T_pXt?HHN+R!$EWby}PMS2#g3n^zcd0u4M7&jGC9IZ>P?fqWTVEOU zzuE*0xEmnucBYK$z!*U)czFN$f@?9q`hkeV9z}=hKk$_Mko0$4j=*j_xX{ z|C#)2^cbZ=9u&b2(_(E(K&Khw`W+#2HBh%{8LVEZimz%G5WXI6LWDbF;LUR_-w>D^KLD6;*B}^J~Olrei>Ou7n5c?;#z+F2?AQg zP-e=1ja1a}+|*ia<&#-$7TSqP0!ww1p_nd)1GAPYfRb`(65^kxv3_OAdF%zKW z6jCgxkd>L^ICKR3KMVgGV`Ohr1o6ZjP%~3)3s~;&QU4VEF(GCiUO;hVNM_&O$|XP( z5ws3Dpo^#-Z5LV*8R^D~InI&MZ7Jge(SsDd61(wp2zJXzWFWN~MypP4rtz=CwJx_aWKfWi3! z?aSaXgT;I6I1S+CcCGLL8@wqB)&*GLNM;TDsS4)VU&0iQ9{Az3d0#<>+I7Z%_C@ciOBs{ie)= zJ-xb}I*wQt!Xtu^2_1q_LMILmeAuJ3;GP5@Ty?j6t?e5l6|z;6oXNUpXb<&kx_w zI+pRbxdV76dpH6KJ77I?h)YZhv4t%@df|&>$?EWMxj{Bkjwbis)*;#AWZj>mSk0v( z!1Mxa_gKGSe2Z0`Pv8exJ)UE4DvW0oN8iOim)z^AzJv}cb~?`dQb|0($vTnnl|Iwp zP=~9#bW9ncdwSd;MxRZzla|o*g`15~AF!fJI{k(C&Y>^CRuPGX0$#7tIO>b@rZkkW z+YOVRT-U4(6(YD_`1%H&g`$aL=%~e$ zk@nHlzr*Tp!?|sEe;1mCL*?*4;`x zs+C2-=r3K=|JVzH`F!T=UUFO|Q^)C5tei34LLz0NCoW}|N2G=ij2S-rL~PVw zK0J3&H78f~dUs{T_-5NI9pLE_y*)Vkrm8Uge@Pw*Ta``>7P2uX`S6++XbuoQe#?Ja zWB0BzGJ1m$Rwgelm!|(i<#5nX#o?WXxDCl5_+kbrD3zV2U{$mmpHfeSUfa}#f6PB} zOagly;HRgJ2cGWD-7U2GEFa3$%Tfwl94Zy|c0qRi`OrPg2b@m>3V@%3*LB1)E1rM+ zLHp^4f#5o^&oW>;li?6(u&Tw|B*mh}@fQ3|$3F9L#O9F!TZ2-+Vria!-nFxA{C#c| zSEZTQFz&EWM_(B7#wG&*4JSeYsy<`CAk|OI%@dsh3^L?Yk~Yw5Srk?pHB9Y_-6(*uvdazJJp_=Y%jwGnMWR zX6hfkqGn#;@K48UcJM@==J)7vaVmC5V`Ob&ziXHH1QnJGmVmX5Dc&8O%5aS-%H8rR z-P>LgwbncRgbT)?qMNN)99EIfy<7XQM#B1ndzGBoc@U?-JX2uLZPE}oiXtG^pH>B{ zK4jNdAAopC1)d|f9#p!f_`^s`0Tp|_i%V%Lpf1GHseh2>-D;b#md@URD|S{X22Ukm*s`v;ri)r>q;P*T!T7p^DhBeYw76=OpzLC zM!7!s6&7E8K8#HDi!vWw(AS(BO!*G+kmvbwy%igL2$NI9e7btIKeW@4w`#b0+Je(7 zn)voGv*60i>~SSP`2gt-I?nu|LfJqZ8m3n@|NJ@rk0IBF{aAfyz2oZz*7PXv(-3h8i{R z<*1!GJblH3Y_qyW$Y3j>c6RXP|iIu z|IB-EH$N35I(!gmML-O;Lc{q~|O-0NQJYF`eS{_iWUH@zii9VuAAM~}46 zK;o3Zi`;J{K42w21}!gJN5hL$TVAN0)_`)4d)$V5p?{&V1zAOLx*l= zBg4)}rd@1WlO6+hj)9dWQ5MEOt7~9yEWLbBh5B`zVka8llqxh#^8lzJOg9(RO*Tp3 zL9m$Tk>xZZ*y&N&W;~KDuf10Hp9B0Bse@M&FvCk~c4m5_b+s;AkcF-1JDMpQ8t5zY z{J>S3f8eiFonY1k*PZ@?mA^uSIBaI^wS(^06HRXitSydYF z=8E66AT7y~=dHU=WLl7|otfGL88>ni#cQ>tG8M})V1=yvLg?^R%jJEyVD{Jg8=1e$ z0Cw$WeB2NKDb6{Iz*&AV$+7P-gu0+_sHP%aB9i})RNWvN0O(0112 zFf2;T%Tr5gN%GE7R#^W5haIeh!f%T$b4N07KF|suqE>u$i6pQk_llR00Gl-h4*Os3 z8rY_&7I6h@KTBJhPL)QgC!ITT!cu9q;OC<{V-UQDWw@GgTy z)~>{M`yhl0p&E|fyF|Ca8f(UnMqLI=Xqk4LYZ zpyh3<%{q_RQxQe??H@Pi8Qd4}I6X;qvho{Myf!*?YDzAZ0Xbna#Wx2fYI~^>IA!%M z#D39DYPZGP&EGBT8PU{SR)+FRCs-P0Sdm+im1pBD4r-s-ZjfQ?$2K);^Yp1&t91cm znKUFLgMCv-StsO$dul0K44%`=GY!bHm=uu_BTx|!kALgjpWLd_NdekFkYv-2&eL^h zA<*ZOTYsPZy&BiHjdCuE**>St*ce!dZ@ z^6i-H+qynmD9^bMQ&Xiw7GHgkKDe+ITXE|IaM0LM+nXR=5ILEY`zNkwL|Q%P{5n;G zrUgR6+wfK~8hKAtM+DIbFiR%t4j#%Lyii;-LLtfjT8itHXuapsHh6;KkcWn7=!bSi z`ytLXeTIW%50D>#$SszJ>Uqvm%Xmum)=x+h`%rj5{mCece%UI4mqUYBm;Otuv`QUa z3vghpb02B^6r0L(>ENQ1?0kUwE0A$AUXlU6wENNvonnsjc%jhfHoVEP!an(`NFvd_*jX=7Eo2Q9v?f z2We|>irfCynK~cf$E@I#IiUR)x-Q~w_pUHK#Oo+L@@qHLBMl-42VNI@m`q!y#|{(% zX$XpICEJ$>9~Z2uJ3aDVH5VLL5kp7WMLNickq4%Woz~o8zKsXns|I2v)@9pUG!5zb zL_{>L^uW}e%Rhx1FYG5RZ>~TeuQV*-p5un?8inge$zRk!cTYSxmoVId5dM<8RGA+~B< zXr42?u9k^wUj9q$3g?N9BqGIfp}a0mK0Jx1VJy+-9S9 zg}5AU{zJh@3T{SbbL3;)lL^pi1eGIsf+6F9MU4rk*^!N~6m~HkIj; z`m}S2H8vh+wxdvXX%$kxgZo2l1QVgC%u96orP*30RQaVWp}x;I6j9;pM&BxEdJWQh`F2%Fw5?cuuK<-{J|dNto-?1JES)%Z@ae9_ImIlRj?&Dk^C5A zi-BTLW24rx-vYWAF+DTew@T4CS%w`fTnmvFJuYb-kisTMaYts=LhRt$ZOZR%hu)MQ zaX1+ff0;d1gSlPkfh_SE<8KX=5GU(SjaE|E>c>Ya|MHxDufdH#7R=cBM_2!ucX9>n%u+ES1Jr6GN?R{SHKbyD zC7R-0=;s9#ez4s<;UR!ima~qF<)vl-GQ$;N=~6UAo!nLFVf~3Xd0uC*us1@MrnQWQ z5i?9!8*VnArQA-u(U5XRs00b0ph%T_-q%x{zHLwHnTl(UBg zZeEU((ONP;z6XnGNDAU1tEzMDehA>}F9&8DI34QC@K)+Gv~M%iN7m8CMBfp=zw#Ig zkrn;w=diks$!z5w{uP!yOm{S_L`8(>hp9=#gAhLe7@-rHV)purvTP@yTKNFP3lKmH z9sToJHX@1#j28~=ce%O8e!TGIRkRKtnH?JK_7U1)&!>_v4>)Mz|7Azgri4LZ573(2 z$Z%-iaD&go6$vSS9pAdj-H*iC=teBR1Rrto&JTnEl>Yjw!X@lnfCr8;uBNB|QO}nSB_d z|59ZHehjz^AbQ>AP(uVH$_kut7{xm^&)pf}-k73c{arY<@Q)owQRoZoZa#SWl0~J? zb8+F>g$E#Deep>Iz@D+V7(GP2Vl{c7|dvmL0Rczqc&kyg;;j_-sj!%I$x*Rcs{90@3#m5Y|-5(c;ho$$+N5pgi#^Ro{4+~-6<)-s}shISqfN>Vinqff^WmlB`L zx6k3VkD6&rU5zeUl7C)HpEnD{vLjf*$c?Uk#9ppGQB#l9u7S1fEEu7P_w@Dy>*-|z z07?7JAdn|tWD2k>V~iQgRrIG~1KSAW%C%E`g@)yC(z!ycGTwH@K5sW$-3ziqb5~tB zQT{Fg(7`G|DPv%*h*u#NG7`%&2*#$3hb~pFF@cC##>H;YgMF}!gg|V9npVYEJW_q< zi&@~bATiywoseSsyf~J#jKd|PL5bfPAHKWpqaV3njK77hWsv8XvnO9@CaA4*-{WLx z3s>%|g1EgV+Ph@d-k!c~QfnbnfY?VcxaqbU4bz>2vU8ty~**FBa$eCxY^52y5U@V_AUSvr*VbDwdCZ`pc>UH=6BSi!h zQDWaK#DQA4=^82DMdtLCpeNM;ejAfyBda={?D%Qe0gaH3Wt+M{Hci1pqO9PijjIY2 zPs=8lMYv*$Q25kUhwnc}ee_K11|g~$Ci@E*_)TLq8G*Iin`n#K*#<%<5<-*;BESh5 zeXoVQ2r)CLSCAab`^<+BJum?g!Posy8VLZeDY1`F)7}B%tjAYsLz%)#SejOS0XO$t4ftbu zA!|x!ok)OoM)oaXg(Krf0-_0P2JEp@($@hv=Et9KFx5>bhvvT2_Pl}cRt{M{)m{rs z0ybUsgTT=kaDodjL3wu2&B=*z;3jsLl9w@SZl-^im}>>W?vZLm3dp6FUF+7o?uIS_ zHXoS&-E-l3M{%Hj}})<%4?EM{Hf z3ZAiy1GiaM73LOKB_>ZY^use9 zdPCbC`r0#yu5^i7wXWI!Tr>fO-Fia_EWu1p#Qx6opSm#kVTe?$%$57w*8MsDJ})8& zXB1rM+>5u)oYP)?r~X@PNKbOWT+Au>QI{}7*s~aQ2>yHT^sn0P6WzL7eyRFOrtq8c zJq=0Jm0*fn7d=Rm)R{O@w?G-04u;e9adXr@=c9Y3z&gVX08MEp`3}kq_$5J2(GtEf zIRAZf^@1*azP97=2K{}~D|^rJwCegnmyyjKujr;9TZ0!|z){*X;;ah?FTqGbEw5-h zHE;Xrai{^-Olm`21TAA)sAyQyLLDb~=tNu~en)PO2Z=Z9Uah~Rq#uVW7&Ih5n?9E* zeX0PHXJdiQ`Hb}bIWIoShmKR<=YFoBBAu`W4hSlf@Iba<9rSREFT|#DPigme)Y-K5 zdlb_=74@Wp_=VUhBYt%@D4XXCy|ZTrqsIN%?h$Z}~9Mz~^6%2^nGI}V; zKvGpJ(4IarGQ78%#EhvliUEf8vqMiNIqs+`its}<`O!an{#FgfG(1ez8dPmxFU2vXPfDH`Y6T=I`#$MI}*IQgJuS*1-o$=Cliceuq4hK-dOaS|8+~3Bq0l#K{(m}=xi zmvCQ0i1|ri|x`-Gz&U}FiwaoA zdgKVEfZcM9ucqC~MJzUs3y{)E@1w||+P1MQ4oxJ99^lgJ43Sv!=YqD20bONb^%M`J z#BkycpHpimN*(cs)`=NbIt0)0&!8@h689jpxzA_JDUzeotIf!ZXPsB_>VtNBr<%3)ZuYx_9Xshc$ldJV-ODZrPd z>}UzvhstiPK$$e$>?}v*R=}&}wmINI{XT$HC++eHVDGm-u6swLD!Y{&z+ZU`66BVI za$LWh`>1{(P?Ae3ahKB;q?nw;mm~Zf1qGY+i%r9yMlD6H{jg*>UL~t%#Y$Q(Cnjbn z_c#=6;cE4QPg*{n`pBWoGy!UTZ#aSZ+)J}Y_+i;Nh>o4jWS9uIDH_1Is`;&N2EeWn zW}cjcAUuuRZ4KZStC)p!q`?sQR$9?Y)Y&O%R8ZZv41G_(L^u?A1RYknNDz2+q8(6f z%&}X*6>$vV%fc$FXYKlzS3!VsHHw2R?Ym9MTo#0_G_rBIZrqe0z2mWQ!5%ZM1HMR) zLB*~LPipPKtsW%;DcvauOK7&2lG%iVi>l^%eAL!0==A^`G7fV7m@xVwleCmjf)VYR z73k#5Bi%g89J_EbtIPWMb>dl_dIHa4j|r>kj_K)~)?hq4Gl*VThyZ;R;G%K@;TY;7 zaNv}{Q$Pgm3Lz-$gt`0l+RTzsgaF`x2#7$Rb3`VV#9aQI{WgYG9to|DyNg=?vq(1K z5eqjyBE&W{3>b$mu#d@8L>{lVVaffP`nFXr2WY6=tBiYZ^ld!?T_Y@xd)_x2#{)ON#j+pdWolx)gYbW$_ z$!7ay{r{X^4ACzH=r2Zi>PT|xe-2YW@#Cmro96rST~)K3Uqgf;#C-={FX#O41E$08 zMsrdD$gWiKP`l=wgfQ+Dc}^`LLW%adgr)C{ zUb8M*Uacale5O5lx)6`Ja=PqEMfp;D?`(pB30tjuG=IA|nzR zvP=}ce`+j2hptT?{Wqq{`2wI5i0Ww3{BQ}^=BG*S=Gb6w2j6F1Y#C6V2H@>(_l%vu zsQcfbd!EBl z!zv7ne@;a17QhCq%2Z+7{6+%OBBR_O=ftQr(V`bXAS*qQ2l+MJduidRcsjq$RCjOa zTYa|~L4znk{7U(gzAW-%sTnHb?+l1uf85e8L9KceJR}y=Fx3TSuV+k@HOb?BAOPj7 zFG%rWSZwnI*sw!DTen`6?N*`G+q6DGd#~&;iE6!FPqn6#b`mcQPL=Lwb6cEhGdTn!|*0e>YX>nD~i=Q!| zI|&YH7hK4(3{#?Kau!rp;*vd$*cQ?V2Ym0p-b;sCv-en+>SGf`317Irur@oj=Ql!U z{^3b2eq$Q+A6s zUtp8_nmx4z#r>x*5VHRmw_++D3GLgd;w{a`m3aSnys-!`toU<+2ixsO*L|3h$zAm0 z`f^npvne3<;*}b1 zReGe$^W?sn=xd(3JRY+*2-DE-dan#v?&hCx`yEDP^#a1u8oK4@oxq{fINIWOmfyaW z^x#R;-CO`sDok>h4LMz%SZek%sOZ^ePd)~WK_TUym9mlxFZ&+MFfFO@m_Ji3F!^)i zZOM9eQeZOrLK*sj&ei?bS8eIfXK6ot+#Q91b%MbH!h0{>Vt=jewPGBJ~fK(yaVgVtzAS7!>1{ugCm z6%;10oIaCZjR!+)x7)qS{i>zs%6 zvU>Nf?%qK?j?R(;uNvU4}>|Nzk0<;ct)Wyx|ATG}kSD%vWwfce4 z$c)%tF}sW*9a-dP2_`_7 zb;+7+)XhzzExTswwDV^K&81Z2;Pu37$^!N8HyO~d{pj9Y<=AhpiqE>mJTT6czfpGD zuk`FQrd6SakXNxD96OW^)DTab6$PV-LNlDemo^VFn5(7WR?K|-ZExW=C9YLNSJ*4I zpAvX!EE`KG)e2QgCs@G1bD?!RN!?|E2+4 z7IjDDi-PLH29~*nGezi9i$9#Q1tUCCfYJ?Bvu5=xiR%+cv#+aQ?D03~bDe!pTUgGp zexF^i5PXDl{&u`Sg}vi4he{t*quSA^VpdjX2{sm7psFfx;k6F<3fw>RA!$F|<(WM5 zJ)P6V26MqFq|x-INoN&NK}U=b)rXP;tN-0>uvrOQ@oWXxekLKm(o-83Cz?cx>ah;zQVD=8#@2 z9`EoI7B#0V05&oLOs`9%agGdLi7Nyk_{zv73HgPo7J&b!6H=*QC%dZOF zJ5XiiY1fD9F3Yt9V8HV{N=?&m!#RxW>Tdik?@wp<(Rk;Ha%FQzfKY=Fp>Gv6;;})a zwCJx6H)@C^yDpzB)E$5;hcxG`!QX^6I*%mH&w;XoS*f*?GIojqu|4n|TX~xCs5YQT;XJRldfsF>YG4^jeje&cIxF|cDYSJ*WIEA?)YqY@ zGj{60PDqhoHC-^^VUicevZG)O2CD#DV&mnuH~*>>m&PEm_Y$CgcS-D0OHb#D6as{P zn17~jg#wTTa^9-IQGy|DNGK0V6*vI0m6qeoiw194>cs2q48>|}csNz7L4d4dbT<0N z=RX&cC5R!)iB$?Gx*`$+FW-|RCYJMShm-vUVAkrU;v{9#zAU0moC>ya6x5GnJbami z5sH>SLxkAkFu71?X`pu3F7>Z~&RV*t%jJF-ATV4*c(;in;GrqaxtJTnZO(|@9sRT` zoSV#lnER=37fp$UwXwSesUY^vYnPtKsOAaI?O!kueFcL3i>EKIz$?2jCq-{b7{UA6 z&qDC8dhkIKA%DBz$H8%`3L=@1yfDX;0g1rwJc7%IOZ5HG=ky&vi9}8TcvnhS<8;Q0 z>V2hpZ=Mgh)u6YGTb8`SC7G|dZBAQJAmGv%}E+uQOpxeavUb!z(@)tUZgT^QsBK)i-|>%`V+PU6$i+at&M-Tlk{E(80*7tV!Bo$`m@4Y$|? zLIuTB2pupR;kfWF7X!4&IzQm>YDL)0C!=JB4Cp*1=Y!Xpg`6%$KN1HU%vV)Q$L)Ha zpc0V6GkP7*H1V=KG!>r;NdYk&eRX3c4v1!LJ6?yp^o&)m3T(H(grDt>q8{$5j#ugj zKwjQV?q7$&RB!i#61UB}1fL>z=U?2p{mPrv4UCB<6wP^1r01bZyP9PmG}g2P)~^7Y zC|}S5ThpCj0XtGm+G@0ENUH3TnaJKnig~!Dvl>AI^p;5X)PP`wpE_N7Dsu1)d85@^ z09%|MbgvPI&bClf;}jvvVvRRxU+Jz#_mkfJ$xj=8wM4PP@V34Qz)8p_|niF3^%li1TRg_iWbK*GVp+#co_4!KvTmx|l3hLArXB3CjH zg{9`$WzzW5ZpzXs!YY5jub=SNKzg^SSi}(AzxSrs9N;fkh^HSGJN5yU(U%o*9;lAg zX(7IcNr^UJ_de)evT$l%Epe+NAcIK9eAO3afOX_Z?0T1OG>n6FqAvkicj;aCWYDBu z{8~|^50vkqoR*L!T|9`WM0*E`G9vfx^ZH@Xe%pE_w>2*|xL%VeT@rXbJVnq+Az9N% z9}6a-;wI!CGpiGZBW_%bS`z%LOIeE=mXPPtx*GBnLA*;SU-^UQXWJo57;<>UJTXH(r&z45-+HXj!< zp0Fw=jz_bG4bMMCx4xvN$)#h;m${Ur_EcKp$doBBw&sAbs7jUm4MVP1Swv#86&N-i zz1^D;!SQuv-=pa<%yX;X5k#Kzqxpeao@eu#%BQ}i_7-;a@9MwW0Au-w62 zQ8fD|k0k!+`>EQX*9Q$d-|rIy9rKwz`G>yzyV2%kD!XEJJ3?4NZj<})RO!kxD}~v0 z*`B)XkNM7$fyS(D%f3~rF_z>wW}Q(9F1$7;mkcZ8aF*&@lR zIt<7lL~qN(hDs1$ilziMpdBh@POHuXe#Xu!Nbh;tSBKoa9$5!$`*Grer#Y<)K05|- zTbtx>(}aB=8@(GF7YFPY8@l=`15Ts~!bf&fgX({u>7KyC%Lcbej7+1S8#xur`_w)bt@YISd>7vYHTiD0 z1mt*Zyg*B?UhkPCp2-%n6M|z(@c<-ZK|!TtUUnWx?xEzBP{2=US&qk9%o}-l{z~DX znW`YF(|}aRJc;B1;02EjCS;CkFW=>n5~D-E0TapXxhE5P|vg8 ztQUbJN^``6emh!6>?TXEguU$u(7fqB?p6NX1K(|9(jNSqJ8QgZmZ&|`GpRf8!j0zi z*ernvij38pXoNwY;7ygct={rlWuS8G!%Zp7Uui&TgugFXA7`pMmv4kV!A0nd9jgW1 zpw(+l4Hclvw&2OoRLHdAH7AJ_T;#$?QI>SSf5x6qqhi>u_5KbUnBdckDfrl%{_o4L zBRqsZ_DJ3WG|)hEF1c|#Ia}<9h5g-^daK_!7U13Q&z>ml3s`^M)Z_yrz5BQp!;Jo9 zB)R-0@=pn)DMf@C+M|}299+f{MF+N}1K`0%)~u-1WHXMhX0;^*E#;eQqG`OJ#&O)) z{2X1l!tB%zFUfg#TUT-j*EW5`f{Dn>qmP%l$atn|6hGqGf0dHwkx~xH-aUwZ2&Dn& zfIWoH%kAn>0gIZ=`h$Qp06}Co{R0XgQmhf4WLxhK z*90$D-zRj9wzWf)FK~RjAIsl8kEyD4us!WP`u|qY=Jug!Kwx_D2`Q$C4EuRfD5I91 zs$@s%KO<0kiwPV<%5)%{kh0zIgx4SK64Fwu-~D~?=I zF0eX9TiA8iy*bt1QN=`NaeVSA9eUF44!O=7xcoWvA$ttxA{9xVLn`k?qlegZ2s-3m z?=%1etWhE-iJ1e#m+d#I&hxuKp%&{~aVs0? z>$bwBwua%Glx`zWX@k}VjTIFEZF{xEcO0HOwUs4sqn|blk^h@y+r<1yKZx2C zi9boiX1LyBj69I>>(`8+G|Jy0xiWCi=f=V zZzGXN7Dss1;WEIW_4k`d8wM@Pr6QyVcK3766UXE#Y3Av2J86+QOQZnYM;DD0#Lk<; z9yo}+uvDfjI{kdBtC=n80l#z%Tw&%YQ?e&Ry`NkfpJZ`lcj4Q-z44JwHmBFr)X1TT zW3STaL!Nzdr{~Q0J~x#Y)srH%mkRrrKfPLG6>E<>-DfXOp>2-+uE1xLSf)X+R9Fuq zyD~YeE%`+!3gqyw4rHUXn}pm7i!#+pf4#%KPKQMJN)!-SYYD*i$6NLAwXG*vuy+z( zP5RV^sCu>rLP-$g{0aM&)oN|gf)axy6NE|H3>Sou?&6@taXISZ2nzp>{sfkf)3}QL z)Y*+jw|&a=q!Zk{l5zYlE~OE~9jXG+7>DHE1>SrZCq;wv^R{Vx_<`N?y<<|@6}}I4 zTC%rsDZU)b7!_&al5^4s$Fy;d3i_vbahbr*AU!P3XXxpM7ln3hM>PEf=y@wz-IsmI z^wd)VE_QSNLp93>G5yJS`o*@SHC|HtjQYT1g${=_T#eR$6CNH%{+%3Tgnj`C=awlb zHQglYrnKTYZTcMbQCR+91F~KZ7$GkAihr6UVeTRXTo<@5PurKcbfWufNtNvfX;J#p7yy_#pHYG5sXZ zzr=^MVVoy$@}YvEW)KW%6L(Ibg|;|PJlmj{xUw3V_gg$ZCVV+3FmxX)q%U)&%BJat)rhiR&}-7Dn9F*?5p za?a9^(z4b@fVc6TcH}r>h~}joPq;aD$9$%a(U^kEp!q8f{khOB#367-ptn3E^V{?) zA3{u6lFH&}$t4r>SNK0#_(llcBIiPKhHTPM>AX~i*pApxIP21mQNLloS;R+>&GWc4 zM|ydrpJ-G-vt2fRJ`FB9i%NcZ78P{hDI26HyBEQ?AJX#brQxKtoLZiKvffJe?wWR&(?4Ls^v$hpfAy;eiD& z-9hB|q?hT1ccsJ{+JT1% zirX_8mhsate#1laF>T;RSbtL!>!w1~_VB~RN*~0%W@c|jRMl46t{b%f!ARWsJSl5xR3*Z6QPFnRu@H3{{Rmwd~$SWDXnRW>e$y-^K6y%+~P zzKaZ}d0{E!VbM{lgt-yW8HK32^Q^IC`s~HJ-Qhx5j14yeJ2Ey&;sKKBY5-UJ-V7?z zUOY;N@OpF<3T5zO^k2xRH;;GI8leTb+yK4gQz1rI7fxj|U?>x>tvj}#&h-G0O&NHN?cJ*% z{qgbrDUaX6i2|=MNZ&Xtw*7=V=Zr_5>Zt-A-;d*ST_*_nZ&`!$-Zwxh;oWyS_6@EY zv~KsGc>4#2Z;j|89L2`N>gmA=4YGB<{}`+$N))-3fTPy#*SlQ1k8D8UZLynQp9h@+ zF~U<)aF||N3sFp|1`BdATv&s6L@~WZB1@41*WuxYj}%}zUFhGTG2DRVzfmE1){E~R zt>4y!?wz9X2TD!r=QnYaplSGt5$G3S3cg&@2u8~a7<+9sUqcMuhyl9yhA5plDt?l@nC%0PuT0K3$e zuDdaD9F-(+r&3Ril8v~0PANoi-Mx9X&ElC9Pc*u+V3>E#e9mzwK_Z0NAA3;h)6S1L zn5aG2wiecdfAld#TL^^L?;K*H4mTjw`gjTALkwe+yDbPyYKa_J<0Goq+PW#aeAvZb z&Bt3VKpN-Vh8|bG#XLf6JpQM-_IT~A2!G_spp_zkSf}N09_3)vr(z{~ z05Cv*ps=3wUdcd7YkEv{H9H@8a(lKFqB&_7{ym{by^?K1WLopL_mN%qlE<5-;C3ik zs!fG_sC(pT4`D~hq4NRZptPaL{-s{dX5eD$$<+;{Q9i$RL+c5I$E$ssC90SX&+70A626~6#tj`hUZ+^uJ{N$ zU2<`-a6aIIV75-#<7d?fyaDA>qrW12kR55asADwKgyP2EV?>pVqgAbn$lY()f!S*8 zAGc-4h!PsB0v&AXMALTce$%x6tQ!Wt^D~{S6<}`SKAXu-2gpAu!KVB;+Z!JayFK+N5qFej^>s zKlfZr>7482w~}?vp%sOUZ@o z{>t}<^^_GRsPM(Ya9G6pckWV18f_ye9$lY47 z<{X>FOIWN8)#T;>pkW4a2*0h;u*p_c@ym&(b!2#Ms*j7uFh&SjhWiPiQy}B`1=JYGhD!Sks13m*m!-fu+`6(~ydmi}9m)|+6V!rAL+J%d$12D*rxmIv4 zM}F=nfc)GQyES0VEY&@^A*kcUv*a+?3Ugxrz)g0yR(Foi+(7hQVmG)N5j+$;H2i4f zB3LpyPMA2?Vk|K8GiE-s55?q_UTNL^E|TIuMJa0k0^~5%{v5u4WB~hihdRV2L*gne zC+P4nLnQrpBBzMJXaolW#}%WvtV}5y|OCLE$cYh(kDsOHpCDgEqBR) z%WWa>rPKd8C>)~Lx*s@@Tu46DZ_1SuAuM5>nIVmkgocEp)X_3-S^e^2%IAqC^Mt$A z*j8eR39ljQ2q=sqpKDBA{az?;;}q0AjYR*$Jislwv)fnI6C$8I$hqQH_~SGIIw7th zT-!ckpF;!VnXW>}cj#VyfQXv`wRCJDr=OJ1U~ca^&v|SCBJI+|3%0w4P^OMMI+_VQ zp;rpGm3_29eiR~(2PF*IU%?~cRIcXj^rw0rVrvL zyM*FejzVw!pg4*QzBKx$l!cQ9x$T7)(@MbwXn5A8Z&&*0I5%F9TpLIiO*e2g-SXW% zuEm78e$C@&&4Rg}x?muPr^HJIhust@zE8u6?Ucd!s0JG+z_LFIj)ELbB&Beq{1UQ6 z7_zioUHe|fb>yiGlV7AoSo_^evq@vGfuQEkje_$LxAhttQtnuCGRShpjpAxX3th4) zjtIC@$*^)NeI-3iu$(Ty7I+Y%F^?R*{}sgUX^Ys|b@k~E6aiPp_It+l`TH4AX8WLut##OpVpVGbAtXri@|;e5aQom}I^8fff&GN{x;U zKJXa{6Y%I~`y2e#gD9p6K2Y@hDnQi70a&IQYk&0GuD;I8#XFyk@>8Y46#@I9x*gl` z*#$^43=ACUF36?+vkY^wHnTVvZK-4gdb1~^mRJl9^(4$cZU$bWGpzi93+~Ppu@ick zsWPq@6Pfda^d5~ZhBaTOL#-U=kC&CQe7sEEYUr;Fy8nERMvbJiu|d4e9W~xY}Wt?Q1F#>!`ZLtCQetNK02l-?iU6!%I;*-G$+Cv&z^T>ZPpc*&p>)x6-%B+nWsPrpyjc8QJ?<-Lr{tCkgM&DvDZ z5}zwV-jjdAs7c(A?AyPB(3?Ug3^~*M8d%1cF#vr~((S0+QF?m>&sTWKAzThQZJH1_ zNqZ2xR{lhhobrvQoim*}z+VWICpDixkxw@G?Wuq4k0r^J6_4YMAM-Jdxwn8dyBC9J z7r=YQop=CS8fstH=TMPxZQETWjQfkC<~GX^5s-mJXT$Fh$9H9?-1>!(MJfwb5pz}w zG%B-yf~I%i$xalsIdc2#q=@ySLaA0k0zYh3dBbM)_az5PJxT)Y(j04$^-z<*Zk%*; z=OA7?et4k<$8q~Wxg6%4nH5+c_r(N6Yz6s8jXWe*rxR(r)oRdlQ#~1jCnU9vk}P<= zNkMsnpu*)Xm_0q|=~rax#WnRC1&}RHL#mCao~K`nzg(7@g z`7HDycN50^L&VqhH&T;DFN*e^zvlv0@?DPSFHZ8w-q-8kj=Q;ltp9KY|91pP0k^!B z$h)51B5vt0lbPr*w?tmK|K@dFNCe(n`*A)vjg9V+1I`Ay5-+*jQ{Bji`#*yFcVTOW zaJ-XZwoLF5H`)fM$|*VT_7%JFp&Jwmtp#OJ04)NZ!DFPQEv$`TP4o1=nzNqoUzVqj z3zuf^A{m^xPcL{5Gm(IXFVzcun{5+OU9k>-@cpzN_X)mt_z^RR8F^+FZjE&Pk={#CqGOLlF$++ zwGnJ0o46xS6>v?Ix$!HXF|6~fFp{mZI$@05&#=C8%qP`AuF#;`Rr#tYlkziSef5j9 zWW7=QrW~~;jBR`2#RescMIB{g=1CLlf>ssSi!pY>j|`=0_U%@%*b7*qw|mNeChvMM zHeQqD@DcosezxGEoEVl=2?sGzW`y-f{j$|%8z%Fo zE*dB5+~^VK_4t>#C=~lXvYqL6Q+9oNb?J|ns9|Q8TF>v>hFT79VNJs4Dz3@p<;?+E z#tr7btRwyXav#&|7V=4a#4@z&4f(328UJcEt2$v+2*N8K;ndZveEHoT#Hu%Okruc> z^+SlooD^Q=15)r!P0y+NZm=lzTw;~9c7-GzCvK3>pi+0+Eg+IXF_WN5GWkVxqvRyC zBaa(__OA}LDe@yFA`t?qd~%NiY4ouky{>fm=Ssb6@MX%H9trI+gSfo2ZKbVUs3&oNBSX84^1DUeUzI^m;&qQ}wx+JtAB>C^V4=V-BEd`$sa+ zRXoK75?G5t91)Zp3jce+@{<#ITHnNM%a_aN-Ozd7FJ1!@A6Ka-7AG=7jOBeeJM5xZ zyT9)+6s9#U8DfouQ97ia{1IWvOFS^z0~2x-S4DMaC%~_nUEF+UB?1T1jr_QH8EWlD z4Bv$WR!*o_QUf0xZvE^zTGKMicx@3SbH<;1WpwKH``06AclU8jr6+;e55^ukj};Fn z)g@j{LW4dX#(*K5!oQ_Ar##$$dqA)8388PJ zE^=MFox3a!enC0;*fAvX=UDPYYiRDy8 z*lqN9pH4XqVFlf&UUEL6qTuXofCMKyWlzqLz>$gOw8`|20=3;&S#pLrL!5fLJu=Tp!=j zlRZgEp#Tt%2N5d_;?#0ivR8ptD-|?+YjjtOEI4h?3$*Fb*7LcZx{Y+`lRDOfi2^UL zYP%Xc-{}S+veLAyc0x-(E2CGrmrr4$fz(NhYwhyQSIDgk_0-RX{zG@3%I)u5d@79E zy$PGos~)QI+%Ej`7j>NqxvdGZ6VO8j3iOLXniV|;DcD4BNXah5Mc;0#|kwrqxr9!Hnj6q7rCpp@`+?Cx&$hy zo>r&lap)k$a&SGBzEgbE-Uym`(HCA}owZG5c&!D20b;MBZ>1%IIwIS{o=6%@Af}Gq ze^x4c&)sNJI&Q53>$8@Mdi|{3t{mw?oNYr)sNqUz4g`3~c(Od<&WvmrQqM>rJnQ3z zm9H)i%^~Wl_$mt=U20jp3LN+1R9WoOS?j@EH7HLnRV z4aqD6(h!mac*pmn<%B4Ym3fib^N)%X;Ly)r*qqRqb8{`2>stWKXv$eE>@r!l^uTu-;B3{Kc+{*}R}iI?f$p4373jxknGg$FyBBaM$7)6% zvja>BK>o$nolf|g1x~sDo&C+VK?jyqE;MT&h*5i^SbglU(!-M+d{gN4G2%hiEYP=* z%utwPn}7V|)fSxx6mR;ol!+j;hs~S#zDJzf%SGz1Gqz(B!PXs6dm!hmR%X@QmlbyeY*CNsc*+#Ac;2E z)diPOyoc}L_b*iUYiJh_V=BRWa-LX-E8s9S z$ncWTg2;046P>w)h37v7i0$CM*FlnhJ)+4(moLpS2k9>s0yvyBNA5Arv?r*EuYR(! zJhh;zzT2a>CmWd&*S(Wf^&k!cA`1N#z(+v`Wprhb6-kLGv;oUm$zKSI50m-z)MJ7?T|Lwh*0p40Q~$(Ot6jQNO)XXd zQjeyX+W+7Oya_c_B4^*-5pBX3OC!_4#Yg6wZ2!{q0Wuher3g&p%x3|Vn*?SpvP(SLCO1jJ+lDewGAlBn25Q)$8V0f{g%0eWx7qXqPVM5)J)4ElX z#H+lmHrE;ne()#cY3vnk+nmYr_JlQoEaQK%tnONBkGn6Z+B)Tah(ke_86=-cJc?K3 zpIGl&cdV=#ALZa>@gjS@{2OV@W|&PubW!*i2OF$a&y|Ae1zNCmOegvVE2zBi9R=fE zSAejY&<{KlWmtVF_*o;Ziy%xVnFm)g9y*VJ-F9a7!A!}7o$i2YdQnp)?kw^3eFRS# zr&=HcDGS}dh?K{N6{;Znr|gVD$I8;}DT`NuVc$VOy1H@)@fpQalx)$zaj{3Rmm z`eG0NBGp(l6iRFl9eLEH%DNK5rjb#<4&(R_&?Xd?aezqG)nVAso0x}{VMi{x1RF^Z zt13iAKSPI*C8&vJ62^$He*v0SDwDwcR2U;fF~(bi#&#;zafXG$0lqf7wLXBFtwRo{ zIv3P@16adO^lyV5-4V*zo4H86Y`!g`UfJPE1*@oki_v2_ac(#R-LN>^CO|QGRw$Gg z45V~C%Rx0VxF#3)So~FCyb^H&UcfwBiu1BLTN;bxTDFe{Di2mp6x25`FZe z2hkn>SN&2!m=@h%t+3$77B~6vY&cC&y1%#32Q%vjtAEYI0^5M|NNPLwd(w+P`@Q5Eba+i{d8f>FO@eysbsU(e5q{q$MeU?IfrX!|h zlPnF#J#;hxMhLri<_HnNIYWCCV zII=N0e@M6nlkIDh|MCLa(pWYsEC$v85Ksp4NLFMWZUc449Slwui9{o@v6x!pmXWz? zy3d&BPYVf~@lc%yL!?8odv{U8B#1DbwwqZr!l;`*f)h0<5Ohib>~rJu<7`PCGJ@Gy>M)SCK7 zue|sZ{`)2KT?Rcy(ovZd_8-^c=d%|-LGrY*;1n60TTou4L}mwP$IFEN8`pb1$7)E) z78X`z=ereFe&W^YFbqP(CC4l}n!aDVF>Px2q^S!Zrn6X*Ck@O9{={OI=$a7q~{Uer6c zGh-(=FIHM5;^*7DuAs*$tYEL>1n}XeD(F1zN=+41@*AwJ4Jl(e|Ci$RZA64`Hz)J| zq{}DK#0Dkgcf(Gp*It%&_Q5O4CIZiNFIc%2>r=iRB)X$w6R)0LU!C;$65WOHhw~=< zuFgt$I{4B<8u!K+yo@-}?KioEDAO&CY6`@iDBoiHEwB?l<fIc_M2{9{pof{9HFG${r>owbIaB`q^XQCNTKIt8>(*%rf^IoHDxae?PzPQ0 zWuWhh!HDml8npv?uKSPRojvM&I;h2Lcz_MrPO1>{>L*>$a>)?6%;m-mB;j z_#QLz$bUprG95o>ZnTyir@QOnPF)?F70pgB;alm8Nt58znum z#JH&o_c4^|s3-u=YjE0?rt|&()32(LTTy=DQbID@+EN|9vCcV~SJL!)wNzt%Bf;G< za1wN41rRZe48{U2nhqb^KQjbjTEELu>}K$e){@!j%8GQ3)4#9A>6m^5GB;jmaK`x5 z+f)&@nlNY=Z?$$sU-{6r(*CE13>_e@Tokfpn^*%-;841MhUvev@8Te3a08h4YUh(> zl$K#Ohy8y#Hh)ZG*nXJd+E&G8n3+g&KO84Gvea~%xaJ44F{3YJnXofoJXf6ANpK$d znWJhhym%rWy>RBgzp<0l^Ha-x(Xj}e#(Dft-h%|ibk|>UU28%Q)m6EZL$VzrTZiU( z-}c3hAQ-VvYI%|2`o@26vr49E8vP+!ev3?N`Hpn<$0 zK3=i4+myy?>vxYi=khtX+ay2u+Fh#F%FVrm?PjlgGDX*U6+V_WYm_gjSTEX9`iT_6 z&DKVi`pt+E-;y?(=DMC1u{^@9siEFn{jWy#eGUZF+6{nJ|C$iLe$f0ODXYNs$mHJD z3MZ|iVjru5WA?{Ai9wl}O^@v)Z9J_~P`o>ci)O@ClZX0`l40rJZmbPujyOMu9DEdd zn==Qu#&ZaCVKjNcOV77*uITP_x#D@FUNXe4lCfjqv#L*Z`6qDS69aPS`TH*1GB^5%<0TDE z3Pf>>0v-48#m)Qh6Zm?4;OV?rKUThP+Bw$9e@Bc&Rmu33lIm0M1XBwVd$6ma*xXT}%cw)GATJU$;vTf;)J&jCCDnDnU z`@J0u%`8mly9AAGF#Tnk_&b`JP!l2^!;9!PR;-(oyj}8C<@+|>4<1T~j=XDO#k&zv z%;6cn;1!0&T$+`T@Mz(%7z~$kiWMi#B6FH*X&R!&l=3K~W^<1-(GJ8stO^Xujc2zP zX$%Z_*YXkD@%m3<2JA6HJ*-|oK@!U5pJ~~mH{yB=7 zKNqzS0WhT^lV%RahXd|6x_(mU3Uk&10Nd}hy6s|Th+#zR!(58-X>+s7l2XhHxOWlh z&`%n6GG)D4a<}=kaMAeblrg=V1v{4Ac($U?Q|2Ex5A=LoDdX{}KCXyRCM1Xuoppqp zuyarArB2k&C>8TYUC`f*-G>?Hmn1;QeQxn~+|^!%K$H=|FOjcK77>rwb~ zZISE3+FHFSr}t5dl!Xgg%$~tD(UVZA%DLk;^k+a8V_5BRTIupN1;fRQiO7(cZpU{WGx?9Hf5Q+P-u5U|MQ0t<-T9nGawSQLUV0W z^{`(D^Q?xeZA#O3?&WOX$I$Fz*0@?7_wnA-=RNXw2!W|CAMS+ezWv} zdP?gLe3!mj43u|qf~k(dizmpiS0yn{ z#bG|IkxPcaLvCPsbK!5)f5nICu+tNx2p>l96OKy#Rz#ZoAYZ_rGVB_Uhlxb>i?Jhp zV_ZMWBCsAzbiHl+59KXp8bhRHGC`(ZP){KgpQmyh&)8u% zn}sytv1RCg{jIqAPUeYugCexUDK`KsM`{Pz=lX^j-PJIousVS=4MwhO=q|$Pn`P#8 zRlhIJ3F_Di(TAJ~t99w~Q%yY(gd#Mj9;tp-cYkBeHSw-GWZP)`lG`}#0XrRpoeFAY zOAZi?q^RHUeqptn$?9%bq`J+kbZ=`GK28Bp5Xc6(KRL+XTZ|!Z zKQ9+K9*nbu^v4^HU;0dm3K>TWbg&64&mF(4Y+%l{PXyPp@eI_3h;OYKD1AbUKPVlb z#9g%jyK%Ri+e~sh)fXoU%EiS`QXPVRoOJiBS^FC6V*RosD_Zee@`{+{f!z2MlZnNo z!vdIeNTi3Y`^#WH6>)#>RZdMAiXisz+=%%U#4Sm+V#l(J3lIY2%lL$GvN{%xd6y7B z5X&GRVdO0<6LbrOZ_^6u0yPtfmDc>4?wsvc)~deAwjX1*`w%*D$M^p(D>oCx z*>b}J4itL858J32yo1Wh3iu2)DAgV~qy0HWDxWIN4KwLSx;eZvqJ+6tC8%xvSk;+K zC1q7Py-61I+>|UQwC109U~t-WPJ+{mxj(`6+`tbAI?5d`bu=}X9dpX8-EK|!AF*oH9*c zUUIu7i#!Rw>>;BZ(TY@vb<0)th5_Nk*79J}(NF`=lIZkL=QIH*8x~rT`m!auN{{|4 zD>|oBIw9UHx5k|(Pp!9(nC<=xcTeVbwA+;t>bmtSR8QmofB+LnkoMQls#!Y-a(!fMC$Ysl)4lG7jX1eIY5WK&>6nJa~1jUNtsq=1p{S`aJaPL51 zdKB$~*x>4E>z%27*V6fsj4{=UX_xO$yYq;)KeUv65pKTa1?A!tcXOe4&*x|hh`g5* zpX_q@W3`kR!An6FrODVbv7c8;r+7ByK7O{?5vMlCmPQ+A`Sw?&UltBi-)x|rn0`1O z#mQ5{E=oJUgPEJDS7;Bo@>C~$TfNc;ot1gH_*LO_`D?x}orAJ`&3~30X?osc?tFQ( z&!;y_Jv<6dkHOH6yy#Nv0M#iCX^$QQ<+6BYr=#l9s*9Hm-bxy~SX@q>ljxJS3iXDw z&azE4Lwg6;7EB}}ZnuH0!dp12)3;Fi zkptc87ZCa<&Y_}-x7SH6U#hz)r$xMhVwy%~!fz}75JQ)$#hx?$me=4t+{SsN@CdHk>Phz=ykCYVH&Vk_FcnUNn8;whIo=Q>0?o4QSp)-gPeeYE=qtB zQY9Nr!Hf=$NkQu~8Dy6#AeUnPMbH;#@dKJrBRm)dK0%CD%8JC6H^!`J-u8>Fpcp=i z6M(4qJBe`_4kItZAZT?TmR^(Sk@XQ~W4QH{iw(|X?J`0E_V;fJY}?(AM5dIw2E_}kUwL#VoD!Nxmh(;ikhi2! zsrW5n3*EeCqEII~(S?E<)7WI;ak(Lx`FhJxHM{1GJqq&+k2X?wcIo$;G(81jQVfN{ z)9J%eVJ~^YtI7mR?w`19Xz1a2aw}7rjJ4yS(>jpxtNIxwxw!K0T1>OP5yJ-Gisi>FpI}gxylhxl?7P zau($++DfIn^&jKOBkO^kne@Vj2RA0ph=FN6ssopRpuCUw7kR&#yQVMrbCN%cw!8`G zId@I8ysU)09ll7VcM@-nj#-G@k>m?wzzOQNeHk+eH0lVFOseVR`r;!f%1Wo6N`oOP81bZjhYI;U4SyRxz(xV=?V+ha)Up>7)69aBUNFVz$^ zq?y0?wbU6YY)+&3xy#r&<=4GZPbyO@!xzC@i2A#zj#H^1`cOZHiT&Z$RA}dN;^rU* zQBEM)_q0vbuKSCloW&f-@_T-H-0FfoB3beKyCQGOHwnyIim>yM{DS2Vj?i{)(g29| zNQ-QFzz@K-#?fQb&pjhZ--WAf{5~gepA})z;r{GdO239EbW^2bKp1%hF|zl@D(J{} ze3SW;vw-e>IGPgR{q<%8KM_7tp}x%p6x%ph=B|*Z!r~*GH}iXuTcw*F>)-W@*Peto|@d5NO!}wg~I9eGY@ZI8A)RsB5rn= zV5v_Q(g2=#!tuyx=P9y$BB;*?RSb5mS&|1hTqf)xgxtVqnNhG=`tJ|ep=KWvFZli$ zD^c&%imM~*t1A4y@sL46w!`j$ZXiRR^AU($-NoUch%6nP_%3?Cn>!meZ8xe5bUYUR zmZWXQ%ypJ{p8I}9m1mn#tDZl_pnQ!I!~XlkS>gqED?d=i|8Pz0%DwBs7whn>!289A z%BJyF{@nPEc!!V{?}LLve?)JsGS+86*XjEJQ>cwq!p82q=J}WxK{p5yO|^sXFd|`B z%u_qfx9gx)Q@;7$mdJui|FK}9r4l3Za+5z6e2m-+|KoUr4l>*w7K2{;wZPD^h$;D( zUZRq+i(;K454(3JAIb8I{5)NblPvF5V&v_FZYo|qgO#IN`2ac*DC!^y@=^S={Fgv$ z>yfXz1ruQEWD%PZPin16vMgOwc@!Qrg8ZD`(@quoz3HsL275$yCs=dhzr5~D4i03} z!N86PJA(*(1@hw6bnb=7JPYoc$glIn|CC4q2Ec-(?66^Uq9ev^=4J%`{gn*1l(T+Oqp~9vCSXL{w)g`j>PhH@e)T1Gf2_)#I!s1@ZTD^eUFgxfBoL3FgM-LRe^h464jr+f&@E3 zA$o;+cHVr*-9amJeU6qjQ!iBF&6$Ke9&2=%$3BbY{)}P@Y`D{|GI6@*UxvOF^O9aW zQr@a*JNbBTb6c|OnDu?9%IDokIk3%t2>P6c06t;+wVbiCb@qC5;lz#P7Kk+Ka0je* zz6Hhr@qJ~N_Cij@w&UIEgfYZUzEUP~(h<0?iO%9?SZnDg#%L z^TI9(Jd4c`RU0cW{_#{t7Z9sEXkcL{Ima-hvSbyqoy>JK)>?Yf_*R@1g0+%uJiR(? zc9WTwl*p?%Kf3gER8buG2J=DO?(P9%wNWzq4SVnaq zv^Eyp+l;c0$l8fJ`bllkRblV33MuG&pB==;JJhv&egq^FN|&#IRBIja`Jn5=NANY5CeGG0G3EXEY)Xe#KJv|$pLegxAQ=rIW3RKSSTlo+{HAE13x{se5b=YPj32`SoS z^o%MgCf$|xRtC*9DP>fR$#gNo{;Ht0f|Lel=EL+-Xj|&~pBcl$B0K=k)c$x15#=0x^9mBgv zdipnfDDTm_ocXmCMj--#;x=pckp^kx)Zeaavvm0MP1tM`A4k#2S?S&hC3Y zP`D2=X+?uVJ*sX0JWqg}PCj@-;)>AP)Q8rChmZ6dPB+(4R%{7hzLp%{F(jmPjRA5NUDuHJPwHR9;wr>H-N@4BlgmmK>dDwQF_o?>%{Wtu_Zv<^tmWlp)?Vhzu zw{9>;*fKb;&d;CTtZL1Dl5mBrwbGs!qp%>mPdS+7*^~aKL-Dqq`J$z`KUJNVeEP26 zK{!WR((I8;nH#{nmYvMOw;ZJzcHsOP^w6R7CZksS-}wojrjA{=~w!t2K9{euHw zfDjy7wc10#<`aVTKMgDGJYoj~j4hkjcF&8Kt{npmek`8Dn6B|cvVxZXZVJBWM)@_Y z)dPDy#WJ^&cgZ7083Z*t^~?n!F9E7`B%Tuk35d>~?k(QFi)+KRPbLVAo|yC-`Bp^F zOK9H@1(QewjPJPSFbxe33_G(=o3Ga3t=(c70!R5prZ-1kF|3x^sbmANFZA1&O`#Io z^7s6H{$TbE8XtBuTA_&GK$s{m@TOfV!j4(4|NIbE1hwOLm1NoF`#?nIi^wGrKtJ(1G1GZXf6vDE= z(eP}U368#TYDnal_JKFdD7w>cB5@l$vbfvAsEkqcY{45LcnwYd4#eSDgu(Sz+4V$4 z{1dQd9bu^oVJtzsCfBfC=~+<1>u(+F2dY$RU7xs*`iO?J`j>q4`o{2QXxT{=E}S%* zu_noI2wQ6A_ym{T_^QX@!A0nKT7%-%=ur=gA%!l$g%gj9NcahlUuy2RFNWZfkcoi+ zQEcJe2D&MaF|-8F0UTxsWdt=4(m#8u`cYRE?qS*FMi$o8{*j(OVz_$y{=wY5JhbN7 zd2VO~A0Wd;H%11*p<|{4{1j6^{jx4Lws2~IIy^PaKj@}Q#2QoVe%GE5 z+g6R^8*u{;GZ4TR4wv6f{X7VWlW%!G?E;}cK&GQ$i6q{%uh@Tp4p7gh(hQ6_jX zmS4E~AP&aG>p3~VZ@FA$wbefL@LdlesDPM**@lp-E|cAh$tJR{RabXT z>XMruYU+cU+vh#aG+a_3(e_#D_`x@qnp9nZJUg$vo*8@qdbSWn78(xnF;|}@pcI1k z%Z4hFNDiV3DL2fhc|fTgZhS;_g4;>((zhSin5D7lkSZ#Y^^BC+wzVq(*OrH_ zS2UbjY%B>uruMd3uoY&EVY$C8|k#_)SC>e)y6mD&EWI}2mVOsZ_uPCNPYO4qMIPH ze$QsCNAnF1`a`>>KL- z?f?aE1p14eqqtZ|N8_S6Qs#T^J%76NNhBwXKFS?Fv^M}(zXCoK3fRv|@lq74qNKQN za9EJL64gY{w|i9pHofDn$VS=V?D7BTMYc(olVI;f|DJKXmgqj;k!p*4Rv+UPeNGe9 z?5E*0_~}}ryg5IfUOn=>fKQpCEANg@4VrkpUe5#_PL374kxDhe{IUx(rf}*2U+Q3O zTmI{016Wd_>?i}f4oz%1!Cimv<|d{9d7CrTXVhu6_fC% z+{f&3Y^i|sC5BD^TsD-Oe$5sh%%f6XPA)wfwkkPWZvH)ya25(P#%+-z!fZy;=BrIa z*tveXfd{Kszkbjhfk`HWvB3htk!(+D^CX_k<#5}XW?*y0ZLA!i*UBzX$*yK6t?@DcY*S zqq?H985qM7t8x&@A1R+77toVN$Fb;5CQNXj zk{w$Dn0B64nnZ}J1|}S!c^Z!O;E>N11gH5mHghKX0jrJX7|-{c6dV8m<|+%ccYl;d zQ1hLQ+7y7;`pn;!9IMV}mI$gkXKeEQAA`XCMHi#LD0uHt>#2x{k37sOy0>LU5?sPZ zU%bQg;7{v@f?O6FpH{X;HEe2?ayBgr&AdsYwz4x$S<<=dnC%SKp>Bk{OKr-1 z-C)lTkT~Nv55Qkc6LcZ@vH*mZ5Mb_b&11qqa>VcA6?>0AJbJ8YOm4s*I_BPA}TUX=JJ%) z`*r$S9Z0H5$ywak*M{|Nv*n}SU<~IgwBhm?Vhyow7uXct)R8ld(&JdgV86r~k;*<5 zFXUiRtR~7gx8#!ju|Gg96!`JsXkF8N&Ecv!fRzVsy%T=Qkj_0d{y(}++WeuAXb+u^ z!VEpm)QQgi14sAvv(A}<4H`(UFQL7K*eT3)xrM)=n6ki+A#M0e78(2`tcfwR_|%=* z#q;K2b3(7a#5e^ayffWy)q%KNv(+cRfCS$(wd*HggaMYY{fYzR(<>HmN-tox4RwBq znsW$A$Dq3*Ac@uT{-wdC1$zEK@^9^cK1}RLHvvZ}kO^@#do2f!^8Gi~slUH!=(A|< z9D7=mRZn2!kB67Ht3|}#wc|zdi-ea&;_UV9iUPr`vT?f+zs!U5a+Jq8(SNBh1#PBA ztU?q(y?6j4B*ClKD2)_)E!5Od()c5|t21QgT;sMIJh8OS9T zsUg~q`4gsmtx~W}p@9+3Qs^e5$enG@3D3Rskm1+BrU<6~o~jH8@>WUawNt@Z_M-l6 z?ww~IAWW%(WD8HHRL8*EJZpsbfU@O4%>s~zeolYsz zuxKNf6^a6k<5D!~g&~FZJm}oj8z*5+Edq^wF24L}bdA#H;9O<&{=?O7WAV>H z>68xE*CKG}{8AVn^Cu7FY>Nsdf{`_ol$OKdV zrxUuC!XLEGJZNt_RZ{x6drkc{?$@7#amAe#F|^3RbSO+1fC2GP*@}L=WfyPaSoe0; za)#_;0Nd|B7(s4KmOWMOY4}Xq_P(OmG&sIQ-=#DXx`j<@EmiR_FQ)_ zA6}@EbflA(x~yIW@by!fQsG1f9gA(Fv=?eLLGb1d(elZ~M9#R7W*H#>E8Bhz`eAx# zIBB1HXYBh*#A+Q4kJJvOo%Nb-Ht?}1=1=g>a9YCOKAMG4lwO7tELO;koaIFBR^K)! zdPJo^HXdtq3It$82CF3sXSPdwQ9BMSN3qz2bFn|b2%ob8I%(oKW0!FoYp}_0pS~=V z1prm(-@GdT+X@mNo8_%Z$MDVU1)LdpwwO|3fQs8A!7*m8QE>lAiTze0+8*E4JX*2q z<2oe(>2%wZm|6D}UOGePGpmS10#rr$q7+;K*D0X4;7_^J!VHITC9FZXgP<D z6*`CnqMlYj&`(6JSw~_l7~!PyeV!USuU2h%LP@Q*uppaC!2a1v+_i{y(^)bFdOCjm zPvj!^7|vXEHA(>=zs_4OH7(LjK4_EMXL&=rG8}t_$*v3;Fjwz(mcycq4Wtw3OqfLM zEvKp5d{JD)6t+reB%YXlML{5=K`wHI=Qh2<(eK&G^3him{MB0|Snko%1=Dl-I&D6p z3)}SKHu$RW4qG)4w)4<`^v&w*lrIFH=& zv5^zs_y|?#!w>);^sbADoUrQN!KwWPeA%Lyp!8~7LlG}aa49o5UPl<0QUWC?O(YdY zB}U0Y9w?LX&k#sGgVHM%e71z+qD8H=+jg##(Xdt-)&=lek>kr&Q%Dtwgx;L^nn>CH zOB8H|t(lya5H--NH4LE-FsM;4ZEWrgU4S200vU96&(#XaFT=HeXww(2waotA+UzQX zYW6(V{_pS_ki4uSi=TaZQHW zmwh-Ah7RyN`eCHh^fy1*0xPg3@djg~7Yi?7MmLF$WK25o=`HuEVgA{*V}1WT(zoIX z{r(;~0=oD3h;bsqs1HO>(#or|-~lSEHZ?3vkmbzF_8Fe8z6Xwxg{H##m_EY@xnpYJ z7FTh*2j#$eYl5|bWJ89saUKzU8tVAP@&3tz1k9*qsW6v%5~WD}#BH^Jkk3Dg-|^zQ zhI^kv9>cmeo_iI#I@o(Cvy9Thy7J_|pq~N|^Di)a?+mcQpGf<9RYyeaX{mfC`r0$T ze}*N|`~@8bpWUnC*KQ)lSHX2b;^*KRe(u2Si1wD~NC*LL;pvaV#+0Gv2X6>OG6Xsa zaKht&ZJu;dO2bl+R<*vMT(d}MrBBxp`non)lQS^$m5%?OTK7ysK8WnC3wwZ@6N+3> z3?QNjGJfsK(+(c#I*&i|isSzCvwnFc}fCMXRmc|E61$^*1#{ra!Y0E4904!Behq4O}lNB3;;}ga$@zv?4?kZF$#l&t1fFa6wN%!x! zmSzSp$T={LS+8_ZTtXJ|7Xx4ilq@2Pi@6oB?@+uJsz-_fq=qEYDb)vJ6DU=jx3_j3 zWm$RBV8$}*GGDHMdd|?d6q>$k2bXgKhI@Zv#=yj(?HS(s{JCC<&;T@6U9ty^cK+=E zFA-vy`tt~~=qVTAwb+GwuA|p5#X{yM%d5Jgusr*&%u({3O=|}7Ny-|C%nHAU!9Lvx z7}e|Y?{|vz;j$?=(4&Bt5S1ky7|78X1sylg^81D#ITCv`0!pGr|1%OI zIbM0zd!pB@u{1t$BG_A{HEc$Ntml9*8yTW_?|poJJ*QokwT zl>FL>z-$@$j}LmuHIdKx6rx_fD0m`!$IN?$xxI25=@>#g-+`05gSebLsQC$`rnVR7 zx$1iNu9`zk1a9B9OdHP@cC=>X7yM?vHBl4{sK^Z`_ds=kXwiW~ztHKQZ7|0c6o;Eo zyQ=#T52#ny59*H}!gASQdXX`3tT2Drm}G{XxG!4JknTd_693%0ZD`d2qyMOeVyJms z){B85arX;LWUPRR=e=fgk8%%5nh!ZUo8XQ#_I*M<$w!rUppD-JduonprimBnoBi!- z-7%8BB)=Kn65({M?VtH{PvSSN`vZrqesW+xAAAVVz+!vKZuDbF%9|0`9|j?+3vPOR(L*%=o}|HD&Ft zR!iU*OrNAo?6&`l=j3kc+fv*^&TEI(X3~G1|3dy}dF7kbRe=TOMV1ZjPpF>UVJrju z<@ymEq^KqIq;Q>hNal^p=_~K-%k|rrbFvl}u+!Dn=7I~JUnepxU?!5IM}D13QbRHI zpd!UPx77Ht1-GrGZ~&wBx1`I%#ASw;72#Uc=^GwJ0i@DD97+J=I3vdUPP&jbKevd0>(fsU_dpy%-Zq%`MKh)I}=8A z7lFR-Ler0zBo&TnujW4tr*Lh9Lt&-TjKM@iz+L?Z>2gBJqDzR!AJ%LzvtudXvI&jx zpZ;bVl7N!$YU%_9WdEa*D`JQhkpBpiy2W?uZU`vyQ|k8x+~@|2o~tCL`#>}nQZp%x z!?ZB@M+pOlcgdB)8=zH&XIet!z{u<|-9@0$rW>Y&@1>Jo<4ad^hyLXd#Sc0qmJ9e}-`$*nv8}`< zCBYKZir1?e9a)td9<4JcF)oaC0mXUfjn7TyP)BmRVJ%Tq5c>R?u<5CUUY7S&qTsor zS+;WL$STMt0LDX<82uFs@=9&GQ780dblq?LZ!oTCl=3>oZNw2OU5q|Hc{9>=JYJUw zBKF@c+vgb&Q_199SC;tK25T-M8S|_G%;>io6*bn!G`BF|dM3{zVhl6_uKSnw$rHta zB6K&&*+L8A1!4EU0JU=O`IDr45u@%kaC>im9p#H|#L9F}t(hbr6F~D^I)j;;LngCF zR7 zdnXIVL!1SSxJA5wWwzNFfeiA4l6qL3HE-wW!L$KBrx1SDy8F14?_nHLEB?q;x2yJ-lHm0zpJa=``g|87s_qTF5l8Tm*vR0=NYowT<`3+_>v?CZ9 z2f(JW=Gfl8<4wg5Kt*7x(iHB`(8I-}$Csv=l5DZjmk6=n7W*1vL?Za;4=dpp-z}C_ z5L~&II`x*=0$j9Ou6;rU&|f~dm8t@*)@WXGA~nwz^~oV~7vqWNu%g`B{*A`{PBq)V(5odX?t)dErPI~`YQ5 zFaO-fUuv?iyX{N6psUQ#PS5|3=Dpy-d(34kU}V$(t_73Oj6Ai?95pmvYF&KU6_-^M zyI>!{9Y5$6ENdY=vEnPxxe|qqKTEICTmVbchd>3Up}E2#)}!u*5j5_lZ(UZ)&$oom znyxLC9u*xQKjl7nl;F``l@3`v(kjyah3_v)LL&Ry_8liM^uF^^D_Q{1grPteBRNXS z0K<+!;Mg}25x#0X*a$sEl*&+iH7DH&^xh;jlB3@kI}*+QhSs365y}{QcWZOr1aMJ> zH{Vs_fH%kKRp#Iz{uX8l!zv}ByrMu)^wlr`wx|rOw8sE=*q?3q1aN^5mKNn44(u7ob-43aywgx%}blNjb#6MI=2AxK1mD>z}BQ>x4c%Fif!F91eE zsOY>S<9w=f+2tJwe9t&874b;wmh0;6tOp9IFih73fSo&Y|9qI0&5ez7hBDxVC&7H6 z;^t*0S$-B@-~q#q>IF64^anux)yo?xF7dk9v%V~xln-(kDbACR4k`qbyP=_W5fvH%2k2yA8o1QJCR7 zy?gCX9He**+)qHwN-c)mLL-$^$>Gb_EKW~;Dcht;?S?-$bkexssZPW`?_$hA-GNB` zIRtFP5ci*(!W_4U_{B3!RE;(WQ^X#|706A`R4(-*DVKc=#T)9V8~A!%~pX_GX%(6Qm-Y4OWo8X zCu?O_stE`6%d-3Y?bE1eadcDA_<0(GNj-A5GV!ggAiicqsIPq(Tf=5?yG`!YuODpu z@TfjfvI87|D6b&Al@BnFddC-ZOzhW<{(RO*CR(u=S)(uSLj`vGPuSJqPsr{keis_y z6BGDLkb}^!Cm5n_Sljq?AQ6&r)XBvl-y5zVh86|7b{H2co3O6bDU^^o z%3LyS|9d#j|HW`9lRC%U1u)0!C0TJyuDE$-)WRy0I5j5aaSykBaD)vg~hPq4DB z$o!P_>XWyOztU>NQE(34U->sWIbGZsP;7hAVsDL1|Clrua~|O{=;0Rh&fMW>D}SNM z)I0*$qy?!c`u6ZBdl?&-j9-&3qbo-R{8G(1qAynlbYgzxW3cUmNpId>cSt<$FDWLZ zNn^`F)@!#BC$&+$di2vp=;wti-JZuH0E94cDHW2))xhab8Z#7rrUeEM-8he*#&?mN z+MeI8*wDF}2GE)WR?#A0*5jm^6u41^P7-)qgi(8RKE1B^>z#ZnW|2B{gAZWz z&dtN&U3vAyMaa7b^Rz%e(pYOMfWeGF2?u>s)C`*d~b_afD z&sSOJ99r>>|Jz{2WL^kfrW8`Ur4p#3~a& z?KV`^Z^1f61~0RKzY)HmpHnb__TC7m|B2qrtt)ijH#4chCs~v3*CLSDc)@>tLd;IO zNvTh{x$p7w_jh-HtIv!xF*R-FR;gRhjfONIrd35QDNk@BHa1YT|gLVOu~-czW{8Y;Wps2gkOO&^{9K(uRLm z@5xAGTf|EH4(6~0CI$ij*h_96VXvHwZ(?fljpxU^N1hxOE}peDBClerZeE0$sa*OZ zvXI;-Dm*`X$(z z8L$OIty^^Fb51faGXd%-Na|-}!X|02X{Z}kX z953PCpH;9?p{!a{>rSfjXeeyTr=8aw#-mhmw&whe!n42LL~jhmsGhDB4uy(ul$XwL zGI75jJD}PmvF+w>9VXlQ+QLh=^vxcy9YcH+sVVI>`HT4 zSaAA4g8S>AcZ*P8|4~INxXixTLdOrB85mv&FsS`)0ukI^usTi{)Hwq)W`4hXe@5+& zCWusVga^wnZD@V!^H`OvBhm^Lupqn~T;hdsX|N8Dk#&aMWd{((OfsBQs;r&lz$*dN z8V~rKZBy}aj7&yB15%kh;f$vd-Zc|CFoSkHME4q@;sL_W-8_&ont#vvv+A5eM&sltAvNgU_|40vn=e>xJur)uklTpuvxf3#@^?uS7GEJIZ6i5Lns zzla&C*pb2x%I!HEyQmolRc%@avn5vb$*;KHZj4zr?$5K!%8puuC-j&larnh{DWk$+%m(caQodtu@oEFg1*YGTuVT`~1 zQpW(VZ~xeO7&i3JVY9gQ&s;i`1sKOT4`?x^EX-`0_ADd6QR@-YxH(zH%)8|3EU)#U zWVx!()>N-8HQhG}s45MzAlmKHLmVJWab%O`lU25gmd)vnkEl53ro7Rm?G1KJ6Wss> zOxF?uSl9?Djk7|1EJw|(Ad}=Mw9?I)6H{&SPdtr?R}|P?ws87Zj5ye5 zzbS94;j?Ot)kYm6iO;mXwZFL2N}iES-{H@=ir1hHiAAJ>cF^r~rOi0)zT9i?U4KY| zBEndq$?SPBfjU#`e2D5aPR^QZ82-^L`BDgK%=^!K>rUOdJ#b?`cOcj{en}CHs{n=Y z*6L1m23@HVa;foXvd>ojI9~)bq`^(!a8NB;^uri%L@>*8=mxMhBb+xSg>y%TQ-qV_ z4-aD60SlH99cs)Mrv%}U0(ETrn|rtN=ba|~Bazh)gHWB#Q<0fKIu?j=DL=amPr&}! z9=%?PV)f4oEXQHLHYP+>6yMtHvC~7)X$;79;rz6K_5(;a?6z6 zDBg186~ZYPE5P!t8_>D~sAFBrnl2@lX;BONj|S9e>U!QS{9|KX)u};{0KLc9O|O=C zenHT=+l}yJk)#%((2|~8{ki3vI2OYw=EHqC7<(h)1G zR8b`5>y2`hh^SzsgySmu=B=6OdTf9Rc$ZE49=UQDYx8AXOx_Q`HRK?$ba}+XtN|c* z_MTc(X~|r1v3;U)%j6x)P+Dr@f4N>fU%|J4Uzl-OGCd}-&O{gJeB|F@f#6WjA0q)+u7Kpd8?y7LV3pb* zl#9W^)>OaA-$kSo=8+PjXsI6y@95ocQ0!6#AM^ ziGs-Xu5kgvDjh36b7xn4q;OejPyoD`*Gdv&=dM78 z7r&C_t*3qzQsCeF-HWLYOXqOl0025#YJb0WsDYC_20hTIV4_R7j8yfdV zm^Kr2Y^Mhh9d5!AsT#ZyofIifB!G0wqTx4Sh69!l|LZcW>QFFV6M@1)|95ykCnj>{ zbP6eU*qPuVJp{E_4IZ~QqyzuE)Msc{&%=W0K0mZ_sjK!K3?u11`67AV!v{T<{T)pQ zd{a0oUc&(d0|@dP_1Q!`@?3+P>|Bf3pDsn$(7O0gD-KF=z}m05-4^3L3{W}2e>PN5 zWbZzp=|}P-O~zdp;-Ii}&5OCDh_8e_cy;!aOA zE@22o!DDa034Ob=aX$=Yb6e10NdXW)yh2h#Er7!~rqTjA#l+$5)r}mt55&TGC&s(~ zW_y@woz@d$z}_gFmNn~XhXs_Mwbzfqj(-Xc_~;D%8Q1y}F1c|kE+BCCJ_G>A2VcCA zE(A{hM8S2ZR;}lY6t26%wpMk6Rlk#Rtk|%Wh{!kaL z=7p`6|A{z`bKU}PV@hjN)g=1I-EaHNK&Q?9(TYsc-(8$xNjM)?6Hdnb1g&9O9^P|3 z9Txl2!7@Z0p3?k}q*%ne)7N&8^iqE)<=;*C?2)c1o#KWI$l;qc)K{EsP5Iw!*U@Sj z+B#u{GK339NS?BTf{87LR}vroVUo1>;9bVh_gCf3$Imw(SpRZ3OTKjo{X?^IuBG^f zz}GWL=87|I#kshd!U)ijfRl=bYde*(Y{Qh{ek?(zo|2rfKiiNV(lT(ztkci6f@Wqd z`*~+UVoip=|6~1E(3KL2Pyxvh3^;#z>tg7AniS+_a!`ViQiF}pmR)!@loQ|3F|3?& zf<=|drOuoAt))(I=XEHKKX;L)*J#`Pyyos<>X2>vljpJLnseNDzgAb=a#Ws%Q7zP$ zbl%MABJD;k7sav>v$s2>uVXg!$Axim)!!e2g&|doGfb|kHN#}7;qY7)qIu&SIE3Il z>Z%d|2Z%g-$%mk~Pv8Ib-%`xa9>uQ=T35!nS zaQP7%?}UcG-+mq!P>s-&d@fTmKif1V16cfcvSQ0lh|3d&q0pr9mW3{I`R~9q^#MP! zXTmFrHmfbIXLIj`D)|A*f0A}7y7TmJE$h{EI!Xi3(}=vi@K1MBuNGwb-nCoz@6@Sx z*!Vx&cZyx5&4pGpUpIpul z{x5dK^(2LPFDms1vFy>K{)F?(4ePDnc3LF1Vmuu{s7lcF=Blp?9;Tlb4L^lJOzW4-VEglSRsNq*wKCS ztT?blB`r#PO~N#hm8f~HGd?`B1X>np<~$3ORLa}OAQ9JcwJwN-fsK%sS=fM$0gVi- zg4l~72gjLy-Q_2+Q6uI;!v3}BH=+nqnSi@eB6_sgFSOqHgSLX8J@o4ok`Mh3fEd>0 zV%VBILhQpEr`EOOQCXjB=s4^8*4C!qQ|8v|;mR4qF=BAesnmIfb8N~$qYn|x{ZFK>UqRjP+;N?i1sL=6~v6ZAQv-W-?;GvINXySq6qo(dT zXjR1z&n39nCN!^+2DD*l*BDT~WfV;n47mphp1Rs?J78!kbKC0N@KkRdEX1y!--9hi zu7?$9cTtzK^Ih6B>XG_!%vNlqKQ$oo4utmi=6A0MWhbM7Y!LpLfST`npM!kx?7UY! zC1IqrJn2t}-lEWsGvUOJ{#@Gzcrsv7;C+>#%9**z>C5YZk}&ymMl0Nik~ep1W*?_a zm(%%Lw!k4#hGp=e^p?7O7=S_cewIzGp(3jhhzcW{A&HUC#$R9|1Mn^Mmrv>_(C~jO z`@y{J1#0IZLGJttgM@)R#_P^wY5N;PJ6JR@VQCM*RSh6Mt?r#c@`O`F!VcrAsPyL} zJ*PjQ$w3F;af|fey0`jilgkR^1l!wJ>qart0FW>nl#hDcTp9eTekL!==I$?;lG5JmY!OD%BZz&1y5Q#s zND#gQp2yN+SpfG%X3zx@dIc^ijLT57MZibO3iIyb7D0h`$UWsr$rBSsdfITg1fI)S zuqGz8!rpI|4*lnJcJ0^SEUvb(NADQktY;~($ojEDvj*$FcepbRg3|>SX)7b;iq^M31JGGfsorv1z*3TRrC% zhpWZENgugABCnP_Z_kZIpPE`_+V{o!nFzgcoQC5M3kF(wUJVU=IG1h%P*>$?90>Pt zArl`U-HTUk&Wd#yB=!dZtef+z@}O~M92vWld|EkZQLmp)2QK5`RR{l=^=$-VjVD%r z=Leu6WG)F5=I36s38%}u@Egd&zmI{1|Ed;;z=-OhlmN8^I2wP>9-H{y`&R%;&$jb( zHZ4CGkVQdFCHNU2)WvzjfcjII+c)X5=;bGYqGAv6Pfk-2fnWSJ1x&$sjHE$X`CH23Ln37swno@j1iKnD_V zr!I*sU?B#H+uQvzF*Jf2bxJSr(AxU$rROWD&Q8{i+_0yMCeVuYDY~JkW{Mv~AP5{d zf0}ySaC<)F}k640CWscuur+*qL}c5@H>}rk*>@Bi=W_M|wjH z>!k&vva&Kt9>3MJKZMcgN|=AdfSZRLiVmH z%2|~HwtGi*pI+JV;uzBcH8w{VQhT17;bXMcSIj$rdV|hDDJxqh5GxTCt4a-Hp5vn8 zTwbL~t!-ffVjW*@WM;^wSf6rJUuT>$udEn{NsQEEICJ{-Du21>3Av{uo4qWZ=+9wt zl-_X+@NJZTZRHVC9-4Q!A=zGC+nxp)im4cfr!%^qpL?!7A`EhV5)X5C&!RmG>y|ZbE^qBNRK<&sYCA!_t#gqiv#ZyOEkQMJmKc~?TgpIA&c0Jcc3c$U9W*D|ly)-}0r+=11l z`|e5sjj-wUlnVbcv9PwtIckaG4Nh@kdtNevenXzq0@8MaM+*4VZa#&b%Rvm5@5!2p zh^kvQ791H(f}GTn0e?h{MLEA+huqKb4&w!K0`e9*%cB?;37VAK^9<)QoD(PcM+4N^ zR~xfc9<}XSaf%i+^;I;bwGBKE%|ESKF?ry?5h3KR?XtXe}O`5}XJzRfFF*MOfKdra7lLRvZGF0NV#TwQ|uM#CVcN%z)w|MX57|MSVo<7ntU z%Q>_SP3p+uk`FfAGAmNLWpQ38pIKyPsWUi;7zX_`EUeC&?H6Jm3NZw2)uy>fZZ$0y zc8Y`goVpcb6>^aZqF5FFLbHo_dff^V9O+sh-8O|T?y_mMuWz)2UGICdP1LYbTi4&i zz}Es3!m$rUzBfSPKV?f>$qm&{Jy*JwyMh?#19gYfDm0DZViZ@b!dDYvzweM6UOm(& z?UOZoh0=}d^{kKmgwx@q1TqJY&o*E?_T(y4K^iQ$I>VUc5)1&BHCtkjV?rr>B%uVt zh4DxnhpG^88bYLY@bLz-PEX>z%pNmj#iw zPDzq7b40oWSGV`DHxjI8MuI0b^>A{QO{MOz!Z-Kq{V_oml9ijx)A)M80w))s!&~4e z6j33T`*}{Ho&}`}3;qE9^^OKS@!G=;RsY32XhY27wO5!!Xeq$E^LL~luxPp|J9Rqf zWo-cdrqq?7{MdfD2ty*h%?DjQiM@N)Z5?>!;p~5h!C*vp6}&?(1!7N4<`4mb!;t|p zrTYs+D$OhKqiQg0;YIrL4pkduzjZIZVlW1?%Hp#x%Glci93e5GjW!yKxB-QWDF?i1 z@BsXpx#LDS{NNl!x5i6b;0=>y(67T!<)Fd^bz0$MjyOrhs0dc``ZSYKx%|sgH%jOv zy>|UqTDd_JHQ(aF&Yg$B?Zr|Qz{{T=c4&O+?o*+fAR@ekys%VKhfJ~8;mF*j)h@reKg7D$I4+!`l7sd7ls|`pmrdxniw5E?qtTo=v$z4)-1dkU)65B zlYmn03ujc-_#XjOCac+6CSPs$!suoJd37#kpmO$F&cqa;1L1iZ!17H2Pl8u`E}oag zb9#@C%-q)XoplwNMmhH|0$N3clQ!e33T2(A{o&MI*PF|5Y&J|H;uWXGLuIDiunE29gw}f(*hu)^?JQ)M9t8**c&$@KyR7g zi@e>6a(kpB<_H$6P_&XB#tsz`WeQr@2Vw=Fa~s5hG_<9-@^879#yD}22XI~rFDnSd z*&>^00nnulmv#ccm>t2&rf@>YTS2Dc9Lq42UciEzjC{L2hI)fOLz2-T;OD5u7%HC= zFu4Is+{3s4XyyStiRnuh6;*%F>BvgTZiUPg?dDSe3LON~@_u|24~+pkli;FDBVbw1 zJz*^JG-?uGWR+XmD>!V4c~l2XJ;@UJZ_7)NC-B4?I|rb1Lq%APRzleVw9BP~jKB+S z?XzEL-EJC>EF=^pp$sJcIBkH0f>2MXvmC$Bs*cAq&;>}GARbSzwOFlI0<`Y&$oE={ z`YQlrpz6RgIwK8PWsDQFhQK4*MBq82AEc3hmA3l<&@mfSFd?rz2^OY@S693+P^9zq7fo>q}8cR3ldMK!pX!6{-t#Su|rd3FGq)?0u~lU$=@VA-NqZ^M78 ze@)&|DR(RG%H=z@UMio1uC?2#fxbJIH!i@K>NQh#%oC|XVQd9DJ5s5CuxcT@OcxTndS|i z0IFUMa4Mj8Kt)nffhxsnBi~|`acPOAHO1)&tyV`0<_P{%{mT|-k4tB@(z~MiNzYSc zi&qVKs22g@mhWC=G!2I146`s0zl;T9WPAV>twX921S!+%2t4PKq`Y*Mh)dlpffp7b z2P`&YI%=`$0PNlhDXb;;p9iFiySEQxLa90hU;&s4b#__!T3CCY$aJ2qRAFAm`E?{b;@XR5h z{axN%me45=K<(487zE^$N0&F@dd&-yCrE0wxMbD5N#Aexy?rHb5y+(H;os$L5q582 z-{Yy9!~r0s&#>#eySrW831C~~`82QM@^18tbBQ{m(jECXyCytSn(66tvrC@6+EmgA zT$&5RwwFr{Q%n>p(^bO?RrVuO2ycQ)$?Z;K>Ss4uk*p(=c> ziKF>vmgv{d0kjW%C?hPdE+DhNsU7n&#Y|{zGKb~7g=1c(O_C|YYhKxTD4&T&OL|WI zq$h5j8*h5s+Rj-(c<4&?C~A!*G)WhbkNOI|Kr;n<(g7kKitXMg3p;mPfJ&!dB9O4* zXd05rd|I5^@d9b_QCg#iNk4?{(+jl`)%DeUd=x72YkjD`Tffy{*RTL|#v#q@ zu!Pj`ruyJ%aV{fTBjx<6gofpuiVtC0%>9hqw@I*&K zfB?#828NlvVGPVH16BUZ1E|_x+XK6h79jn$dJYJlRUos~w~u)zXl4;<42j>(UZ>l= zdCdzVlSs@AjKNS$-Wn1^Sj(~FMJoce>2cpHHUY8}Hm&T?rhTN2Ci#V$SCKJim5Wx5 zEmQ?Pt>z_TI$)XZt$me@R{hgsQNwjB2G!ttz~@ zS!3b#x%eCuv7R3>)&{^rxlZzyOQme-F|Rdo09@V(EbIsf7S^SuCnq><{V{;lrSA9h zT2P~Sg9Qq$egj}$I=Nyr_;MDC=FI{?p&o&3H#32xI9*B$1g``rNTyeu?EpOOdpik^ z(@V#^wrHoU!+)HA)xI|{r-HyxpB8}Ud2440>gJeN=-JRuLl*X!ewQ~|f+F35%)}Y2 zfGcT&#uEUHDfWPF-@)-I9e~c4h39#(`EtGBhO8FS9Iwfe=!j6!{B0G`G(!Sp)w&BZ zh9VHW8P-YwCUplCv|;L(){yBE+hbmV5PX(wc576^tMP~@TjF(}vD0D0Nyo~u`#i%kQoMa$b=#I}tVEU9AJ z2AB*2PK*+oemYs+FrKt1psP0RW{D^@E8xf&O~jkstmbiv-U2Z8vVc3$iTVMQDH;l5 zse#)D^0Fz-1i+%7KxLUydL7`52l)TM7a9Fa^5T;p*HekVCvR-6!6U!Zf}`mGN7fir z#4yvh0wWt_f&fIyHYf&508VLV1c*w3fFgXkn>yr86$p1l69CIX2W+BRoQPeTG9?#4 z*Y2btTqel;5eTgsiQn=IqjNkG;{eE!8-RbP)Fp~{z$vE~-O_;e5QIv5DTbBJU8nya zxbuCH_rahyfBM6xd4KYQ&;MNZng53Sdr85Fzeg+)1Wt{pbNprgBaaCGBJZ!|l3)G7 z&p!CJ-{yV)x4!iy#eYTKzuS6G;)G>hz<;wBdEfd&Ipt5j^?}p8Km7m6OO#VM(fTic z@v=Xh_pAT6d7;zbgyz5DAsMfE|6jf4{h#)l_kY@-zi9QApM38N2KnOj>jPo`3;m%h zMpWi|KYP!Mn>AkZ{ulZqH*35;jQxMZ>$4R8r@iL=pZ1#ff7)x_|7riCyaYig0{~r6 z3lK5@)(C+=#%{;oh6W;ToYL6vh$H|QHF$y4kobcl=lBbKR||kNkx&rOSmnWbjw8~D zKgd$m0y-m9v>U&3?*82=XuJ^dVYy|AVcS6U%7p>TvU3eghTAq2fm}{h z<+4TqwM}8T>Gih5!p4W^wB>v}9?!>>!3E+X-fZSX`90TcHiH0aaT>WxJR)Vt_m5lP zE+dbb42}e`l+9$KEfUbM8o*ZAY*m{94It*LRs&MURjvABc&=K?%64UWC|&3PXy*ce zAnS)rv(rf_R|S;}j#7CN6Xm#kcQKs0>=M8<3SHR`jP_8FG))uDDC7+ZXt@GjDCh8K z7~fY%`}hzbx|4rb-oQ=b=FZ%^FOBDekA<=O8g=zCKf!&hF{?thym~mg^_l?08%a;{ z=3~iZvLWI*UAuD8pI+r#7nO?`h(h@=Wg3;{thBx?#{hIVi*7DHK4H*4=hEHctj^DQ zE@uJ4-niD%NGgX=%et}5vG;qidEqV@O&$ke=h!1At^`|m^Z9tF5zptl6+9=z<@0FX zvhrE&%Q^s-k1qj)dum>CU+X%f1H_|RiEp&-?9+^?3rjL`fw!=B?n|yBc8MwdFFOzlstQR$pY8~U!DqA8tswK3Ltj- zMxU5n=@SX_00L1S=W?2pf z3$8dB4<;78Kv;}cx1pdlT4^YZ2?2mF8G$UYt0dytftI<_Cp}eQnRIJ3{1hM^|R&=Q}=tER_iS&Y?8QWJgS)pQ$VuBXrCN>n>bgBhnW@&>R4;FXJf1F%>PcDfmT0 z+)ietW~{;&(>&vHdtC@L(uG~~K6*~6d3AojU!(E+O&WQtMeLv)y<6|S=vSr(JDw9f z0aHxhKmTrN4n=HbSGqP#P%P%&MA_Xwvx5?V@>!WH(w#;+&7T$U#I{NS$g{grtrn*D z&P)_C>t&{tT`B*q)@t60o<7M-6#!(L0BRm1kY66w>%z7f``6{wG9UT!*P1x7zUkbu zZ;JI|bfx6IybrA`AS3bnnifF+n>RNf`gP<|%Ooav#%3EdMS*Lt zn)Bo36sHUizl&06@aOIwI6f6Wj*a#i80t*!Ju8k zbsX|f;4%W3tc<65Hvmd;0D_#?L6!3PyeJkI#eZ2|&Fsrx`HV-4-y!%fpIzU}Z&!2A zarTz(QL&qRDF$QwAXfEm z$l_&yuK-}3coL`wAtTr@{NC!)$uOG;CM?JE5A|D?QgkWv$alO(w!*nTo;UwprOM88IJpHX987x>an2XCZis%TcvYdCT^ucpz`I8Qi!;_#1q=SnD}y`X>(k6y-J<#wJe;F}=Bd?^zX$zsqa!rqt&js0g=^N$$1QwnEYenbWL2oxR1o@+IZjmG8Q8USb~J-Idy# z{l79VbS4s~ob|vex+*ZGR#M&fUY9&qi>rS2wtt&~V)x~mnpanG0mFy0`%p4O@%(*8 z32I&=U@R(QQOgLiR zfyUzp>9$^YHAW(0{%zhx$bZZ`3Ibt1X^u$AT<2g zXEH1fED2y*gsr#$wjT=u2(N{6fEWGtfOmr@1XKR);_Rks;c&WJb->k3s6TeIp7ucz z@8Suu^#Asv)prLpEL@~~*PLwPLFQkU_a)JMzREX7OwouQu9)QX2S&tJj-^=VZu0+Jb5doS5YfucW(^Iq7`k5VIMJ^{pp!O2QE|r)@DOG zcNjZx!K@e^T8*X+GO@?$i*EQB(Phi_N`URaQ~~6+II+-MAq%G;%7Bh507$7TJl)wM zn~1w~tx~RQgQ#dCruLq@rf{U4dPkH4JTI#|%QYC&fi7VJQEZ3IA!1{x?F0ttmN?5joq ztqCw*UOE5}8WPV5VQ7M|2G0960&r}rZUQR%n1&+=6&dt}jmpe^Vmmpjz#u>XnwSMD z`(R=Mf-b1EfvWPgIvZfU=({0vTY!{k#fiv-gp#I}vH-9W04xzGbTk4EC^QxT5e-x{ zt-c^0P2z;9ZvjBVVgqzBS2!F2K)U<{R1Pa_eIs6|EpcSk2F6CKV`xJyWyedFul%if z*ZBV;xBBm6{mkE*H-lII@iZU(Tl2>8>OWrKFUm{lDgE=j9A5p$6F&53^ZxkjKm9{_ zlX&$XZ~HuNUC#TfPyFmD?>pqY20cYR-$~!NjkZ_+*+}tu-jJO4m!J6AdrtCxVyvDox_slS*WU!^E zm{MD7ED(zzH55a+6%bkkjVOqKcQHmq7L5d=F=-bhZY>KEe}b2l#+^SvP4q8#=1i55 zGXq1h7kn5!Gh+qJ+vhtsCXSIMJeMU;*PGP)ZI(am`h4gcjklRB`|XSI?!JHMf!`*1Du}_dq_D=`mnUoP8rv)UhxP`z$R>S~y)n74 zdFx`l`(AsMWh-fhEMXRz=*vf(xysxtG9#Ngmg-TLo+j)Po1Mf=Si}ZP$v39K&AmRLwU8=jH6r(KdS6RwgAE9z@xZ$2>9_om5$y*W>rug%9~$#ZHU z@ou9J+FoCdGq*Pn{tgk2X0~7SX2({GhK(PR^WXj4 zx)o)n2rD4K(B51Gj3d{^ols9*;j%?t#f}k7M4@AE`yiIdQ$wNKJ4ST6Udcb6-tE<{ zIw#Jvg$<5&6ZXQu-W&vs;m$x+i&Z@ziI)OM$0FAEzhngFjTuu3$ zFMX?LxU{Bx%9@q;#a;_T+xhzW9ev8Q!_<3M*WMfijNT#OT9KN=c&w^tzzR5T_mo3y z9z^{e2+>;uj^Ew}?+n%gT^&Hf^|MVbps4?Gx%zjVcdomj-0v(!aaHZ$4Y9YU0bCz# z!rq((+((%b)ry6N>t|uH99p-u-9ecAMFr3%V-+I`7wFE5Q znJQe3Tb~^-L0A@!(|89eM_X_(ejCoBgF)fo4G~=v=xP*V-4OkLeD?ttY@mcLThaNj z)ZLG=*c0beKYE@XM9qcY`l?M~^}QjYH!Y&uMc(_HEDY_QVB)J?l5D35$9XgM3ed4P z`vK!fcUxOq=vEn6ah@$juX{K=-CB3qUS_B9w)Dmvz*q+&u|DYtS}xU1P2f~$_+k~% zF2Q~j7-EmO*&0D{#fy~Z^@6hvXt9ep7X}3GpJZ%rPW`Q()2+?^bMuKado4@Yb=S*& z-s&RZcpfy_^Q>gAdgq_VOaJe|-|@PgsB#ZSq~7RIt+iQ+*EKr~bhV+px7Q`~#0DCq z2u?K?$NPa+5Bv{-Yq2r_H4&i1Q9IfMj75fLdof@yK}3lc+*H0W>l$Z7B+9U zEMX(9&LLWzj}x9SC?V)qKqBrYf zw*d9MU~|`Xb>rN52)FA7LpBtLW3jFv9!e!>bJzQt5U}^TyAiaxFj7bFg?M{ambW(t z0SnE9r0(ns|kDmsl#G*c~evQu)wf7MWMtg0@bxN zZ)dSkY86lx2m%5F#kHkY2g-^u*aNE+0feS>(j$NNHWD4&vgGl7@_uGNsKK%Qz}p0U4wUUH@YH}}&ffIdD(q!# z!Lhu(^vIjN1H?$)lS#JKtH+)fiBzMJzNBr{_R^zp?KO#U-^&gId$SyJV9r2ZIx9-B z1xa0fcPyy-P7*zig0dQW0hqLxHU*rrp}i3DVsE8xJ~K?-RN~_v3qyBq#Pnr@XO6?; ztG5?e@Afi`?GC1gYkC_H2n75a;l$Gr*aDN3udxf0a zE7TA@o-1?S^GRcQ)!sLGlIklzC3-w{Wn!<=tb2R8Z*?(X9apm$vsg#;s5mZ5o|-qD zyxicKZ7kR;^z&`V%wABIwRfHP%iGHuV|#OzE*bSvc^@T{@Ag@iVb7UF@|&V>oaiza z&CFi*+xoXx1Jpwkc`ocN_7P$tg77OXh-zE36T=*qA>lZtz5u$Qtrdkgv5dX2p~>U#sD#IQ88 zNzr|E!OEB|yY42EKdHVxH!+~qfeh_cFFAWx)EC7?N7hbLlc|@PdsVd)+B%dId#|$j zs=-bX-AhQk*}u)g!H=#MSb3fz2Dk%jv6p?U%3d6e&758vFAuMdmoHcPj8lam`u{O0{k%)8e}f z@#UZtJZRP7;_RU^1&gDyU7qJK*tN|ekUya>r;XnB2egCjU+{U-36qiZE!`^SvmJU_ zTb}Q}&#!q}Hd%xX0gvAhV?;XJTYHhV+Z+7E45UafxU0SWedT=Wk#QC|Jb0fdP-$+> zt+(eGDC&nBsW4+C@#ti*`}XQLO#bS{UxH^BnL+gVul5>z_S+iIUoeKg1Dvw_CPXhmO(Dv~O(eOka%czT>guyMH+6croJbVA;wsq z<5^D1LQo4(M4Kpw4B##N@`_J0W@hi73L;&%H~0@<_Z~y~-`=xN5{!vNgx9Zl;ht+E z^YOa@U_FBKeZ`o{{XE@!d-vA27svbN*j{_yJ=z^>uL+;}$cGs-2??kBSb+-ZCptin zmH=!>oZeq^i5dK#B)V;H(DE~9l!ED(xfVaYM{xJ~v!(4lcI|enrO)f>CRJFR8gUYx z7$P-L%5{?|R}%@Q z1L07@*0E5S>BIuh;<<~uD+gReH%3Sez&eYsf4OnSHb6ote3~Ils}L4Yx?OSV`M$l1 z&nNkXFk>4OOA=03da9sw-7cbAezFAM`X z2|#sPzyp|l#n=Ww{%#bH-S`Ix)H1pv>IHpx9zrF{O1QwYdB%3Y!Z}tSyI(X2N+deX z=#9%!Rsf7W5I9`mg%D#qNaF&ouEcFA5Y$F}M9-+8!%QOod6}~gJ1Cf8(442(jfv8m+6k!e8J*A0I-RAXxdBJY*e$&In zLzj&RNnBld)bAv$;`Ea>0ATE~B(XSPDQ(Z-eH9*0@y&2=%qakrDju4!674CM0NSDN zNs``R?!}T_;r)_G3p?Rn-BJOnZouaxtmX6vWK{%8{WT6)-=h~+?1cL-v6y0`JK=6? z5WpJga1qvX4Ufty07@nq5%hqgym0ZGy-W8|IG>(vX3I%Jd<%sOVpY$OljsY2n4DKo zgJZX&g49en%FX7+6LyQO7g~AsQs7axdT}H78mL;JH04J7a^KL7RlG$P*R!u9IAMh6 zqpURfYjG(bvQxG|IFwlVo_jIDp=fuq6=p8qQh=yjnhJO+qMw}f@Mxg~afP?vb130I z5##3)5$?{WCXJ94jGVL?N~P{jpwcu~6XPU7nwhR^P!yH^8{In(v z>G75;6E+iq5aIZl%`Z~L2K8=4}D=R~NeTI^P)-pCr7 z`hl%wZN?gN^-OGCRf=dyMW|kyFOwcGO%Vr!qP-6HYE`bqGz9|joEcGGE))vOwct6M z8JufTEp5naRnjvuQ6KDmOrz)$Y+cV;$DJL-) zoRo{EeSW{+>pf)T=n?GbA)6tu*NfJ0h;~sFVTs?&vPr?0;dh|`0000qU5E%dfpvuZfr~m-)U;qH78xiK8gs67Y1^|G*QBqKo{5S3C z?f3EV+uGWyuBkgaJI~F{J3KsITv{n9DQ#?OT3_Gz`}b{lWIQG&VS8tHb94LSjRa8{V%PX|BbZBYm+uJ)hI5<5#JWEPSl9N+fTie>&+NGpq zmRB}*F1O|7zkK(jlhV?1#Ka`JR=YBW(imM^NG+H`ZY+G(k9!Rn&w~p(LJ-Iz@n6Iyz z{V~2Xu9L03y|KYxmpi*Z<6h%-^z57(bDWM+~ z)mRu|o#{SpAVkwjkM6(UzxW3BHk3|arm?I z#?RyHxbE>(+WDaKb+7(uW~$|cQ}aqg=0EsiI;(tD1-P8>CR5k3$QMP3!I@9<3XUAz zQ~;oqSY;(d)!f(4*XyhM!8oCFgQ)_5124gx4KozQ!vb;)@;OXIxJO=j?~a$8lcPb9 zxxWGa-r(|Jx(YJ+Ul?aH-IC8U*a%Vd^l-BU7@zkTn@4$DH2{3GIujmNQoo{$95FBJ z>HGlQ-!C?SV?1>DGtE3Of4j=eWQH*hzp;#KM0PMuAmyV^sGQ-UjXi4tcM_r+)c}H( z4++4b=ku;nNoN1)#SUspSU>ZwttcA&UO)@uK*CL_%LR)gRCEEuu=JhezY(yAVc2Vz z&!FmP2+0t`ifz0Z^xY`V=4Uyrze81=bt92+9?m^9NJ%}q`_PMZ62I5t^x{YIaE}u zstILaG)v$aRHbr!!6?9Sm5MQ5K#3yMBF|w@v=EOTyY9 zgCK#peHUt86F&-4K+QgSQAg@0?8c9u-dSa!`(hnFmEpK) ztBzxzDES654@iXUM<8Z0IkFUP?VjpR&N?HTmr+_Y^+WOIc38L7>KCH$LQ>4G3iEl? zAO1`Pt%&uIuz25&BU|^2@3TNX$qC~ugZhspmO^#z$H~%P+Wkrr-hxnoMK^~p z|MpF-=gQ@M&=19*uA@#?$I5HW$iDSOC-0+Ol`q&D#H_i7c7RrDN;# zi5QDD&cu&;%8-Y?j4%N;CJp=8aIC}mtNSB+rh8MRHxWD~a1LY{g zf`O1VGLU5R!nc{&px25nY;6yl2gg0tSjTU=XbO8;7aLvFL*|Wh&-6(Jb6=9BBs~dI zBJ(VUuNH~nVC`X{aV~B*7coO%Mv3elQ@_#6IidOl^aTWp?bo5E)rGYFcEm|7aUgSB zASDhq(gn^rHx+-j$ePk{l$W%wD<}e>%_b7{)A0q?@KNX<>lMit0C*zWon{68z|i^# zOWOWwU9`m%$%^s7aAP%UER#ErUa}DtZk95;*>BLJR40c6Lq?GU4U1k51IX&kaT-Wm z@|9~)0FK|l!-bK2-0N((S>^*Lb3dhdx%_$f_K_@5SF|MszXsU5Ad~GAv|1w+qp;-5 zoYM&!kZFgwrw0P(#eWtc8O9hM3l}*v9`+o(=~99!320i(y?uiwe(7L%Ne$z7_xH8Q z$fyA@PQLSMYvE{c%CL2VrUoZy1UN&w4OeT5pQj4bA7mFd;`gXi>e?4^08XHC=kZ$T zwbfAXWb_dY43Dw?D6$FeIb4*gRd(qyrps(_xB`S93eI$>Ou}-moVV!Q+LdBO(_5@c z#b&+DFk}heWWw^W!5oJlwE_o2P((c9wR#}KA6WRC(RvlLE~A@W((BhAGPF-b5jV~i zckLe^8LOJ;S9+a>_r7jskpurQ`=BhHV+pS0wT!f%qLzk#BY3`2y`*XrbI5sZs0oAQ zsQRz;^nmr0uDZR;HI)1Wc*6Yt>qd?4a+T!+l%zs=X&8g=z+8rr5T5A6$X9q+5yW`? zX4dxznP>6}gcJYKE^7PdRJ%sR`P}CM-s^q&%jO_N^(6XXBdb|@&D~~~KQ(_JQ}mh# zXKj;y!R?`0zf;ijs(Revbm-{Ld*!OXQo#PcAj!^4cS;iE(JO#YkjTejpy{4*_Y;^I zqSPNa8G$toTbN(67>-&EQv1A64s=H^JePs?li2}@-PA;V*5l!~tJlbHpiXlPG>T-_ z8a0WrscYj7$MgwGq<}a^ib+=|!W8KS$yE?tcya6y$8xt9=fNWQsQKVc`i`xBGHkge z^UoiFpz#xVrAM2OqcZ5W??1MW<2Df}_@2JV5!_nw+Cf>FJI_(=8F&-;g092L-1ix9 zK(I8tO$K+y`Ge?m5{2}~w&(Ym{VSB4cU5V%4)Cj~ykEC=4@j(!gBeBw$TYEkYc*)# zb!!P_f5%a>`z3N%#qMJ}!A%(8DqN`GA(EJ8V#>oqfg_zfrS9g;YO3Ai_3Z*?sD}cS zDVy~BZ|f4M!7#itcjuwYxw>V@C)LJ0JEcHG`DEr5RZ>PfxZ8hcsMvS6JZ` zt;^I^WD~A0>bBiYGc&#ItRU$%SHFThtIrChtNSHkIjET!zu_fJI=}rbXLZJ^sA*h6 ziWASMFM7}I4pr4|d$=S^5jrPcSby=ode-~J7Mp&1yhh;ioj;GkWd1Fc-r47TOE$6b z(1V2ssVAV~Qn@Rfl`k=D+Tp9`aDivjud}5|%(E|@3I*$fEZ)Ae*lj3b1hH8#1z?~A-|Ld2Cg~JS!d~~%T9PivOtQRS-%122p87y< zBMNa?i2XH-pyi0}4v8?fO7e%1X)`71Z~em!Gnqt%f?p+OV&fWD&KmKM6-)Z0q{n%! z1&7z5_xw2?;V-w10kWN8Lsc8Pj_z^4e|nx)j>jW@yD;X(inUeLS!z^)tMFjZMu+k( zI{Yb|wlfg{-mVE$o)*)}A8I0axEvW9KMD5UUwuJv8F>EY>$wE}_2ff7&qb-zQxS?; z&?}A~+3-Vv1<9XQcR-|)d8k-|&awR}5k_-wU)#Kqp9?rVlx5Hf?6vJ}Ka)ZAt0TIW zB+6Q?T~5si#u)&i#@(3@Auq-bBOLr9fC8lAyAwJsi!VJEbh$k*wx&L8JPVOyMtm}D z+Dt1+1kvI2pK=*z8!0=^>dw18-(Zb2OYQ&U=F@;+Au0B1SP-hFv z7GBo;%v2!pAf@>eFZPF?g43L0)pZGglv>NRzKbb-+pMt0dBA)R5W(4d7Dyx| zeYt47in|ED?gB6fbXXt76g|)dgmA0>)Y9t~V3*swvB8Hn0Ug-9DnxW0MPkQP{eDE! zD?nk=us}I_qT|sP024qONhX_#`^%<+2=mx~MXqS9qg-gt{79lOpw}lWDfv5w9G`IB zA&YygsCz@D9zpw+3{KWe#br%+cuef(PaefH_XhZV4h#%^C<{&SJN}`xhT{9IS3Q0Q z4QtsJbQ0P5_Y~5B!}1gQ)k$$X z4{xJM&7O1^7Jp#TTCrp3o?zghytDC2d#RUt&9Ay3EeFSwX0n0fL!!=3<*-#vKF*3? zBmew~NkW1HK$ega%7E)47WOa3hr~H`4dd6Iu8dBBNOWYEAh-8J zEweU~!|Dq)N}?C61XG6#?eF~%@Pl}Pk=awB?Yn44}tl@#0~z6doa#XIS|q#2kI}*S&yg` z#X%Oq>|U)&-BK&*j$3O-!hc4=ztiylVN3KbCm{EgeayQ;IjrZ=(AyHUmt?phaO`e( zmwR9H-P`u;iB}<3X#^}mpQhjy50TlqKx@s;s;CsU!eJ%~9lkR20!KSDa1m;us|}>j zpit>9I={y6-b`5l_Z(eJf5!nUoBnW*O#V!I>NNgt0xC6WG_vw^_onLR`0_(HTz?X8 z%@!naCgs$vf4)To-#xFG{p3AjbsGe+21!R`@)(13&o7&3Jc}fQZUV7Z)b`p=ogU#M zwi80UscMOa>4sLKP3}y*07$&gZs*+cz{qYgPg7^kP9K#`n^6>a1Qm5JfVq z%1zY9``@^k_3V*YTe8f%D^?TQgjcna2q3ien#pZ}?ObAyq$67#*S5h=572kCwY1=> zwe2-mr}d-sG^(#4_STEl<{_dHTRwHiSL^{JnQ#Xxg47B7%fL$|D>^@WOoZDT^I;8Q zc=3bEH*kCuU$*+Ry5sP^=azOOl%2c`L3M=h82XW%iM^N!zb4allWi<<0RREvKq9XC z0b%+6{pMz&pblkX3JDwkoK`30&hE`0e{yPMpqbSjGJ!_(k{odO4NmiiflYl)?-T-> z#8X9%&2Bx^f^U7wqv-=|I~Oj*>TxAtP)d6J6o zE{cOjWAE8l62qCeFxorvp)i`Upo^e$NL??5f>`7*b-X#HfwV?%qwm^5|0CvV1tc2H z3+c|fTcoDbZ}_Ibo#mVmgE`t1lu<^t+o2`bEX{Z9K!HRW4NhxiOI^ec7p#)Oy*n}30OAOh8l zBaT08Q+~)U`QqoByMh@Je+|4)gszB#`d|zJ(fQ9!bxeJC!2R#=@lIGx8Non*=Okzm z*_Vo7v9M;a%wQuO9LiLFGzJD)!K%gfq4{6{ovbq*{6Q$JM3U42R5_RqsVT)@AxVm{ zJQ-OB7$>-VP{DQBm8DO<*p3Lsvx2*K9p9(5-@2Ew z`*m`E;UOe%7=XkSEy+e1W$JnI^Oo>B`Zh8Q&lCkVGW^J+Tnmc|6P*a4v+)tJi9~=> zK{U*m4cQh((dvw7;dKWbb~Zr)+!eW5l>4Yw(iX*#UK$b|6Jcu8G4v^}36Ypn)nK0~ zkOZLw_$8ZY=5*q4p1($DT<+{eGB)a73iI2~e7m;KW5E!M>Yx+Jw;iSiQk5wJ;`n-J zkzt2|N*1HaiH1=?q0iS=Pd^3C4U!nzB=nkC0=ispZ*{Pq`HYLzza^R49-_s?O@x-*@95C0wI6rnI%NDoyR_;ZUF${VY<*#Y4E!bOcxYD z2ji~+BTp7SGkod)EiIpZf8r=QNql1U=trNUPg&|P5ZEKJ`>^Z$a9T>kPUrbUFzl#p z4N^3Z8vKR@(7S!7Mh5&fOjV|Cp4PpX{u}^bQ~tJD)#G89D8e0W+R!F{`g5bV@yNep z|AXdbUGYcya-@0jyt+-UzM*<+In?I+aI_>+fsGF0qv6KnuCjvb!#wmEP?oHL{5O zmiiUic_G;~5I|_R$#u1 zv$OLiY#>?rRZzY*Ha=EcjV*{30ul?S{-WV4nDKMuWt4o%pwz~cM&ToES4FQV?j z0gXq#V*jroQ+Ty~D~)EC$A8an0KwLm;I0j!)ysM3Q#N;O3#}mbY7iz-J>jWD>B(WV zIv>Lqhqe5*Op5PF84ty@qKe4yg2;i9<<|jH1h9B!Q31kt%5EFgI^UWnQ)*`9m3p4K z1%2<{eBEd}b=W}b7}29GOkk=6T#E+dIp9$OUGS`*sAD>hcuKiUvKdcc-%2bqJ?+Dh z0Mi#kX-W;WsDRlIky|x~Lsp(nI%Ni0TUnclf>wn$wvg4G_E`)jc(D(dA=~MJh-A58 z@v95O;qbplqULU*tbk+7e@a}%N_M|6CyPE%pP{ul*t1;t5W`S&8yA^eZIvplT_mOW z>%Ad(91G}SCN)iT7-MO*2oZ`E8H3GL#sp-Rz`gYtKnODDVi&4ELtVgpGjmZwEEuQB zn1tg&hc8m-i%%1-sq)sHRwwUl`T6rFmpH+t(AsZr@3PeK0c^ThASt_*leKXT{rykh zkDESyeCcTf^j27A803Ar20)=IAZ3;bjnq)Y96b!-jV(&i`t-W48q@M@jI2= zOXCA1gN9PGHM_vXj7%PXnk+!aUqj$RCw;JzX`kWWDMOP*eG8$}2raLY`DM@ymw{i4 zhb9Yfxc}Gsq~OI>*ilASK6y^xdf9h>8o$a_OIS)ZRpa&z&$)FHo{ZdR>Do5(GX8yX zO1!a+btCNg7N2S(Jxm;>_p5K13-n2vMDo z5;Q(1#D7HWWCR{3jE-YPok*54Fx*cCDQX&=<>DX>|6MdUi<{}s3_wj}H0prQ zZ^y8uzzWzldVMGMI*yWIo>Kg0sxQJK9EK`ku4; zR@_V0pNXTt)uJlqNCwv5L%u^?U4@b|@~HE7jX$;g&;iT1P~Zbu^s%qG%l_b+S26P~ zV`ZuYDdY1j9a3$}-!~z=uB#?F9sOxCY%0@}(^;Q8l^YD|o1u%k_`NN-y`dQm(A6e0%XE*Qa8J6n4q3h< z4fL3k!}ypFHju`doj7qIXff>9&1mvZ>Y-6vZNPO1)gSjRR)>#!A8nN3g6oLkcPYZ( z?^dc~ne=(xEPUs8i>PfDbOao^9kX~Yb0K}#9UBfkQ)h$t-^taK9nC@6^UGVKI|Nc5 zK?OM;RvM8xkl&nv^*ZN3@h?L}59SUICj-zHuw$#-oWn!wFQFR zT1GYV+})Z=tXR-GU;(hv%^#zHR2^o}xWsw|3K}%`uVtogr-<;C)iwMxgS_jru}y;P*h2sddBovG1o7KB&jmQlVWDck1!A9t64-g8 zEjj(9Rd=OLiE0Ai&sBJaC{+{)8Dr=n{x~QMhY|5oHbv>PPyl}>jYR?gKK#Qz!xmxo zjnW^(0h)Mf_A#R2VJWYE`0+vkbVEleL8ypQnT=+n;0&)U+MLc`eY9`B^u&`1n2=UIq+pe}iTaVT)G#WQd&`*801Ve@H4= zcQc-|)>emR!@y&P@EEUpIrPa<(CBH&XsIpR^I^=4RFK#}v1 zERbc@8!829&-qJmos7vCbo_l~S0#L-;ltv&$O1(v4_QhT@fF{2L;z|cadVh{Gg+IL zuW4HvM-pcf*)x!uC&`Z$zqNA_Il~TAB8R4W4pv^DFHQcd_xsN5Kp=At5x+kUyMCPQ z?|W)4x0=I{9~KsC9vUG^IR*7$ZyB6rFD~$=vRP%TI9XL}?5~|4S&RyP9Sy9n$Q?^7 z`Y|#>3WRW%sYPdW128vukLPa*qI6xK8q3ba)#4m%svIL+@4f9_$=gjdu&~}TKJ$Dc z`{rtvta}>)dW$nS&(X8HRU_^d9x&20^0a3o%4|zeznLt36k~}-5v?vo-5F}ZFzIT- zfo@>#s-E&sROrB$7%5dgblMBKnU2!;tY@7i5*}g~4nS~Uz`dTcAR%RaHcig`IN>#w zU)p*(>QBTLH@lZ=ep`A_ zT39>TFaV8a+Ae}&^!8+8=L<>=)jWQ`e>H+K1mvB+5PEf!DLVb59#PU5wgWw=Kd>^U z^S;FL$ETjJpv&FaxyLDnk8gugYZmKblb4U!uPA_3LZsBa}z%4>USU zt}z$#&}hC`COn38O1ILD<=4bujB$k+1xGl?#ic7aY{M+(NHg`07_J7<1$|0sR3^{L zuS95KP0znp3htwoh-Omcax4CJFM4dGj!*inzwWzS^yA-87@ftgH6GLPWW7a063e72 z;)}4x@>oFbNygB(_>koxjBN^SNZ2%2#b8LUQ~8G_{5~$}Pm{4mXcJ3(*{jv+#|}yb zPS!AoFP~!XRnGBVlh`VzzH#tvyj%_}(jpIBi1ypp&Y+0T6msk5;f5YvWM$!RxnI6t zrWsrcy|ui*|An&}=*}K+uk5#%wA#o~j~i(`$$VX{B`-hkV$*F1R7vdC=wYs!`UQ#WtEsJLhd(+pg1SVm&Q+hOzBWr*QeFSRVtJ^r&s+Ld%s0>mQ6sN zRXU%ov@6jl=_ji26Tn8)H8iAHNE9hYaNQgNObhy~UQB##eh7 zf$uq4tOnjE^LAI4msdXp3A#CtqSP~8m_u$phtv}apOkfn6aU;bVP+H2eU0jD6b~WN z`Hs7q3#8T1YwWjIJY@HlVYi*hJd2YBQjC$%&;1CM;RMnx!ZO91cfKw%q(&&sQKgZK zmGs(Fvu0pQGUQ_U8kO1m@XGyhv1N(|X!4e*hU8{X{|ygTzChr^tQC>>CF~qGlVc3n%s@nJK|qNV}pdrI7nm`iXSq#IV&{X(7{t}HZkQtro;C72u{8oxZNS` zr?XEf&M9AID`8ar1$k7Cw576X;lvx>tn<{V;9~PzhDUhSqEObz(hOr#Rg)B=`kZ85 zl^x+su8EySsUn|CUWKJ}o}?df#)Qug%Z=H}M(yF{9`cCwD9c=v}qMBodgEhN<&=hB&P|2L|25&~ks zD0bcixMPHBtpk>V$1Q1L_#RPhv{jkpRys5xtk2y9Z1Tb}MypM+iDIw4vA!+iZ*bM4 zZ)?A-!~W42$kH-$yUHy$IX!~5$4rer(oc66 z(YME_P>t&9Q;`2~PlApX^RGNa+3yw26)#Y_lR;C~&|Qqq>dL08a)7?4#bjTv$f@k` z57!8$O-z!X$RRxB9KrBP?+#OY;X?%QDOEeFknA5jw5YN+bxTvrna6+D35LIM)2ix` zsl2@agFKV9HmM)fLIR@e)uC7h`#)5UFb};0j=z7FK8cw?T{vX8s1pF3fXRQSg;K3aCAB*5Wq$)&YBj(SqHV2hhh#|q`hC8EJ* zvhd|xmN&(?2#IG5{1ry`GxIZDq}}^(Y-t$~=ABY`bVDSI)Hn6$y{D>AEM!eI1X7lE zOwr{-Ts3tjHxK0o68+Z`f{hHNEDR?M0uzuCc%}pG7NnFdUu>Bl#1swKkWo?HF^3l_ z;CHy7%mwxVAFgGiY9=fx8dF$v_Gn~k3J5GT+;nX)Pag>v4;SYYxXqI1OfZotmQ_NV z5$jiJKN(o}#%X{`{maB>Z6@XCMCuugD(Uo)NZhb#u%XL@0eed(dXQZWKUTE9=XNIY zz8i+{9dT2_=a`*uL`U+`p%B@G}J0;{dr9t|`(mD!B@_&>(-Y+uDGnrJA64I3+ z6My+~t#b($cBgU^=O8FW7#YDP>4R}r)Lr;3N3Ha;{#^;gzhTl=e#lTNY0;FEe6W8h zx*411WBwVv$yWj-E0B5{S?`;1ao>oE<`$iTm&qWf4(-Ax^ z`DG!4yt1GdY&@n%P0Sufo)Z#TRpyH?HO)}&5UJU!^)tcrnp!@WnhK6yPH8V&^`EO3 zIu~n>i2JpiHmOs7dkcJiDDEt#dqKIErrH0^m@9vAg=D-}HaAwjL23@t`0?H+jlv#1 z%0A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 KMNUMnLSTX^N7_UH literal 0 HcmV?d00001 diff --git a/assets/images/logo.png b/assets/images/logo.png index 6fc6dab37ca83bd0798e5cc113d923de85b0015c..08b5970a98130f5026ebf48485c571c8bf934d12 100644 GIT binary patch literal 3448 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 literal 8188 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 WhileLoopII(int n) { int res = 0; int i = 1; // 初始化条件变量 - // 循环求和 1, 2, 4, 5... + // 循环求和 1, 4, 10, ... while (i <= n) { res += i; // 更新条件变量 diff --git a/en/assets/images/logo.png b/en/assets/images/logo.png index 6fc6dab37ca83bd0798e5cc113d923de85b0015c..08b5970a98130f5026ebf48485c571c8bf934d12 100644 GIT binary patch literal 3448 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 literal 8188 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 WhileLoopII(int n) { int res = 0; int i = 1; // 初始化条件变量 - // 循环求和 1, 2, 4, 5... + // 循环求和 1, 4, 10, ... while (i <= n) { res += i; // 更新条件变量 diff --git a/en/index.html b/en/index.html index 52442cf6a..7bfa50081 100644 --- a/en/index.html +++ b/en/index.html @@ -1367,8 +1367,7 @@
-

"Chase the wind and moon, never stopping"

-

"Beyond the plains, there are spring mountains"

+

"Knowledge increases by sharing."


diff --git a/en/search/search_index.json b/en/search/search_index.json index 3d516bfbd..1fe0e822a 100644 --- a/en/search/search_index.json +++ b/en/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"Hello Algo

Data Structures and Algorithms Crash Course with Animated Illustrations and Off-the-Shelf Code

Dive In Clone Repo Get PDF

The English edition is brewing...

Feel free to engage in Chinese-to-English translation and pull request review! For guidelines, please see #914.

Quote

\"An easy-to-understand book on data structures and algorithms, which guides readers to learn by minds-on and hands-on. Strongly recommended for algorithm beginners!\"

\u2014\u2014 Junhui Deng, Professor of Computer Science, Tsinghua University

Quote

\"If I had 'Hello Algo' when I was learning data structures and algorithms, it would have been 10 times easier!\"

\u2014\u2014 Mu Li, Senior Principal Scientist, Amazon

Animated illustrations

Easy to understandSmooth learning curve

\"A picture is worth a thousand words.\"

Off-the-Shelf Code

Multi programming languagesRun with one click

\"Talk is cheap. Show me the code.\"

Learning Together

Discussion and questions welcomeReaders progress together

\"Chase the wind and moon, never stopping\"

\"Beyond the plains, there are spring mountains\"

Preface

Two years ago, I shared the \"Sword Offer\" series of problem solutions on LeetCode, which received much love and support from many students. During my interactions with readers, the most common question I encountered was \"How to get started with algorithms.\" Gradually, I developed a deep interest in this question.

Blindly solving problems seems to be the most popular method, being simple, direct, and effective. However, problem-solving is like playing a \"Minesweeper\" game, where students with strong self-learning abilities can successfully clear the mines one by one, but those with insufficient foundations may end up bruised from explosions, retreating step by step in frustration. Thoroughly reading textbooks is also common, but for students aiming for job applications, the energy consumed by graduation, resume submissions, and preparing for written tests and interviews makes tackling thick books a daunting challenge.

If you are facing similar troubles, then you are lucky to have found this book. This book is my answer to this question, not necessarily the best solution, but at least an active attempt. Although this book won't directly land you an Offer, it will guide you through the \"knowledge map\" of data structures and algorithms, help you understand the shape, size, and distribution of different \"mines,\" and equip you with various \"demining methods.\" With these skills, I believe you can more comfortably solve problems and read literature, gradually building a complete knowledge system.

I deeply agree with Professor Feynman's saying: \"Knowledge isn't free. You have to pay attention.\" In this sense, this book is not entirely \"free.\" To not disappoint the precious \"attention\" you pay to this book, I will do my utmost, investing the greatest \"attention\" to complete the creation of this book.

Author

Yudong Jin(Krahets), Senior Algorithm Engineer in a top tech company, Master's degree from Shanghai Jiao Tong University. The highest-read blogger across the entire LeetCode, his published \"Illustration of Algorithm Data Structures\" has been subscribed to by over 300k.

Contribution

This book is continuously improved with the joint efforts of many contributors from the open-source community. Thanks to each writer who invested their time and energy, listed in the order generated by GitHub:

The code review work for this book was completed by codingonion, Gonglja, gvenusleo, hpstory, justin\u2010tse, krahets, night-cruise, nuomi1, and Reanon (listed in alphabetical order). Thanks to them for their time and effort, ensuring the standardization and uniformity of the code in various languages.

codingonionRust, Zig GongljaC, C++ gvenusleoDart hpstoryC# justin-tseJS, TS krahetsJava, Python night-cruiseRust nuomi1Swift ReanonGo, C"},{"location":"chapter_array_and_linkedlist/","title":"Chapter 4. \u00a0 Arrays and Linked Lists","text":"

Abstract

The world of data structures resembles a sturdy brick wall.

In arrays, envision bricks snugly aligned, each resting seamlessly beside the next, creating a unified formation. Meanwhile, in linked lists, these bricks disperse freely, embraced by vines gracefully knitting connections between them.

"},{"location":"chapter_array_and_linkedlist/#chapter-contents","title":"Chapter Contents","text":"
  • 4.1 \u00a0 Array
  • 4.2 \u00a0 Linked List
  • 4.3 \u00a0 List
  • 4.4 \u00a0 Memory and Cache
  • 4.5 \u00a0 Summary
"},{"location":"chapter_array_and_linkedlist/array/","title":"4.1 \u00a0 Arrays","text":"

An \"array\" is a linear data structure that operates as a lineup of similar items, stored together in a computer's memory in contiguous spaces. It's like a sequence that maintains organized storage. Each item in this lineup has its unique 'spot' known as an \"index\". Please refer to the Figure 4-1 to observe how arrays work and grasp these key terms.

Figure 4-1 \u00a0 Array Definition and Storage Method

"},{"location":"chapter_array_and_linkedlist/array/#411-common-operations-on-arrays","title":"4.1.1 \u00a0 Common Operations on Arrays","text":""},{"location":"chapter_array_and_linkedlist/array/#1-initializing-arrays","title":"1. \u00a0 Initializing Arrays","text":"

Arrays can be initialized in two ways depending on the needs: either without initial values or with specified initial values. When initial values are not specified, most programming languages will set the array elements to \\(0\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig array.py
# Initialize array\narr: list[int] = [0] * 5  # [ 0, 0, 0, 0, 0 ]\nnums: list[int] = [1, 3, 2, 5, 4]\n
array.cpp
/* Initialize array */\n// Stored on stack\nint arr[5];\nint nums[5] = { 1, 3, 2, 5, 4 };\n// Stored on heap (manual memory release needed)\nint* arr1 = new int[5];\nint* nums1 = new int[5] { 1, 3, 2, 5, 4 };\n
array.java
/* Initialize array */\nint[] arr = new int[5]; // { 0, 0, 0, 0, 0 }\nint[] nums = { 1, 3, 2, 5, 4 };\n
array.cs
/* Initialize array */\nint[] arr = new int[5]; // [ 0, 0, 0, 0, 0 ]\nint[] nums = [1, 3, 2, 5, 4];\n
array.go
/* Initialize array */\nvar arr [5]int\n// In Go, specifying the length ([5]int) denotes an array, while not specifying it ([]int) denotes a slice.\n// Since Go's arrays are designed to have compile-time fixed length, only constants can be used to specify the length.\n// For convenience in implementing the extend() method, the Slice will be considered as an Array here.\nnums := []int{1, 3, 2, 5, 4}\n
array.swift
/* Initialize array */\nlet arr = Array(repeating: 0, count: 5) // [0, 0, 0, 0, 0]\nlet nums = [1, 3, 2, 5, 4]\n
array.js
/* Initialize array */\nvar arr = new Array(5).fill(0);\nvar nums = [1, 3, 2, 5, 4];\n
array.ts
/* Initialize array */\nlet arr: number[] = new Array(5).fill(0);\nlet nums: number[] = [1, 3, 2, 5, 4];\n
array.dart
/* Initialize array */\nList<int> arr = List.filled(5, 0); // [0, 0, 0, 0, 0]\nList<int> nums = [1, 3, 2, 5, 4];\n
array.rs
/* Initialize array */\nlet arr: Vec<i32> = vec![0; 5]; // [0, 0, 0, 0, 0]\nlet nums: Vec<i32> = vec![1, 3, 2, 5, 4];\n
array.c
/* Initialize array */\nint arr[5] = { 0 }; // { 0, 0, 0, 0, 0 }\nint nums[5] = { 1, 3, 2, 5, 4 };\n
array.zig
// Initialize array\nvar arr = [_]i32{0} ** 5; // { 0, 0, 0, 0, 0 }\nvar nums = [_]i32{ 1, 3, 2, 5, 4 };\n
"},{"location":"chapter_array_and_linkedlist/array/#2-accessing-elements","title":"2. \u00a0 Accessing Elements","text":"

Elements in an array are stored in contiguous memory spaces, making it simpler to compute each element's memory address. The formula shown in the Figure below aids in determining an element's memory address, utilizing the array's memory address (specifically, the first element's address) and the element's index. This computation streamlines direct access to the desired element.

Figure 4-2 \u00a0 Memory Address Calculation for Array Elements

As observed in the above illustration, array indexing conventionally begins at \\(0\\). While this might appear counterintuitive, considering counting usually starts at \\(1\\), within the address calculation formula, an index is essentially an offset from the memory address. For the first element's address, this offset is \\(0\\), validating its index as \\(0\\).

Accessing elements in an array is highly efficient, allowing us to randomly access any element in \\(O(1)\\) time.

PythonC++JavaC#GoSwiftJSTSDartRustCZig array.py
def random_access(nums: list[int]) -> int:\n    \"\"\"\u968f\u673a\u8bbf\u95ee\u5143\u7d20\"\"\"\n    # \u5728\u533a\u95f4 [0, len(nums)-1] \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    random_index = random.randint(0, len(nums) - 1)\n    # \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    random_num = nums[random_index]\n    return random_num\n
array.cpp
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nint randomAccess(int *nums, int size) {\n    // \u5728\u533a\u95f4 [0, size) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    int randomIndex = rand() % size;\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    int randomNum = nums[randomIndex];\n    return randomNum;\n}\n
array.java
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nint randomAccess(int[] nums) {\n    // \u5728\u533a\u95f4 [0, nums.length) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    int randomIndex = ThreadLocalRandom.current().nextInt(0, nums.length);\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    int randomNum = nums[randomIndex];\n    return randomNum;\n}\n
array.cs
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nint RandomAccess(int[] nums) {\n    Random random = new();\n    // \u5728\u533a\u95f4 [0, nums.Length) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    int randomIndex = random.Next(nums.Length);\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    int randomNum = nums[randomIndex];\n    return randomNum;\n}\n
array.go
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nfunc randomAccess(nums []int) (randomNum int) {\n    // \u5728\u533a\u95f4 [0, nums.length) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    randomIndex := rand.Intn(len(nums))\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    randomNum = nums[randomIndex]\n    return\n}\n
array.swift
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nfunc randomAccess(nums: [Int]) -> Int {\n    // \u5728\u533a\u95f4 [0, nums.count) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    let randomIndex = nums.indices.randomElement()!\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    let randomNum = nums[randomIndex]\n    return randomNum\n}\n
array.js
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nfunction randomAccess(nums) {\n    // \u5728\u533a\u95f4 [0, nums.length) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    const random_index = Math.floor(Math.random() * nums.length);\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    const random_num = nums[random_index];\n    return random_num;\n}\n
array.ts
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nfunction randomAccess(nums: number[]): number {\n    // \u5728\u533a\u95f4 [0, nums.length) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    const random_index = Math.floor(Math.random() * nums.length);\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    const random_num = nums[random_index];\n    return random_num;\n}\n
array.dart
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nint randomAccess(List<int> nums) {\n  // \u5728\u533a\u95f4 [0, nums.length) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n  int randomIndex = Random().nextInt(nums.length);\n  // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n  int randomNum = nums[randomIndex];\n  return randomNum;\n}\n
array.rs
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nfn random_access(nums: &[i32]) -> i32 {\n    // \u5728\u533a\u95f4 [0, nums.len()) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    let random_index = rand::thread_rng().gen_range(0..nums.len());\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    let random_num = nums[random_index];\n    random_num\n}\n
array.c
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nint randomAccess(int *nums, int size) {\n    // \u5728\u533a\u95f4 [0, size) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    int randomIndex = rand() % size;\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    int randomNum = nums[randomIndex];\n    return randomNum;\n}\n
array.zig
// \u968f\u673a\u8bbf\u95ee\u5143\u7d20\nfn randomAccess(nums: []i32) i32 {\n    // \u5728\u533a\u95f4 [0, nums.len) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6574\u6570\n    var randomIndex = std.crypto.random.intRangeLessThan(usize, 0, nums.len);\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    var randomNum = nums[randomIndex];\n    return randomNum;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/array/#3-inserting-elements","title":"3. \u00a0 Inserting Elements","text":"

Array elements are tightly packed in memory, with no space available to accommodate additional data between them. Illustrated in Figure below, inserting an element in the middle of an array requires shifting all subsequent elements back by one position to create room for the new element.

Figure 4-3 \u00a0 Array Element Insertion Example

It's important to note that due to the fixed length of an array, inserting an element will unavoidably result in the loss of the last element in the array. Solutions to address this issue will be explored in the \"List\" chapter.

PythonC++JavaC#GoSwiftJSTSDartRustCZig array.py
def insert(nums: list[int], num: int, index: int):\n    \"\"\"\u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num\"\"\"\n    # \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for i in range(len(nums) - 1, index, -1):\n        nums[i] = nums[i - 1]\n    # \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num\n
array.cpp
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nvoid insert(int *nums, int size, int num, int index) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for (int i = size - 1; i > index; i--) {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
array.java
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nvoid insert(int[] nums, int num, int index) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for (int i = nums.length - 1; i > index; i--) {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
array.cs
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nvoid Insert(int[] nums, int num, int index) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for (int i = nums.Length - 1; i > index; i--) {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
array.go
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nfunc insert(nums []int, num int, index int) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for i := len(nums) - 1; i > index; i-- {\n        nums[i] = nums[i-1]\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num\n}\n
array.swift
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nfunc insert(nums: inout [Int], num: Int, index: Int) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for i in nums.indices.dropFirst(index).reversed() {\n        nums[i] = nums[i - 1]\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num\n}\n
array.js
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nfunction insert(nums, num, index) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for (let i = nums.length - 1; i > index; i--) {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
array.ts
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nfunction insert(nums: number[], num: number, index: number): void {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for (let i = nums.length - 1; i > index; i--) {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
array.dart
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 _num */\nvoid insert(List<int> nums, int _num, int index) {\n  // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n  for (var i = nums.length - 1; i > index; i--) {\n    nums[i] = nums[i - 1];\n  }\n  // \u5c06 _num \u8d4b\u7ed9 index \u5904\u5143\u7d20\n  nums[index] = _num;\n}\n
array.rs
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nfn insert(nums: &mut Vec<i32>, num: i32, index: usize) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for i in (index + 1..nums.len()).rev() {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
array.c
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nvoid insert(int *nums, int size, int num, int index) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for (int i = size - 1; i > index; i--) {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
array.zig
// \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num\nfn insert(nums: []i32, num: i32, index: usize) void {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    var i = nums.len - 1;\n    while (i > index) : (i -= 1) {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/array/#4-deleting-elements","title":"4. \u00a0 Deleting Elements","text":"

Similarly, as depicted in the Figure 4-4 , to delete an element at index \\(i\\), all elements following index \\(i\\) must be moved forward by one position.

Figure 4-4 \u00a0 Array Element Deletion Example

Please note that after deletion, the former last element becomes \"meaningless,\" hence requiring no specific modification.

PythonC++JavaC#GoSwiftJSTSDartRustCZig array.py
def remove(nums: list[int], index: int):\n    \"\"\"\u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20\"\"\"\n    # \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for i in range(index, len(nums) - 1):\n        nums[i] = nums[i + 1]\n
array.cpp
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nvoid remove(int *nums, int size, int index) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for (int i = index; i < size - 1; i++) {\n        nums[i] = nums[i + 1];\n    }\n}\n
array.java
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nvoid remove(int[] nums, int index) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for (int i = index; i < nums.length - 1; i++) {\n        nums[i] = nums[i + 1];\n    }\n}\n
array.cs
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nvoid Remove(int[] nums, int index) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for (int i = index; i < nums.Length - 1; i++) {\n        nums[i] = nums[i + 1];\n    }\n}\n
array.go
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nfunc remove(nums []int, index int) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for i := index; i < len(nums)-1; i++ {\n        nums[i] = nums[i+1]\n    }\n}\n
array.swift
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nfunc remove(nums: inout [Int], index: Int) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for i in nums.indices.dropFirst(index).dropLast() {\n        nums[i] = nums[i + 1]\n    }\n}\n
array.js
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nfunction remove(nums, index) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for (let i = index; i < nums.length - 1; i++) {\n        nums[i] = nums[i + 1];\n    }\n}\n
array.ts
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nfunction remove(nums: number[], index: number): void {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for (let i = index; i < nums.length - 1; i++) {\n        nums[i] = nums[i + 1];\n    }\n}\n
array.dart
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nvoid remove(List<int> nums, int index) {\n  // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n  for (var i = index; i < nums.length - 1; i++) {\n    nums[i] = nums[i + 1];\n  }\n}\n
array.rs
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nfn remove(nums: &mut Vec<i32>, index: usize) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for i in index..nums.len() - 1 {\n        nums[i] = nums[i + 1];\n    }\n}\n
array.c
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\n// \u6ce8\u610f\uff1astdio.h \u5360\u7528\u4e86 remove \u5173\u952e\u8bcd\nvoid removeItem(int *nums, int size, int index) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for (int i = index; i < size - 1; i++) {\n        nums[i] = nums[i + 1];\n    }\n}\n
array.zig
// \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20\nfn remove(nums: []i32, index: usize) void {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    var i = index;\n    while (i < nums.len - 1) : (i += 1) {\n        nums[i] = nums[i + 1];\n    }\n}\n
Visualizing Code

Full Screen >

In summary, the insertion and deletion operations in arrays present the following disadvantages:

  • High Time Complexity: Both insertion and deletion in an array have an average time complexity of \\(O(n)\\), where \\(n\\) is the length of the array.
  • Loss of Elements: Due to the fixed length of arrays, elements that exceed the array's capacity are lost during insertion.
  • Waste of Memory: Initializing a longer array and utilizing only the front part results in \"meaningless\" end elements during insertion, leading to some wasted memory space.
"},{"location":"chapter_array_and_linkedlist/array/#5-traversing-arrays","title":"5. \u00a0 Traversing Arrays","text":"

In most programming languages, we can traverse an array either by using indices or by directly iterating over each element:

PythonC++JavaC#GoSwiftJSTSDartRustCZig array.py
def traverse(nums: list[int]):\n    \"\"\"\u904d\u5386\u6570\u7ec4\"\"\"\n    count = 0\n    # \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for i in range(len(nums)):\n        count += nums[i]\n    # \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for num in nums:\n        count += num\n    # \u540c\u65f6\u904d\u5386\u6570\u636e\u7d22\u5f15\u548c\u5143\u7d20\n    for i, num in enumerate(nums):\n        count += nums[i]\n        count += num\n
array.cpp
/* \u904d\u5386\u6570\u7ec4 */\nvoid traverse(int *nums, int size) {\n    int count = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for (int i = 0; i < size; i++) {\n        count += nums[i];\n    }\n}\n
array.java
/* \u904d\u5386\u6570\u7ec4 */\nvoid traverse(int[] nums) {\n    int count = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for (int i = 0; i < nums.length; i++) {\n        count += nums[i];\n    }\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for (int num : nums) {\n        count += num;\n    }\n}\n
array.cs
/* \u904d\u5386\u6570\u7ec4 */\nvoid Traverse(int[] nums) {\n    int count = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for (int i = 0; i < nums.Length; i++) {\n        count += nums[i];\n    }\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    foreach (int num in nums) {\n        count += num;\n    }\n}\n
array.go
/* \u904d\u5386\u6570\u7ec4 */\nfunc traverse(nums []int) {\n    count := 0\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for i := 0; i < len(nums); i++ {\n        count += nums[i]\n    }\n    count = 0\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for _, num := range nums {\n        count += num\n    }\n    // \u540c\u65f6\u904d\u5386\u6570\u636e\u7d22\u5f15\u548c\u5143\u7d20\n    for i, num := range nums {\n        count += nums[i]\n        count += num\n    }\n}\n
array.swift
/* \u904d\u5386\u6570\u7ec4 */\nfunc traverse(nums: [Int]) {\n    var count = 0\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for i in nums.indices {\n        count += nums[i]\n    }\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for num in nums {\n        count += num\n    }\n}\n
array.js
/* \u904d\u5386\u6570\u7ec4 */\nfunction traverse(nums) {\n    let count = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for (let i = 0; i < nums.length; i++) {\n        count += nums[i];\n    }\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for (const num of nums) {\n        count += num;\n    }\n}\n
array.ts
/* \u904d\u5386\u6570\u7ec4 */\nfunction traverse(nums: number[]): void {\n    let count = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for (let i = 0; i < nums.length; i++) {\n        count += nums[i];\n    }\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for (const num of nums) {\n        count += num;\n    }\n}\n
array.dart
/* \u904d\u5386\u6570\u7ec4\u5143\u7d20 */\nvoid traverse(List<int> nums) {\n  int count = 0;\n  // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n  for (var i = 0; i < nums.length; i++) {\n    count += nums[i];\n  }\n  // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n  for (int _num in nums) {\n    count += _num;\n  }\n  // \u901a\u8fc7 forEach \u65b9\u6cd5\u904d\u5386\u6570\u7ec4\n  nums.forEach((_num) {\n    count += _num;\n  });\n}\n
array.rs
/* \u904d\u5386\u6570\u7ec4 */\nfn traverse(nums: &[i32]) {\n    let mut _count = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for i in 0..nums.len() {\n        _count += nums[i];\n    }\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for num in nums {\n        _count += num;\n    }\n}\n
array.c
/* \u904d\u5386\u6570\u7ec4 */\nvoid traverse(int *nums, int size) {\n    int count = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for (int i = 0; i < size; i++) {\n        count += nums[i];\n    }\n}\n
array.zig
// \u904d\u5386\u6570\u7ec4\nfn traverse(nums: []i32) void {\n    var count: i32 = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    var i: i32 = 0;\n    while (i < nums.len) : (i += 1) {\n        count += nums[i];\n    }\n    count = 0;\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for (nums) |num| {\n        count += num;\n    }\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/array/#6-finding-elements","title":"6. \u00a0 Finding Elements","text":"

Locating a specific element within an array involves iterating through the array, checking each element to determine if it matches the desired value.

Because arrays are linear data structures, this operation is commonly referred to as \"linear search.\"

PythonC++JavaC#GoSwiftJSTSDartRustCZig array.py
def find(nums: list[int], target: int) -> int:\n    \"\"\"\u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20\"\"\"\n    for i in range(len(nums)):\n        if nums[i] == target:\n            return i\n    return -1\n
array.cpp
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nint find(int *nums, int size, int target) {\n    for (int i = 0; i < size; i++) {\n        if (nums[i] == target)\n            return i;\n    }\n    return -1;\n}\n
array.java
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nint find(int[] nums, int target) {\n    for (int i = 0; i < nums.length; i++) {\n        if (nums[i] == target)\n            return i;\n    }\n    return -1;\n}\n
array.cs
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nint Find(int[] nums, int target) {\n    for (int i = 0; i < nums.Length; i++) {\n        if (nums[i] == target)\n            return i;\n    }\n    return -1;\n}\n
array.go
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nfunc find(nums []int, target int) (index int) {\n    index = -1\n    for i := 0; i < len(nums); i++ {\n        if nums[i] == target {\n            index = i\n            break\n        }\n    }\n    return\n}\n
array.swift
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nfunc find(nums: [Int], target: Int) -> Int {\n    for i in nums.indices {\n        if nums[i] == target {\n            return i\n        }\n    }\n    return -1\n}\n
array.js
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nfunction find(nums, target) {\n    for (let i = 0; i < nums.length; i++) {\n        if (nums[i] === target) return i;\n    }\n    return -1;\n}\n
array.ts
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nfunction find(nums: number[], target: number): number {\n    for (let i = 0; i < nums.length; i++) {\n        if (nums[i] === target) {\n            return i;\n        }\n    }\n    return -1;\n}\n
array.dart
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nint find(List<int> nums, int target) {\n  for (var i = 0; i < nums.length; i++) {\n    if (nums[i] == target) return i;\n  }\n  return -1;\n}\n
array.rs
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nfn find(nums: &[i32], target: i32) -> Option<usize> {\n    for i in 0..nums.len() {\n        if nums[i] == target {\n            return Some(i);\n        }\n    }\n    None\n}\n
array.c
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nint find(int *nums, int size, int target) {\n    for (int i = 0; i < size; i++) {\n        if (nums[i] == target)\n            return i;\n    }\n    return -1;\n}\n
array.zig
// \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20\nfn find(nums: []i32, target: i32) i32 {\n    for (nums, 0..) |num, i| {\n        if (num == target) return @intCast(i);\n    }\n    return -1;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/array/#7-expanding-arrays","title":"7. \u00a0 Expanding Arrays","text":"

In complex system environments, ensuring the availability of memory space after an array for safe capacity extension becomes challenging. Consequently, in most programming languages, the length of an array is immutable.

To expand an array, it's necessary to create a larger array and then copy the elements from the original array. This operation has a time complexity of \\(O(n)\\) and can be time-consuming for large arrays. The code are as follows:

PythonC++JavaC#GoSwiftJSTSDartRustCZig array.py
def extend(nums: list[int], enlarge: int) -> list[int]:\n    \"\"\"\u6269\u5c55\u6570\u7ec4\u957f\u5ea6\"\"\"\n    # \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    res = [0] * (len(nums) + enlarge)\n    # \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for i in range(len(nums)):\n        res[i] = nums[i]\n    # \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res\n
array.cpp
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nint *extend(int *nums, int size, int enlarge) {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    int *res = new int[size + enlarge];\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for (int i = 0; i < size; i++) {\n        res[i] = nums[i];\n    }\n    // \u91ca\u653e\u5185\u5b58\n    delete[] nums;\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res;\n}\n
array.java
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nint[] extend(int[] nums, int enlarge) {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    int[] res = new int[nums.length + enlarge];\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for (int i = 0; i < nums.length; i++) {\n        res[i] = nums[i];\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res;\n}\n
array.cs
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nint[] Extend(int[] nums, int enlarge) {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    int[] res = new int[nums.Length + enlarge];\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for (int i = 0; i < nums.Length; i++) {\n        res[i] = nums[i];\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res;\n}\n
array.go
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nfunc extend(nums []int, enlarge int) []int {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    res := make([]int, len(nums)+enlarge)\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for i, num := range nums {\n        res[i] = num\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res\n}\n
array.swift
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nfunc extend(nums: [Int], enlarge: Int) -> [Int] {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    var res = Array(repeating: 0, count: nums.count + enlarge)\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for i in nums.indices {\n        res[i] = nums[i]\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res\n}\n
array.js
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\n// \u8bf7\u6ce8\u610f\uff0cJavaScript \u7684 Array \u662f\u52a8\u6001\u6570\u7ec4\uff0c\u53ef\u4ee5\u76f4\u63a5\u6269\u5c55\n// \u4e3a\u4e86\u65b9\u4fbf\u5b66\u4e60\uff0c\u672c\u51fd\u6570\u5c06 Array \u770b\u4f5c\u957f\u5ea6\u4e0d\u53ef\u53d8\u7684\u6570\u7ec4\nfunction extend(nums, enlarge) {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    const res = new Array(nums.length + enlarge).fill(0);\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for (let i = 0; i < nums.length; i++) {\n        res[i] = nums[i];\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res;\n}\n
array.ts
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\n// \u8bf7\u6ce8\u610f\uff0cTypeScript \u7684 Array \u662f\u52a8\u6001\u6570\u7ec4\uff0c\u53ef\u4ee5\u76f4\u63a5\u6269\u5c55\n// \u4e3a\u4e86\u65b9\u4fbf\u5b66\u4e60\uff0c\u672c\u51fd\u6570\u5c06 Array \u770b\u4f5c\u957f\u5ea6\u4e0d\u53ef\u53d8\u7684\u6570\u7ec4\nfunction extend(nums: number[], enlarge: number): number[] {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    const res = new Array(nums.length + enlarge).fill(0);\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for (let i = 0; i < nums.length; i++) {\n        res[i] = nums[i];\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res;\n}\n
array.dart
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nList<int> extend(List<int> nums, int enlarge) {\n  // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n  List<int> res = List.filled(nums.length + enlarge, 0);\n  // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n  for (var i = 0; i < nums.length; i++) {\n    res[i] = nums[i];\n  }\n  // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n  return res;\n}\n
array.rs
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nfn extend(nums: Vec<i32>, enlarge: usize) -> Vec<i32> {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    let mut res: Vec<i32> = vec![0; nums.len() + enlarge];\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\n    for i in 0..nums.len() {\n        res[i] = nums[i];\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    res\n}\n
array.c
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nint *extend(int *nums, int size, int enlarge) {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    int *res = (int *)malloc(sizeof(int) * (size + enlarge));\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for (int i = 0; i < size; i++) {\n        res[i] = nums[i];\n    }\n    // \u521d\u59cb\u5316\u6269\u5c55\u540e\u7684\u7a7a\u95f4\n    for (int i = size; i < size + enlarge; i++) {\n        res[i] = 0;\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res;\n}\n
array.zig
// \u6269\u5c55\u6570\u7ec4\u957f\u5ea6\nfn extend(mem_allocator: std.mem.Allocator, nums: []i32, enlarge: usize) ![]i32 {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    var res = try mem_allocator.alloc(i32, nums.len + enlarge);\n    @memset(res, 0);\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    std.mem.copy(i32, res, nums);\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/array/#412-advantages-and-limitations-of-arrays","title":"4.1.2 \u00a0 Advantages and Limitations of Arrays","text":"

Arrays are stored in contiguous memory spaces and consist of elements of the same type. This approach provides substantial prior information that systems can leverage to optimize the efficiency of data structure operations.

  • High Space Efficiency: Arrays allocate a contiguous block of memory for data, eliminating the need for additional structural overhead.
  • Support for Random Access: Arrays allow \\(O(1)\\) time access to any element.
  • Cache Locality: When accessing array elements, the computer not only loads them but also caches the surrounding data, utilizing high-speed cache to enchance subsequent operation speeds.

However, continuous space storage is a double-edged sword, with the following limitations:

  • Low Efficiency in Insertion and Deletion: As arrays accumulate many elements, inserting or deleting elements requires shifting a large number of elements.
  • Fixed Length: The length of an array is fixed after initialization. Expanding an array requires copying all data to a new array, incurring significant costs.
  • Space Wastage: If the allocated array size exceeds the what is necessary, the extra space is wasted.
"},{"location":"chapter_array_and_linkedlist/array/#413-typical-applications-of-arrays","title":"4.1.3 \u00a0 Typical Applications of Arrays","text":"

Arrays are fundamental and widely used data structures. They find frequent application in various algorithms and serve in the implementation of complex data structures.

  • Random Access: Arrays are ideal for storing data when random sampling is required. By generating a random sequence based on indices, we can achieve random sampling efficiently.
  • Sorting and Searching: Arrays are the most commonly used data structure for sorting and searching algorithms. Techniques like quick sort, merge sort, binary search, etc., are primarily operate on arrays.
  • Lookup Tables: Arrays serve as efficient lookup tables for quick element or relationship retrieval. For instance, mapping characters to ASCII codes becomes seamless by using the ASCII code values as indices and storing corresponding elements in the array.
  • Machine Learning: Within the domain of neural networks, arrays play a pivotal role in executing crucial linear algebra operations involving vectors, matrices, and tensors. Arrays serve as the primary and most extensively used data structure in neural network programming.
  • Data Structure Implementation: Arrays serve as the building blocks for implementing various data structures like stacks, queues, hash tables, heaps, graphs, etc. For instance, the adjacency matrix representation of a graph is essentially a two-dimensional array.
"},{"location":"chapter_array_and_linkedlist/linked_list/","title":"4.2 \u00a0 Linked Lists","text":"

Memory space is a common resource for all programs. In a complex system environment, free memory space can be scattered throughout memory. We know that the memory space for storing an array must be contiguous, and when the array is very large, it may not be possible to provide such a large contiguous space. This is where the flexibility advantage of linked lists becomes apparent.

A \"linked list\" is a linear data structure where each element is a node object, and the nodes are connected via \"references\". A reference records the memory address of the next node, allowing access to the next node from the current one.

The design of a linked list allows its nodes to be scattered throughout memory, with no need for contiguous memory addresses.

Figure 4-5 \u00a0 Linked List Definition and Storage Method

Observing the image above, the fundamental unit of a linked list is the \"node\" object. Each node contains two pieces of data: the \"value\" of the node and the \"reference\" to the next node.

  • The first node of a linked list is known as the \"head node\", and the last one is called the \"tail node\".
  • The tail node points to \"null\", which is represented as null in Java, nullptr in C++, and None in Python.
  • In languages that support pointers, like C, C++, Go, and Rust, the aforementioned \"reference\" should be replaced with a \"pointer\".

As shown in the following code, a linked list node ListNode, apart from containing a value, also needs to store a reference (pointer). Therefore, a linked list consumes more memory space than an array for the same amount of data.

PythonC++JavaC#GoSwiftJSTSDartRustCZig
class ListNode:\n    \"\"\"Linked List Node Class\"\"\"\n    def __init__(self, val: int):\n        self.val: int = val               # Node value\n        self.next: ListNode | None = None # Reference to the next node\n
/* Linked List Node Structure */\nstruct ListNode {\n    int val;         // Node value\n    ListNode *next;  // Pointer to the next node\n    ListNode(int x) : val(x), next(nullptr) {}  // Constructor\n};\n
/* Linked List Node Class */\nclass ListNode {\n    int val;        // Node value\n    ListNode next;  // Reference to the next node\n    ListNode(int x) { val = x; }  // Constructor\n}\n
/* Linked List Node Class */\nclass ListNode(int x) {  // Constructor\n    int val = x;         // Node value\n    ListNode? next;      // Reference to the next node\n}\n
/* Linked List Node Structure */\ntype ListNode struct {\n    Val  int       // Node value\n    Next *ListNode // Pointer to the next node\n}\n\n// NewListNode Constructor, creates a new linked list\nfunc NewListNode(val int) *ListNode {\n    return &ListNode{\n        Val:  val,\n        Next: nil,\n    }\n}\n
/* Linked List Node Class */\nclass ListNode {\n    var val: Int // Node value\n    var next: ListNode? // Reference to the next node\n\n    init(x: Int) { // Constructor\n        val = x\n    }\n}\n
/* Linked List Node Class */\nclass ListNode {\n    constructor(val, next) {\n        this.val = (val === undefined ? 0 : val);       // Node value\n        this.next = (next === undefined ? null : next); // Reference to the next node\n    }\n}\n
/* Linked List Node Class */\nclass ListNode {\n    val: number;\n    next: ListNode | null;\n    constructor(val?: number, next?: ListNode | null) {\n        this.val = val === undefined ? 0 : val;        // Node value\n        this.next = next === undefined ? null : next;  // Reference to the next node\n    }\n}\n
/* \u94fe\u8868\u8282\u70b9\u7c7b */\nclass ListNode {\n  int val; // Node value\n  ListNode? next; // Reference to the next node\n  ListNode(this.val, [this.next]); // Constructor\n}\n
use std::rc::Rc;\nuse std::cell::RefCell;\n/* Linked List Node Class */\n#[derive(Debug)]\nstruct ListNode {\n    val: i32, // Node value\n    next: Option<Rc<RefCell<ListNode>>>, // Pointer to the next node\n}\n
/* Linked List Node Structure */\ntypedef struct ListNode {\n    int val;               // Node value\n    struct ListNode *next; // Pointer to the next node\n} ListNode;\n\n/* Constructor */\nListNode *newListNode(int val) {\n    ListNode *node;\n    node = (ListNode *) malloc(sizeof(ListNode));\n    node->val = val;\n    node->next = NULL;\n    return node;\n}\n
// Linked List Node Class\npub fn ListNode(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        val: T = 0, // Node value\n        next: ?*Self = null, // Pointer to the next node\n\n        // Constructor\n        pub fn init(self: *Self, x: i32) void {\n            self.val = x;\n            self.next = null;\n        }\n    };\n}\n
"},{"location":"chapter_array_and_linkedlist/linked_list/#421-common-operations-on-linked-lists","title":"4.2.1 \u00a0 Common Operations on Linked Lists","text":""},{"location":"chapter_array_and_linkedlist/linked_list/#1-initializing-a-linked-list","title":"1. \u00a0 Initializing a Linked List","text":"

Building a linked list involves two steps: initializing each node object and then establishing the references between nodes. Once initialized, we can access all nodes sequentially from the head node via the next reference.

PythonC++JavaC#GoSwiftJSTSDartRustCZig linked_list.py
# Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4\n# Initialize each node\nn0 = ListNode(1)\nn1 = ListNode(3)\nn2 = ListNode(2)\nn3 = ListNode(5)\nn4 = ListNode(4)\n# Build references between nodes\nn0.next = n1\nn1.next = n2\nn2.next = n3\nn3.next = n4\n
linked_list.cpp
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nListNode* n0 = new ListNode(1);\nListNode* n1 = new ListNode(3);\nListNode* n2 = new ListNode(2);\nListNode* n3 = new ListNode(5);\nListNode* n4 = new ListNode(4);\n// Build references between nodes\nn0->next = n1;\nn1->next = n2;\nn2->next = n3;\nn3->next = n4;\n
linked_list.java
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nListNode n0 = new ListNode(1);\nListNode n1 = new ListNode(3);\nListNode n2 = new ListNode(2);\nListNode n3 = new ListNode(5);\nListNode n4 = new ListNode(4);\n// Build references between nodes\nn0.next = n1;\nn1.next = n2;\nn2.next = n3;\nn3.next = n4;\n
linked_list.cs
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nListNode n0 = new(1);\nListNode n1 = new(3);\nListNode n2 = new(2);\nListNode n3 = new(5);\nListNode n4 = new(4);\n// Build references between nodes\nn0.next = n1;\nn1.next = n2;\nn2.next = n3;\nn3.next = n4;\n
linked_list.go
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nn0 := NewListNode(1)\nn1 := NewListNode(3)\nn2 := NewListNode(2)\nn3 := NewListNode(5)\nn4 := NewListNode(4)\n// Build references between nodes\nn0.Next = n1\nn1.Next = n2\nn2.Next = n3\nn3.Next = n4\n
linked_list.swift
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nlet n0 = ListNode(x: 1)\nlet n1 = ListNode(x: 3)\nlet n2 = ListNode(x: 2)\nlet n3 = ListNode(x: 5)\nlet n4 = ListNode(x: 4)\n// Build references between nodes\nn0.next = n1\nn1.next = n2\nn2.next = n3\nn3.next = n4\n
linked_list.js
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nconst n0 = new ListNode(1);\nconst n1 = new ListNode(3);\nconst n2 = new ListNode(2);\nconst n3 = new ListNode(5);\nconst n4 = new ListNode(4);\n// Build references between nodes\nn0.next = n1;\nn1.next = n2;\nn2.next = n3;\nn3.next = n4;\n
linked_list.ts
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nconst n0 = new ListNode(1);\nconst n1 = new ListNode(3);\nconst n2 = new ListNode(2);\nconst n3 = new ListNode(5);\nconst n4 = new ListNode(4);\n// Build references between nodes\nn0.next = n1;\nn1.next = n2;\nn2.next = n3;\nn3.next = n4;\n
linked_list.dart
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nListNode n0 = ListNode(1);\nListNode n1 = ListNode(3);\nListNode n2 = ListNode(2);\nListNode n3 = ListNode(5);\nListNode n4 = ListNode(4);\n// Build references between nodes\nn0.next = n1;\nn1.next = n2;\nn2.next = n3;\nn3.next = n4;\n
linked_list.rs
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nlet n0 = Rc::new(RefCell::new(ListNode { val: 1, next: None }));\nlet n1 = Rc::new(RefCell::new(ListNode { val: 3, next: None }));\nlet n2 = Rc::new(RefCell::new(ListNode { val: 2, next: None }));\nlet n3 = Rc::new(RefCell::new(ListNode { val: 5, next: None }));\nlet n4 = Rc::new(RefCell::new(ListNode { val: 4, next: None }));\n\n// Build references between nodes\nn0.borrow_mut().next = Some(n1.clone());\nn1.borrow_mut().next = Some(n2.clone());\nn2.borrow_mut().next = Some(n3.clone());\nn3.borrow_mut().next = Some(n4.clone());\n
linked_list.c
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nListNode* n0 = newListNode(1);\nListNode* n1 = newListNode(3);\nListNode* n2 = newListNode(2);\nListNode* n3 = newListNode(5);\nListNode* n4 = newListNode(4);\n// Build references between nodes\nn0->next = n1;\nn1->next = n2;\nn2->next = n3;\nn3->next = n4;\n
linked_list.zig
// Initialize linked list\n// Initialize each node\nvar n0 = inc.ListNode(i32){.val = 1};\nvar n1 = inc.ListNode(i32){.val = 3};\nvar n2 = inc.ListNode(i32){.val = 2};\nvar n3 = inc.ListNode(i32){.val = 5};\nvar n4 = inc.ListNode(i32){.val = 4};\n// Build references between nodes\nn0.next = &n1;\nn1.next = &n2;\nn2.next = &n3;\nn3.next = &n4;\n

An array is a single variable, such as the array nums containing elements nums[0], nums[1], etc., while a linked list is composed of multiple independent node objects. We usually refer to the linked list by its head node, as in the linked list n0 in the above code.

"},{"location":"chapter_array_and_linkedlist/linked_list/#2-inserting-a-node","title":"2. \u00a0 Inserting a Node","text":"

Inserting a node in a linked list is very easy. As shown in the image below, suppose we want to insert a new node P between two adjacent nodes n0 and n1. This requires changing only two node references (pointers), with a time complexity of \\(O(1)\\).

In contrast, the time complexity of inserting an element in an array is \\(O(n)\\), which is less efficient with large data volumes.

Figure 4-6 \u00a0 Linked List Node Insertion Example

PythonC++JavaC#GoSwiftJSTSDartRustCZig linked_list.py
def insert(n0: ListNode, P: ListNode):\n    \"\"\"\u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P\"\"\"\n    n1 = n0.next\n    P.next = n1\n    n0.next = P\n
linked_list.cpp
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nvoid insert(ListNode *n0, ListNode *P) {\n    ListNode *n1 = n0->next;\n    P->next = n1;\n    n0->next = P;\n}\n
linked_list.java
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nvoid insert(ListNode n0, ListNode P) {\n    ListNode n1 = n0.next;\n    P.next = n1;\n    n0.next = P;\n}\n
linked_list.cs
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nvoid Insert(ListNode n0, ListNode P) {\n    ListNode? n1 = n0.next;\n    P.next = n1;\n    n0.next = P;\n}\n
linked_list.go
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nfunc insertNode(n0 *ListNode, P *ListNode) {\n    n1 := n0.Next\n    P.Next = n1\n    n0.Next = P\n}\n
linked_list.swift
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nfunc insert(n0: ListNode, P: ListNode) {\n    let n1 = n0.next\n    P.next = n1\n    n0.next = P\n}\n
linked_list.js
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nfunction insert(n0, P) {\n    const n1 = n0.next;\n    P.next = n1;\n    n0.next = P;\n}\n
linked_list.ts
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nfunction insert(n0: ListNode, P: ListNode): void {\n    const n1 = n0.next;\n    P.next = n1;\n    n0.next = P;\n}\n
linked_list.dart
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nvoid insert(ListNode n0, ListNode P) {\n  ListNode? n1 = n0.next;\n  P.next = n1;\n  n0.next = P;\n}\n
linked_list.rs
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\n#[allow(non_snake_case)]\npub fn insert<T>(n0: &Rc<RefCell<ListNode<T>>>, P: Rc<RefCell<ListNode<T>>>) {\n    let n1 =  n0.borrow_mut().next.take();\n    P.borrow_mut().next = n1;\n    n0.borrow_mut().next = Some(P);\n}\n
linked_list.c
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nvoid insert(ListNode *n0, ListNode *P) {\n    ListNode *n1 = n0->next;\n    P->next = n1;\n    n0->next = P;\n}\n
linked_list.zig
// \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P\nfn insert(n0: ?*inc.ListNode(i32), P: ?*inc.ListNode(i32)) void {\n    var n1 = n0.?.next;\n    P.?.next = n1;\n    n0.?.next = P;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/linked_list/#3-deleting-a-node","title":"3. \u00a0 Deleting a Node","text":"

As shown below, deleting a node in a linked list is also very convenient, requiring only the change of one node's reference (pointer).

Note that although node P still points to n1 after the deletion operation is completed, it is no longer accessible when traversing the list, meaning P is no longer part of the list.

Figure 4-7 \u00a0 Linked List Node Deletion

PythonC++JavaC#GoSwiftJSTSDartRustCZig linked_list.py
def remove(n0: ListNode):\n    \"\"\"\u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9\"\"\"\n    if not n0.next:\n        return\n    # n0 -> P -> n1\n    P = n0.next\n    n1 = P.next\n    n0.next = n1\n
linked_list.cpp
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nvoid remove(ListNode *n0) {\n    if (n0->next == nullptr)\n        return;\n    // n0 -> P -> n1\n    ListNode *P = n0->next;\n    ListNode *n1 = P->next;\n    n0->next = n1;\n    // \u91ca\u653e\u5185\u5b58\n    delete P;\n}\n
linked_list.java
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nvoid remove(ListNode n0) {\n    if (n0.next == null)\n        return;\n    // n0 -> P -> n1\n    ListNode P = n0.next;\n    ListNode n1 = P.next;\n    n0.next = n1;\n}\n
linked_list.cs
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nvoid Remove(ListNode n0) {\n    if (n0.next == null)\n        return;\n    // n0 -> P -> n1\n    ListNode P = n0.next;\n    ListNode? n1 = P.next;\n    n0.next = n1;\n}\n
linked_list.go
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nfunc removeItem(n0 *ListNode) {\n    if n0.Next == nil {\n        return\n    }\n    // n0 -> P -> n1\n    P := n0.Next\n    n1 := P.Next\n    n0.Next = n1\n}\n
linked_list.swift
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nfunc remove(n0: ListNode) {\n    if n0.next == nil {\n        return\n    }\n    // n0 -> P -> n1\n    let P = n0.next\n    let n1 = P?.next\n    n0.next = n1\n    P?.next = nil\n}\n
linked_list.js
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nfunction remove(n0) {\n    if (!n0.next) return;\n    // n0 -> P -> n1\n    const P = n0.next;\n    const n1 = P.next;\n    n0.next = n1;\n}\n
linked_list.ts
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nfunction remove(n0: ListNode): void {\n    if (!n0.next) {\n        return;\n    }\n    // n0 -> P -> n1\n    const P = n0.next;\n    const n1 = P.next;\n    n0.next = n1;\n}\n
linked_list.dart
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nvoid remove(ListNode n0) {\n  if (n0.next == null) return;\n  // n0 -> P -> n1\n  ListNode P = n0.next!;\n  ListNode? n1 = P.next;\n  n0.next = n1;\n}\n
linked_list.rs
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\n#[allow(non_snake_case)]\npub fn remove<T>(n0: &Rc<RefCell<ListNode<T>>>) {\n    if n0.borrow().next.is_none() {return};\n    // n0 -> P -> n1\n    let P = n0.borrow_mut().next.take();\n    if let Some(node) = P {\n        let n1 = node.borrow_mut().next.take();\n        n0.borrow_mut().next = n1;\n    }\n}\n
linked_list.c
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\n// \u6ce8\u610f\uff1astdio.h \u5360\u7528\u4e86 remove \u5173\u952e\u8bcd\nvoid removeItem(ListNode *n0) {\n    if (!n0->next)\n        return;\n    // n0 -> P -> n1\n    ListNode *P = n0->next;\n    ListNode *n1 = P->next;\n    n0->next = n1;\n    // \u91ca\u653e\u5185\u5b58\n    free(P);\n}\n
linked_list.zig
// \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9\nfn remove(n0: ?*inc.ListNode(i32)) void {\n    if (n0.?.next == null) return;\n    // n0 -> P -> n1\n    var P = n0.?.next;\n    var n1 = P.?.next;\n    n0.?.next = n1;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/linked_list/#4-accessing-nodes","title":"4. \u00a0 Accessing Nodes","text":"

Accessing nodes in a linked list is less efficient. As mentioned earlier, any element in an array can be accessed in \\(O(1)\\) time. However, in a linked list, the program needs to start from the head node and traverse each node sequentially until it finds the target node. That is, accessing the \\(i\\)-th node of a linked list requires \\(i - 1\\) iterations, with a time complexity of \\(O(n)\\).

PythonC++JavaC#GoSwiftJSTSDartRustCZig linked_list.py
def access(head: ListNode, index: int) -> ListNode | None:\n    \"\"\"\u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9\"\"\"\n    for _ in range(index):\n        if not head:\n            return None\n        head = head.next\n    return head\n
linked_list.cpp
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nListNode *access(ListNode *head, int index) {\n    for (int i = 0; i < index; i++) {\n        if (head == nullptr)\n            return nullptr;\n        head = head->next;\n    }\n    return head;\n}\n
linked_list.java
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nListNode access(ListNode head, int index) {\n    for (int i = 0; i < index; i++) {\n        if (head == null)\n            return null;\n        head = head.next;\n    }\n    return head;\n}\n
linked_list.cs
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nListNode? Access(ListNode? head, int index) {\n    for (int i = 0; i < index; i++) {\n        if (head == null)\n            return null;\n        head = head.next;\n    }\n    return head;\n}\n
linked_list.go
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nfunc access(head *ListNode, index int) *ListNode {\n    for i := 0; i < index; i++ {\n        if head == nil {\n            return nil\n        }\n        head = head.Next\n    }\n    return head\n}\n
linked_list.swift
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nfunc access(head: ListNode, index: Int) -> ListNode? {\n    var head: ListNode? = head\n    for _ in 0 ..< index {\n        if head == nil {\n            return nil\n        }\n        head = head?.next\n    }\n    return head\n}\n
linked_list.js
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nfunction access(head, index) {\n    for (let i = 0; i < index; i++) {\n        if (!head) {\n            return null;\n        }\n        head = head.next;\n    }\n    return head;\n}\n
linked_list.ts
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nfunction access(head: ListNode | null, index: number): ListNode | null {\n    for (let i = 0; i < index; i++) {\n        if (!head) {\n            return null;\n        }\n        head = head.next;\n    }\n    return head;\n}\n
linked_list.dart
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nListNode? access(ListNode? head, int index) {\n  for (var i = 0; i < index; i++) {\n    if (head == null) return null;\n    head = head.next;\n  }\n  return head;\n}\n
linked_list.rs
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\npub fn access<T>(head: Rc<RefCell<ListNode<T>>>, index: i32) -> Rc<RefCell<ListNode<T>>> {\n    if index <= 0 {return head};\n    if let Some(node) = &head.borrow_mut().next {\n        return access(node.clone(), index - 1);\n    }\n    return head;\n}\n
linked_list.c
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nListNode *access(ListNode *head, int index) {\n    for (int i = 0; i < index; i++) {\n        if (head == NULL)\n            return NULL;\n        head = head->next;\n    }\n    return head;\n}\n
linked_list.zig
// \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9\nfn access(node: ?*inc.ListNode(i32), index: i32) ?*inc.ListNode(i32) {\n    var head = node;\n    var i: i32 = 0;\n    while (i < index) : (i += 1) {\n        head = head.?.next;\n        if (head == null) return null;\n    }\n    return head;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/linked_list/#5-finding-nodes","title":"5. \u00a0 Finding Nodes","text":"

Traverse the linked list to find a node with a value equal to target, and output the index of that node in the linked list. This process also falls under linear search. The code is as follows:

PythonC++JavaC#GoSwiftJSTSDartRustCZig linked_list.py
def find(head: ListNode, target: int) -> int:\n    \"\"\"\u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9\"\"\"\n    index = 0\n    while head:\n        if head.val == target:\n            return index\n        head = head.next\n        index += 1\n    return -1\n
linked_list.cpp
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nint find(ListNode *head, int target) {\n    int index = 0;\n    while (head != nullptr) {\n        if (head->val == target)\n            return index;\n        head = head->next;\n        index++;\n    }\n    return -1;\n}\n
linked_list.java
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nint find(ListNode head, int target) {\n    int index = 0;\n    while (head != null) {\n        if (head.val == target)\n            return index;\n        head = head.next;\n        index++;\n    }\n    return -1;\n}\n
linked_list.cs
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nint Find(ListNode? head, int target) {\n    int index = 0;\n    while (head != null) {\n        if (head.val == target)\n            return index;\n        head = head.next;\n        index++;\n    }\n    return -1;\n}\n
linked_list.go
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nfunc findNode(head *ListNode, target int) int {\n    index := 0\n    for head != nil {\n        if head.Val == target {\n            return index\n        }\n        head = head.Next\n        index++\n    }\n    return -1\n}\n
linked_list.swift
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nfunc find(head: ListNode, target: Int) -> Int {\n    var head: ListNode? = head\n    var index = 0\n    while head != nil {\n        if head?.val == target {\n            return index\n        }\n        head = head?.next\n        index += 1\n    }\n    return -1\n}\n
linked_list.js
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nfunction find(head, target) {\n    let index = 0;\n    while (head !== null) {\n        if (head.val === target) {\n            return index;\n        }\n        head = head.next;\n        index += 1;\n    }\n    return -1;\n}\n
linked_list.ts
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nfunction find(head: ListNode | null, target: number): number {\n    let index = 0;\n    while (head !== null) {\n        if (head.val === target) {\n            return index;\n        }\n        head = head.next;\n        index += 1;\n    }\n    return -1;\n}\n
linked_list.dart
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nint find(ListNode? head, int target) {\n  int index = 0;\n  while (head != null) {\n    if (head.val == target) {\n      return index;\n    }\n    head = head.next;\n    index++;\n  }\n  return -1;\n}\n
linked_list.rs
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\npub fn find<T: PartialEq>(head: Rc<RefCell<ListNode<T>>>, target: T, index: i32) -> i32 {\n    if head.borrow().val == target {return index};\n    if let Some(node) = &head.borrow_mut().next {\n        return find(node.clone(), target, index + 1);\n    }\n    return -1;\n}\n
linked_list.c
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nint find(ListNode *head, int target) {\n    int index = 0;\n    while (head) {\n        if (head->val == target)\n            return index;\n        head = head->next;\n        index++;\n    }\n    return -1;\n}\n
linked_list.zig
// \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9\nfn find(node: ?*inc.ListNode(i32), target: i32) i32 {\n    var head = node;\n    var index: i32 = 0;\n    while (head != null) {\n        if (head.?.val == target) return index;\n        head = head.?.next;\n        index += 1;\n    }\n    return -1;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/linked_list/#422-arrays-vs-linked-lists","title":"4.2.2 \u00a0 Arrays vs. Linked Lists","text":"

The following table summarizes the characteristics of arrays and linked lists and compares their operational efficiencies. Since they employ two opposite storage strategies, their properties and operational efficiencies also show contrasting features.

Table 4-1 \u00a0 Efficiency Comparison of Arrays and Linked Lists

Arrays Linked Lists Storage Contiguous Memory Space Dispersed Memory Space Capacity Expansion Fixed Length Flexible Expansion Memory Efficiency Less Memory per Element, Potential Space Wastage More Memory per Element Accessing Elements \\(O(1)\\) \\(O(n)\\) Adding Elements \\(O(n)\\) \\(O(1)\\) Deleting Elements \\(O(n)\\) \\(O(1)\\)"},{"location":"chapter_array_and_linkedlist/linked_list/#423-common-types-of-linked-lists","title":"4.2.3 \u00a0 Common Types of Linked Lists","text":"

As shown in the following image, there are three common types of linked lists.

  • Singly Linked List: This is the regular linked list introduced earlier. The nodes of a singly linked list contain the value and a reference to the next node. The first node is called the head node, and the last node, pointing to null (None), is the tail node.
  • Circular Linked List: If the tail node of a singly linked list points back to the head node (forming a loop), it becomes a circular linked list. In a circular linked list, any node can be considered the head node.
  • Doubly Linked List: Compared to a singly linked list, a doubly linked list stores references in two directions. Its nodes contain references to both the next (successor) and the previous (predecessor) nodes. Doubly linked lists are more flexible as they allow traversal in both directions but require more memory space.
PythonC++JavaC#GoSwiftJSTSDartRustCZig
class ListNode:\n    \"\"\"Bidirectional linked list node class\"\"\"\"\n    def __init__(self, val: int):\n        self.val: int = val                # Node value\n        self.next: ListNode | None = None  # Reference to the successor node\n        self.prev: ListNode | None = None  # Reference to a predecessor node\n
/* Bidirectional linked list node structure */\nstruct ListNode {\n    int val;         // Node value\n    ListNode *next;  // Pointer to the successor node\n    ListNode *prev;  // Pointer to the predecessor node\n    ListNode(int x) : val(x), next(nullptr), prev(nullptr) {}  // Constructor\n};\n
/* Bidirectional linked list node class */\nclass ListNode {\n    int val;        // Node value\n    ListNode next;  // Reference to the next node\n    ListNode prev;  // Reference to the predecessor node\n    ListNode(int x) { val = x; }  // Constructor\n}\n
/* Bidirectional linked list node class */\nclass ListNode(int x) {  // Constructor\n    int val = x;    // Node value\n    ListNode next;  // Reference to the next node\n    ListNode prev;  // Reference to the predecessor node\n}\n
/* Bidirectional linked list node structure */\ntype DoublyListNode struct {\n    Val  int             // Node value\n    Next *DoublyListNode // Pointer to the successor node\n    Prev *DoublyListNode // Pointer to the predecessor node\n}\n\n// NewDoublyListNode initialization\nfunc NewDoublyListNode(val int) *DoublyListNode {\n    return &DoublyListNode{\n        Val:  val,\n        Next: nil,\n        Prev: nil,\n    }\n}\n
/* Bidirectional linked list node class */\nclass ListNode {\n    var val: Int // Node value\n    var next: ListNode? // Reference to the next node\n    var prev: ListNode? // Reference to the predecessor node\n\n    init(x: Int) { // Constructor\n        val = x\n    }\n}\n
/* Bidirectional linked list node class */\nclass ListNode {\n    constructor(val, next, prev) {\n        this.val = val  ===  undefined ? 0 : val;        // Node value\n        this.next = next  ===  undefined ? null : next;  // Reference to the successor node\n        this.prev = prev  ===  undefined ? null : prev;  // Reference to the predecessor node\n    }\n}\n
/* Bidirectional linked list node class */\nclass ListNode {\n    val: number;\n    next: ListNode | null;\n    prev: ListNode | null;\n    constructor(val?: number, next?: ListNode | null, prev?: ListNode | null) {\n        this.val = val  ===  undefined ? 0 : val;        // Node value\n        this.next = next  ===  undefined ? null : next;  // Reference to the successor node\n        this.prev = prev  ===  undefined ? null : prev;  // Reference to the predecessor node\n    }\n}\n
/* Bidirectional linked list node class */\nclass ListNode {\n    int val;        // Node value\n    ListNode next;  // Reference to the next node\n    ListNode prev;  // Reference to the predecessor node\n    ListNode(this.val, [this.next, this.prev]);  // Constructor\n}\n
use std::rc::Rc;\nuse std::cell::RefCell;\n\n/* Bidirectional linked list node type */\n#[derive(Debug)]\nstruct ListNode {\n    val: i32, // Node value\n    next: Option<Rc<RefCell<ListNode>>>, // Pointer to successor node\n    prev: Option<Rc<RefCell<ListNode>>>, // Pointer to predecessor node\n}\n\n/* Constructors */\nimpl ListNode {\n    fn new(val: i32) -> Self {\n        ListNode {\n            val,\n            next: None,\n            prev: None,\n        }\n    }\n}\n
/* Bidirectional linked list node structure */\ntypedef struct ListNode {\n    int val;               // Node value\n    struct ListNode *next; // Pointer to the successor node\n    struct ListNode *prev; // Pointer to the predecessor node\n} ListNode;\n\n/* Constructors */\nListNode *newListNode(int val) {\n    ListNode *node, *next;\n    node = (ListNode *) malloc(sizeof(ListNode));\n    node->val = val;\n    node->next = NULL;\n    node->prev = NULL;\n    return node;\n}\n
// Bidirectional linked list node class\npub fn ListNode(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        val: T = 0, // Node value\n        next: ?*Self = null, // Pointer to the successor node\n        prev: ?*Self = null, // Pointer to the predecessor node\n\n        // Constructor\n        pub fn init(self: *Self, x: i32) void {\n            self.val = x;\n            self.next = null;\n            self.prev = null;\n        }\n    };\n}\n

Figure 4-8 \u00a0 Common Types of Linked Lists

"},{"location":"chapter_array_and_linkedlist/linked_list/#424-typical-applications-of-linked-lists","title":"4.2.4 \u00a0 Typical Applications of Linked Lists","text":"

Singly linked lists are commonly used to implement stacks, queues, hash tables, and graphs.

  • Stacks and Queues: When insertion and deletion operations are performed at one end of the linked list, it exhibits last-in-first-out characteristics, corresponding to a stack. When insertion is at one end and deletion is at the other, it shows first-in-first-out characteristics, corresponding to a queue.
  • Hash Tables: Chaining is one of the mainstream solutions to hash collisions, where all colliding elements are placed in a linked list.
  • Graphs: Adjacency lists are a common way to represent graphs, where each vertex is associated with a linked list. Each element in the list represents other vertices connected to that vertex.

Doubly linked lists are commonly used in scenarios that require quick access to the previous and next elements.

  • Advanced Data Structures: For example, in red-black trees and B-trees, we need to access a node's parent, which can be achieved by storing a reference to the parent node in each node, similar to a doubly linked list.
  • Browser History: In web browsers, when a user clicks the forward or backward button, the browser needs to know the previously and next visited web pages. The properties of a doubly linked list make this operation simple.
  • LRU Algorithm: In Least Recently Used (LRU) cache eviction algorithms, we need to quickly find the least recently used data and support rapid addition and deletion of nodes. Here, using a doubly linked list is very appropriate.

Circular linked lists are commonly used in scenarios requiring periodic operations, such as resource scheduling in operating systems.

  • Round-Robin Scheduling Algorithm: In operating systems, the round-robin scheduling algorithm is a common CPU scheduling algorithm that cycles through a group of processes. Each process is assigned a time slice, and when it expires, the CPU switches to the next process. This circular operation can be implemented using a circular linked list.
  • Data Buffers: Circular linked lists may also be used in some data buffer implementations. For instance, in audio and video players, the data stream might be divided into multiple buffer blocks placed in a circular linked list to achieve seamless playback.
"},{"location":"chapter_array_and_linkedlist/list/","title":"4.3 \u00a0 List","text":"

A \"list\" is an abstract data structure concept, representing an ordered collection of elements. It supports operations like element access, modification, addition, deletion, and traversal, without requiring users to consider capacity limitations. Lists can be implemented based on linked lists or arrays.

  • A linked list naturally functions as a list, supporting operations for adding, deleting, searching, and modifying elements, and can dynamically adjust its size.
  • Arrays also support these operations, but due to their fixed length, they can be considered as a list with a length limit.

When using arrays to implement lists, the fixed length property reduces the practicality of the list. This is because we often cannot determine in advance how much data needs to be stored, making it difficult to choose an appropriate list length. If the length is too small, it may not meet the requirements; if too large, it may waste memory space.

To solve this problem, we can use a \"dynamic array\" to implement lists. It inherits the advantages of arrays and can dynamically expand during program execution.

In fact, many programming languages' standard libraries implement lists using dynamic arrays, such as Python's list, Java's ArrayList, C++'s vector, and C#'s List. In the following discussion, we will consider \"list\" and \"dynamic array\" as synonymous concepts.

"},{"location":"chapter_array_and_linkedlist/list/#431-common-list-operations","title":"4.3.1 \u00a0 Common List Operations","text":""},{"location":"chapter_array_and_linkedlist/list/#1-initializing-a-list","title":"1. \u00a0 Initializing a List","text":"

We typically use two methods of initialization: \"without initial values\" and \"with initial values\".

PythonC++JavaC#GoSwiftJSTSDartRustCZig list.py
# Initialize list\n# Without initial values\nnums1: list[int] = []\n# With initial values\nnums: list[int] = [1, 3, 2, 5, 4]\n
list.cpp
/* Initialize list */\n// Note, in C++ the vector is the equivalent of nums described here\n// Without initial values\nvector<int> nums1;\n// With initial values\nvector<int> nums = { 1, 3, 2, 5, 4 };\n
list.java
/* Initialize list */\n// Without initial values\nList<Integer> nums1 = new ArrayList<>();\n// With initial values (note the element type should be the wrapper class Integer[] for int[])\nInteger[] numbers = new Integer[] { 1, 3, 2, 5, 4 };\nList<Integer> nums = new ArrayList<>(Arrays.asList(numbers));\n
list.cs
/* Initialize list */\n// Without initial values\nList<int> nums1 = [];\n// With initial values\nint[] numbers = [1, 3, 2, 5, 4];\nList<int> nums = [.. numbers];\n
list_test.go
/* Initialize list */\n// Without initial values\nnums1 := []int{}\n// With initial values\nnums := []int{1, 3, 2, 5, 4}\n
list.swift
/* Initialize list */\n// Without initial values\nlet nums1: [Int] = []\n// With initial values\nvar nums = [1, 3, 2, 5, 4]\n
list.js
/* Initialize list */\n// Without initial values\nconst nums1 = [];\n// With initial values\nconst nums = [1, 3, 2, 5, 4];\n
list.ts
/* Initialize list */\n// Without initial values\nconst nums1: number[] = [];\n// With initial values\nconst nums: number[] = [1, 3, 2, 5, 4];\n
list.dart
/* Initialize list */\n// Without initial values\nList<int> nums1 = [];\n// With initial values\nList<int> nums = [1, 3, 2, 5, 4];\n
list.rs
/* Initialize list */\n// Without initial values\nlet nums1: Vec<i32> = Vec::new();\n// With initial values\nlet nums: Vec<i32> = vec![1, 3, 2, 5, 4];\n
list.c
// C does not provide built-in dynamic arrays\n
list.zig
// Initialize list\nvar nums = std.ArrayList(i32).init(std.heap.page_allocator);\ndefer nums.deinit();\ntry nums.appendSlice(&[_]i32{ 1, 3, 2, 5, 4 });\n
"},{"location":"chapter_array_and_linkedlist/list/#2-accessing-elements","title":"2. \u00a0 Accessing Elements","text":"

Lists are essentially arrays, so accessing and updating elements can be done in \\(O(1)\\) time, which is very efficient.

PythonC++JavaC#GoSwiftJSTSDartRustCZig list.py
# Access elements\nnum: int = nums[1]  # Access the element at index 1\n\n# Update elements\nnums[1] = 0    # Update the element at index 1 to 0\n
list.cpp
/* Access elements */\nint num = nums[1];  // Access the element at index 1\n\n/* Update elements */\nnums[1] = 0;  // Update the element at index 1 to 0\n
list.java
/* Access elements */\nint num = nums.get(1);  // Access the element at index 1\n\n/* Update elements */\nnums.set(1, 0);  // Update the element at index 1 to 0\n
list.cs
/* Access elements */\nint num = nums[1];  // Access the element at index 1\n\n/* Update elements */\nnums[1] = 0;  // Update the element at index 1 to 0\n
list_test.go
/* Access elements */\nnum := nums[1]  // Access the element at index 1\n\n/* Update elements */\nnums[1] = 0     // Update the element at index 1 to 0\n
list.swift
/* Access elements */\nlet num = nums[1] // Access the element at index 1\n\n/* Update elements */\nnums[1] = 0 // Update the element at index 1 to 0\n
list.js
/* Access elements */\nconst num = nums[1];  // Access the element at index 1\n\n/* Update elements */\nnums[1] = 0;  // Update the element at index 1 to 0\n
list.ts
/* Access elements */\nconst num: number = nums[1];  // Access the element at index 1\n\n/* Update elements */\nnums[1] = 0;  // Update the element at index 1 to 0\n
list.dart
/* Access elements */\nint num = nums[1];  // Access the element at index 1\n\n/* Update elements */\nnums[1] = 0;  // Update the element at index 1 to 0\n
list.rs
/* Access elements */\nlet num: i32 = nums[1];  // Access the element at index 1\n/* Update elements */\nnums[1] = 0;             // Update the element at index 1 to 0\n
list.c
// C does not provide built-in dynamic arrays\n
list.zig
// Access elements\nvar num = nums.items[1]; // Access the element at index 1\n\n// Update elements\nnums.items[1] = 0; // Update the element at index 1 to 0  \n
"},{"location":"chapter_array_and_linkedlist/list/#3-inserting-and-deleting-elements","title":"3. \u00a0 Inserting and Deleting Elements","text":"

Compared to arrays, lists can freely add and remove elements. Adding elements at the end of the list has a time complexity of \\(O(1)\\), but the efficiency of inserting and deleting elements is still the same as in arrays, with a time complexity of \\(O(n)\\).

PythonC++JavaC#GoSwiftJSTSDartRustCZig list.py
# Clear list\nnums.clear()\n\n# Append elements at the end\nnums.append(1)\nnums.append(3)\nnums.append(2)\nnums.append(5)\nnums.append(4)\n\n# Insert element in the middle\nnums.insert(3, 6)  # Insert number 6 at index 3\n\n# Remove elements\nnums.pop(3)        # Remove the element at index 3\n
list.cpp
/* Clear list */\nnums.clear();\n\n/* Append elements at the end */\nnums.push_back(1);\nnums.push_back(3);\nnums.push_back(2);\nnums.push_back(5);\nnums.push_back(4);\n\n/* Insert element in the middle */\nnums.insert(nums.begin() + 3, 6);  // Insert number 6 at index 3\n\n/* Remove elements */\nnums.erase(nums.begin() + 3);      // Remove the element at index 3\n
list.java
/* Clear list */\nnums.clear();\n\n/* Append elements at the end */\nnums.add(1);\nnums.add(3);\nnums.add(2);\nnums.add(5);\nnums.add(4);\n\n/* Insert element in the middle */\nnums.add(3, 6);  // Insert number 6 at index 3\n\n/* Remove elements */\nnums.remove(3);  // Remove the element at index 3\n
list.cs
/* Clear list */\nnums.Clear();\n\n/* Append elements at the end */\nnums.Add(1);\nnums.Add(3);\nnums.Add(2);\nnums.Add(5);\nnums.Add(4);\n\n/* Insert element in the middle */\nnums.Insert(3, 6);\n\n/* Remove elements */\nnums.RemoveAt(3);\n
list_test.go
/* Clear list */\nnums = nil\n\n/* Append elements at the end */\nnums = append(nums, 1)\nnums = append(nums, 3)\nnums = append(nums, 2)\nnums = append(nums, 5)\nnums = append(nums, 4)\n\n/* Insert element in the middle */\nnums = append(nums[:3], append([]int{6}, nums[3:]...)...) // Insert number 6 at index 3\n\n/* Remove elements */\nnums = append(nums[:3], nums[4:]...) // Remove the element at index 3\n
list.swift
/* Clear list */\nnums.removeAll()\n\n/* Append elements at the end */\nnums.append(1)\nnums.append(3)\nnums.append(2)\nnums.append(5)\nnums.append(4)\n\n/* Insert element in the middle */\nnums.insert(6, at: 3) // Insert number 6 at index 3\n\n/* Remove elements */\nnums.remove(at: 3) // Remove the element at index 3\n
list.js
/* Clear list */\nnums.length = 0;\n\n/* Append elements at the end */\nnums.push(1);\nnums.push(3);\nnums.push(2);\nnums.push(5);\nnums.push(4);\n\n/* Insert element in the middle */\nnums.splice(3, 0, 6);\n\n/* Remove elements */\nnums.splice(3, 1);\n
list.ts
/* Clear list */\nnums.length = 0;\n\n/* Append elements at the end */\nnums.push(1);\nnums.push(3);\nnums.push(2);\nnums.push(5);\nnums.push(4);\n\n/* Insert element in the middle */\nnums.splice(3, 0, 6);\n\n/* Remove elements */\nnums.splice(3, 1);\n
list.dart
/* Clear list */\nnums.clear();\n\n/* Append elements at the end */\nnums.add(1);\nnums.add(3);\nnums.add(2);\nnums.add(5);\nnums.add(4);\n\n/* Insert element in the middle */\nnums.insert(3, 6); // Insert number 6 at index 3\n\n/* Remove elements */\nnums.removeAt(3); // Remove the element at index 3\n
list.rs
/* Clear list */\nnums.clear();\n\n/* Append elements at the end */\nnums.push(1);\nnums.push(3);\nnums.push(2);\nnums.push(5);\nnums.push(4);\n\n/* Insert element in the middle */\nnums.insert(3, 6);  // Insert number 6 at index 3\n\n/* Remove elements */\nnums.remove(3);    // Remove the element at index 3\n
list.c
// C does not provide built-in dynamic arrays\n
list.zig
// Clear list\nnums.clearRetainingCapacity();\n\n// Append elements at the end\ntry nums.append(1);\ntry nums.append(3);\ntry nums.append(2);\ntry nums.append(5);\ntry nums.append(4);\n\n// Insert element in the middle\ntry nums.insert(3, 6); // Insert number 6 at index 3\n\n// Remove elements\n_ = nums.orderedRemove(3); // Remove the element at index 3\n
"},{"location":"chapter_array_and_linkedlist/list/#4-traversing-the-list","title":"4. \u00a0 Traversing the List","text":"

Like arrays, lists can be traversed based on index, or by directly iterating over each element.

PythonC++JavaC#GoSwiftJSTSDartRustCZig list.py
# Iterate through the list by index\ncount = 0\nfor i in range(len(nums)):\n    count += nums[i]\n\n# Iterate directly through list elements\nfor num in nums:\n    count += num\n
list.cpp
/* Iterate through the list by index */\nint count = 0;\nfor (int i = 0; i < nums.size(); i++) {\n    count += nums[i];\n}\n\n/* Iterate directly through list elements */\ncount = 0;\nfor (int num : nums) {\n    count += num;\n}\n
list.java
/* Iterate through the list by index */\nint count = 0;\nfor (int i = 0; i < nums.size(); i++) {\n    count += nums.get(i);\n}\n\n/* Iterate directly through list elements */\nfor (int num : nums) {\n    count += num;\n}\n
list.cs
/* Iterate through the list by index */\nint count = 0;\nfor (int i = 0; i < nums.Count; i++) {\n    count += nums[i];\n}\n\n/* Iterate directly through list elements */\ncount = 0;\nforeach (int num in nums) {\n    count += num;\n}\n
list_test.go
/* Iterate through the list by index */\ncount := 0\nfor i := 0; i < len(nums); i++ {\n    count += nums[i]\n}\n\n/* Iterate directly through list elements */\ncount = 0\nfor _, num := range nums {\n    count += num\n}\n
list.swift
/* Iterate through the list by index */\nvar count = 0\nfor i in nums.indices {\n    count += nums[i]\n}\n\n/* Iterate directly through list elements */\ncount = 0\nfor num in nums {\n    count += num\n}\n
list.js
/* Iterate through the list by index */\nlet count = 0;\nfor (let i = 0; i < nums.length; i++) {\n    count += nums[i];\n}\n\n/* Iterate directly through list elements */\ncount = 0;\nfor (const num of nums) {\n    count += num;\n}\n
list.ts
/* Iterate through the list by index */\nlet count = 0;\nfor (let i = 0; i < nums.length; i++) {\n    count += nums[i];\n}\n\n/* Iterate directly through list elements */\ncount = 0;\nfor (const num of nums) {\n    count += num;\n}\n
list.dart
/* Iterate through the list by index */\nint count = 0;\nfor (var i = 0; i < nums.length; i++) {\n    count += nums[i];\n}\n\n/* Iterate directly through list elements */\ncount = 0;\nfor (var num in nums) {\n    count += num;\n}\n
list.rs
// Iterate through the list by index\nlet mut _count = 0;\nfor i in 0..nums.len() {\n    _count += nums[i];\n}\n\n// Iterate directly through list elements\n_count = 0;\nfor num in &nums {\n    _count += num;\n}\n
list.c
// C does not provide built-in dynamic arrays\n
list.zig
// Iterate through the list by index\nvar count: i32 = 0;\nvar i: i32 = 0;\nwhile (i < nums.items.len) : (i += 1) {\n    count += nums[i];\n}\n\n// Iterate directly through list elements\ncount = 0;\nfor (nums.items) |num| {\n    count += num;\n}\n
"},{"location":"chapter_array_and_linkedlist/list/#5-concatenating-lists","title":"5. \u00a0 Concatenating Lists","text":"

Given a new list nums1, we can append it to the end of the original list.

PythonC++JavaC#GoSwiftJSTSDartRustCZig list.py
# Concatenate two lists\nnums1: list[int] = [6, 8, 7, 10, 9]\nnums += nums1  # Concatenate nums1 to the end of nums\n
list.cpp
/* Concatenate two lists */\nvector<int> nums1 = { 6, 8, 7, 10, 9 };\n// Concatenate nums1 to the end of nums\nnums.insert(nums.end(), nums1.begin(), nums1.end());\n
list.java
/* Concatenate two lists */\nList<Integer> nums1 = new ArrayList<>(Arrays.asList(new Integer[] { 6, 8, 7, 10, 9 }));\nnums.addAll(nums1);  // Concatenate nums1 to the end of nums\n
list.cs
/* Concatenate two lists */\nList<int> nums1 = [6, 8, 7, 10, 9];\nnums.AddRange(nums1);  // Concatenate nums1 to the end of nums\n
list_test.go
/* Concatenate two lists */\nnums1 := []int{6, 8, 7, 10, 9}\nnums = append(nums, nums1...)  // Concatenate nums1 to the end of nums\n
list.swift
/* Concatenate two lists */\nlet nums1 = [6, 8, 7, 10, 9]\nnums.append(contentsOf: nums1) // Concatenate nums1 to the end of nums\n
list.js
/* Concatenate two lists */\nconst nums1 = [6, 8, 7, 10, 9];\nnums.push(...nums1);  // Concatenate nums1 to the end of nums\n
list.ts
/* Concatenate two lists */\nconst nums1: number[] = [6, 8, 7, 10, 9];\nnums.push(...nums1);  // Concatenate nums1 to the end of nums\n
list.dart
/* Concatenate two lists */\nList<int> nums1 = [6, 8, 7, 10, 9];\nnums.addAll(nums1);  // Concatenate nums1 to the end of nums\n
list.rs
/* Concatenate two lists */\nlet nums1: Vec<i32> = vec![6, 8, 7, 10, 9];\nnums.extend(nums1);\n
list.c
// C does not provide built-in dynamic arrays\n
list.zig
// Concatenate two lists\nvar nums1 = std.ArrayList(i32).init(std.heap.page_allocator);\ndefer nums1.deinit();\ntry nums1.appendSlice(&[_]i32{ 6, 8, 7, 10, 9 });\ntry nums.insertSlice(nums.items.len, nums1.items); // Concatenate nums1 to the end of nums\n
"},{"location":"chapter_array_and_linkedlist/list/#6-sorting-the-list","title":"6. \u00a0 Sorting the List","text":"

After sorting the list, we can use algorithms often tested in array-related algorithm problems, such as \"binary search\" and \"two-pointer\" algorithms.

PythonC++JavaC#GoSwiftJSTSDartRustCZig list.py
# Sort the list\nnums.sort()  # After sorting, the list elements are in ascending order\n
list.cpp
/* Sort the list */\nsort(nums.begin(), nums.end());  // After sorting, the list elements are in ascending order\n
list.java
/* Sort the list */\nCollections.sort(nums);  // After sorting, the list elements are in ascending order\n
list.cs
/* Sort the list */\nnums.Sort(); // After sorting, the list elements are in ascending order\n
list_test.go
/* Sort the list */\nsort.Ints(nums)  // After sorting, the list elements are in ascending order\n
list.swift
/* Sort the list */\nnums.sort() // After sorting, the list elements are in ascending order\n
list.js
/* Sort the list */  \nnums.sort((a, b) => a - b);  // After sorting, the list elements are in ascending order\n
list.ts
/* Sort the list */\nnums.sort((a, b) => a - b);  // After sorting, the list elements are in ascending order\n
list.dart
/* Sort the list */\nnums.sort(); // After sorting, the list elements are in ascending order\n
list.rs
/* Sort the list */\nnums.sort(); // After sorting, the list elements are in ascending order\n
list.c
// C does not provide built-in dynamic arrays\n
list.zig
// Sort the list\nstd.sort.sort(i32, nums.items, {}, comptime std.sort.asc(i32));\n
"},{"location":"chapter_array_and_linkedlist/list/#432-list-implementation","title":"4.3.2 \u00a0 List Implementation","text":"

Many programming languages have built-in lists, such as Java, C++, Python, etc. Their implementations are quite complex, with very meticulous settings for parameters such as initial capacity and expansion multiplier. Interested readers can refer to the source code for learning.

To deepen the understanding of how lists work, let's try implementing a simple version of a list, focusing on three key designs.

  • Initial Capacity: Choose a reasonable initial capacity for the array. In this example, we choose 10 as the initial capacity.
  • Size Recording: Declare a variable size to record the current number of elements in the list, updating in real-time with element insertion and deletion. With this variable, we can locate the end of the list and determine whether expansion is needed.
  • Expansion Mechanism: If the list's capacity is full when inserting an element, expansion is necessary. First, create a larger array based on the expansion multiplier, then move all elements of the current array to the new array. In this example, we define that each time the array will expand to twice its previous size.
PythonC++JavaC#GoSwiftJSTSDartRustCZig my_list.py
class MyList:\n    \"\"\"\u5217\u8868\u7c7b\"\"\"\n\n    def __init__(self):\n        \"\"\"\u6784\u9020\u65b9\u6cd5\"\"\"\n        self._capacity: int = 10  # \u5217\u8868\u5bb9\u91cf\n        self._arr: list[int] = [0] * self._capacity  # \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n        self._size: int = 0  # \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n        self._extend_ratio: int = 2  # \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n    def size(self) -> int:\n        \"\"\"\u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\"\"\"\n        return self._size\n\n    def capacity(self) -> int:\n        \"\"\"\u83b7\u53d6\u5217\u8868\u5bb9\u91cf\"\"\"\n        return self._capacity\n\n    def get(self, index: int) -> int:\n        \"\"\"\u8bbf\u95ee\u5143\u7d20\"\"\"\n        # \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n        if index < 0 or index >= self._size:\n            raise IndexError(\"\u7d22\u5f15\u8d8a\u754c\")\n        return self._arr[index]\n\n    def set(self, num: int, index: int):\n        \"\"\"\u66f4\u65b0\u5143\u7d20\"\"\"\n        if index < 0 or index >= self._size:\n            raise IndexError(\"\u7d22\u5f15\u8d8a\u754c\")\n        self._arr[index] = num\n\n    def add(self, num: int):\n        \"\"\"\u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20\"\"\"\n        # \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if self.size() == self.capacity():\n            self.extend_capacity()\n        self._arr[self._size] = num\n        self._size += 1\n\n    def insert(self, num: int, index: int):\n        \"\"\"\u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20\"\"\"\n        if index < 0 or index >= self._size:\n            raise IndexError(\"\u7d22\u5f15\u8d8a\u754c\")\n        # \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if self._size == self.capacity():\n            self.extend_capacity()\n        # \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for j in range(self._size - 1, index - 1, -1):\n            self._arr[j + 1] = self._arr[j]\n        self._arr[index] = num\n        # \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        self._size += 1\n\n    def remove(self, index: int) -> int:\n        \"\"\"\u5220\u9664\u5143\u7d20\"\"\"\n        if index < 0 or index >= self._size:\n            raise IndexError(\"\u7d22\u5f15\u8d8a\u754c\")\n        num = self._arr[index]\n        # \u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for j in range(index, self._size - 1):\n            self._arr[j] = self._arr[j + 1]\n        # \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        self._size -= 1\n        # \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num\n\n    def extend_capacity(self):\n        \"\"\"\u5217\u8868\u6269\u5bb9\"\"\"\n        # \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 _extend_ratio \u500d\u7684\u65b0\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        self._arr = self._arr + [0] * self.capacity() * (self._extend_ratio - 1)\n        # \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n        self._capacity = len(self._arr)\n\n    def to_array(self) -> list[int]:\n        \"\"\"\u8fd4\u56de\u6709\u6548\u957f\u5ea6\u7684\u5217\u8868\"\"\"\n        return self._arr[: self._size]\n
my_list.cpp
/* \u5217\u8868\u7c7b */\nclass MyList {\n  private:\n    int *arr;             // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    int arrCapacity = 10; // \u5217\u8868\u5bb9\u91cf\n    int arrSize = 0;      // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n    int extendRatio = 2;   // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n  public:\n    /* \u6784\u9020\u65b9\u6cd5 */\n    MyList() {\n        arr = new int[arrCapacity];\n    }\n\n    /* \u6790\u6784\u65b9\u6cd5 */\n    ~MyList() {\n        delete[] arr;\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09*/\n    int size() {\n        return arrSize;\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n    int capacity() {\n        return arrCapacity;\n    }\n\n    /* \u8bbf\u95ee\u5143\u7d20 */\n    int get(int index) {\n        // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n        if (index < 0 || index >= size())\n            throw out_of_range(\"\u7d22\u5f15\u8d8a\u754c\");\n        return arr[index];\n    }\n\n    /* \u66f4\u65b0\u5143\u7d20 */\n    void set(int index, int num) {\n        if (index < 0 || index >= size())\n            throw out_of_range(\"\u7d22\u5f15\u8d8a\u754c\");\n        arr[index] = num;\n    }\n\n    /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n    void add(int num) {\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (size() == capacity())\n            extendCapacity();\n        arr[size()] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        arrSize++;\n    }\n\n    /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n    void insert(int index, int num) {\n        if (index < 0 || index >= size())\n            throw out_of_range(\"\u7d22\u5f15\u8d8a\u754c\");\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (size() == capacity())\n            extendCapacity();\n        // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for (int j = size() - 1; j >= index; j--) {\n            arr[j + 1] = arr[j];\n        }\n        arr[index] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        arrSize++;\n    }\n\n    /* \u5220\u9664\u5143\u7d20 */\n    int remove(int index) {\n        if (index < 0 || index >= size())\n            throw out_of_range(\"\u7d22\u5f15\u8d8a\u754c\");\n        int num = arr[index];\n        // \u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for (int j = index; j < size() - 1; j++) {\n            arr[j] = arr[j + 1];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        arrSize--;\n        // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num;\n    }\n\n    /* \u5217\u8868\u6269\u5bb9 */\n    void extendCapacity() {\n        // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 extendRatio \u500d\u7684\u65b0\u6570\u7ec4\n        int newCapacity = capacity() * extendRatio;\n        int *tmp = arr;\n        arr = new int[newCapacity];\n        // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        for (int i = 0; i < size(); i++) {\n            arr[i] = tmp[i];\n        }\n        // \u91ca\u653e\u5185\u5b58\n        delete[] tmp;\n        arrCapacity = newCapacity;\n    }\n\n    /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a Vector \u7528\u4e8e\u6253\u5370 */\n    vector<int> toVector() {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        vector<int> vec(size());\n        for (int i = 0; i < size(); i++) {\n            vec[i] = arr[i];\n        }\n        return vec;\n    }\n};\n
my_list.java
/* \u5217\u8868\u7c7b */\nclass MyList {\n    private int[] arr; // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    private int capacity = 10; // \u5217\u8868\u5bb9\u91cf\n    private int size = 0; // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n    private int extendRatio = 2; // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n    /* \u6784\u9020\u65b9\u6cd5 */\n    public MyList() {\n        arr = new int[capacity];\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09 */\n    public int size() {\n        return size;\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n    public int capacity() {\n        return capacity;\n    }\n\n    /* \u8bbf\u95ee\u5143\u7d20 */\n    public int get(int index) {\n        // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n        if (index < 0 || index >= size)\n            throw new IndexOutOfBoundsException(\"\u7d22\u5f15\u8d8a\u754c\");\n        return arr[index];\n    }\n\n    /* \u66f4\u65b0\u5143\u7d20 */\n    public void set(int index, int num) {\n        if (index < 0 || index >= size)\n            throw new IndexOutOfBoundsException(\"\u7d22\u5f15\u8d8a\u754c\");\n        arr[index] = num;\n    }\n\n    /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n    public void add(int num) {\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (size == capacity())\n            extendCapacity();\n        arr[size] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        size++;\n    }\n\n    /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n    public void insert(int index, int num) {\n        if (index < 0 || index >= size)\n            throw new IndexOutOfBoundsException(\"\u7d22\u5f15\u8d8a\u754c\");\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (size == capacity())\n            extendCapacity();\n        // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for (int j = size - 1; j >= index; j--) {\n            arr[j + 1] = arr[j];\n        }\n        arr[index] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        size++;\n    }\n\n    /* \u5220\u9664\u5143\u7d20 */\n    public int remove(int index) {\n        if (index < 0 || index >= size)\n            throw new IndexOutOfBoundsException(\"\u7d22\u5f15\u8d8a\u754c\");\n        int num = arr[index];\n        // \u5c06\u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for (int j = index; j < size - 1; j++) {\n            arr[j] = arr[j + 1];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        size--;\n        // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num;\n    }\n\n    /* \u5217\u8868\u6269\u5bb9 */\n    public void extendCapacity() {\n        // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 extendRatio \u500d\u7684\u65b0\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        arr = Arrays.copyOf(arr, capacity() * extendRatio);\n        // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n        capacity = arr.length;\n    }\n\n    /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4 */\n    public int[] toArray() {\n        int size = size();\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        int[] arr = new int[size];\n        for (int i = 0; i < size; i++) {\n            arr[i] = get(i);\n        }\n        return arr;\n    }\n}\n
my_list.cs
/* \u5217\u8868\u7c7b */\nclass MyList {\n    private int[] arr;           // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    private int arrCapacity = 10;    // \u5217\u8868\u5bb9\u91cf\n    private int arrSize = 0;         // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n    private readonly int extendRatio = 2;  // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n    /* \u6784\u9020\u65b9\u6cd5 */\n    public MyList() {\n        arr = new int[arrCapacity];\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09*/\n    public int Size() {\n        return arrSize;\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n    public int Capacity() {\n        return arrCapacity;\n    }\n\n    /* \u8bbf\u95ee\u5143\u7d20 */\n    public int Get(int index) {\n        // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n        if (index < 0 || index >= arrSize)\n            throw new IndexOutOfRangeException(\"\u7d22\u5f15\u8d8a\u754c\");\n        return arr[index];\n    }\n\n    /* \u66f4\u65b0\u5143\u7d20 */\n    public void Set(int index, int num) {\n        if (index < 0 || index >= arrSize)\n            throw new IndexOutOfRangeException(\"\u7d22\u5f15\u8d8a\u754c\");\n        arr[index] = num;\n    }\n\n    /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n    public void Add(int num) {\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (arrSize == arrCapacity)\n            ExtendCapacity();\n        arr[arrSize] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        arrSize++;\n    }\n\n    /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n    public void Insert(int index, int num) {\n        if (index < 0 || index >= arrSize)\n            throw new IndexOutOfRangeException(\"\u7d22\u5f15\u8d8a\u754c\");\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (arrSize == arrCapacity)\n            ExtendCapacity();\n        // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for (int j = arrSize - 1; j >= index; j--) {\n            arr[j + 1] = arr[j];\n        }\n        arr[index] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        arrSize++;\n    }\n\n    /* \u5220\u9664\u5143\u7d20 */\n    public int Remove(int index) {\n        if (index < 0 || index >= arrSize)\n            throw new IndexOutOfRangeException(\"\u7d22\u5f15\u8d8a\u754c\");\n        int num = arr[index];\n        // \u5c06\u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for (int j = index; j < arrSize - 1; j++) {\n            arr[j] = arr[j + 1];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        arrSize--;\n        // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num;\n    }\n\n    /* \u5217\u8868\u6269\u5bb9 */\n    public void ExtendCapacity() {\n        // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a arrCapacity * extendRatio \u7684\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        Array.Resize(ref arr, arrCapacity * extendRatio);\n        // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n        arrCapacity = arr.Length;\n    }\n\n    /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4 */\n    public int[] ToArray() {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        int[] arr = new int[arrSize];\n        for (int i = 0; i < arrSize; i++) {\n            arr[i] = Get(i);\n        }\n        return arr;\n    }\n}\n
my_list.go
/* \u5217\u8868\u7c7b */\ntype myList struct {\n    arrCapacity int\n    arr         []int\n    arrSize     int\n    extendRatio int\n}\n\n/* \u6784\u9020\u51fd\u6570 */\nfunc newMyList() *myList {\n    return &myList{\n        arrCapacity: 10,              // \u5217\u8868\u5bb9\u91cf\n        arr:         make([]int, 10), // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n        arrSize:     0,               // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n        extendRatio: 2,               // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n    }\n}\n\n/* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09 */\nfunc (l *myList) size() int {\n    return l.arrSize\n}\n\n/*  \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\nfunc (l *myList) capacity() int {\n    return l.arrCapacity\n}\n\n/* \u8bbf\u95ee\u5143\u7d20 */\nfunc (l *myList) get(index int) int {\n    // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n    if index < 0 || index >= l.arrSize {\n        panic(\"\u7d22\u5f15\u8d8a\u754c\")\n    }\n    return l.arr[index]\n}\n\n/* \u66f4\u65b0\u5143\u7d20 */\nfunc (l *myList) set(num, index int) {\n    if index < 0 || index >= l.arrSize {\n        panic(\"\u7d22\u5f15\u8d8a\u754c\")\n    }\n    l.arr[index] = num\n}\n\n/* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\nfunc (l *myList) add(num int) {\n    // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n    if l.arrSize == l.arrCapacity {\n        l.extendCapacity()\n    }\n    l.arr[l.arrSize] = num\n    // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n    l.arrSize++\n}\n\n/* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\nfunc (l *myList) insert(num, index int) {\n    if index < 0 || index >= l.arrSize {\n        panic(\"\u7d22\u5f15\u8d8a\u754c\")\n    }\n    // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n    if l.arrSize == l.arrCapacity {\n        l.extendCapacity()\n    }\n    // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for j := l.arrSize - 1; j >= index; j-- {\n        l.arr[j+1] = l.arr[j]\n    }\n    l.arr[index] = num\n    // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n    l.arrSize++\n}\n\n/* \u5220\u9664\u5143\u7d20 */\nfunc (l *myList) remove(index int) int {\n    if index < 0 || index >= l.arrSize {\n        panic(\"\u7d22\u5f15\u8d8a\u754c\")\n    }\n    num := l.arr[index]\n    // \u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for j := index; j < l.arrSize-1; j++ {\n        l.arr[j] = l.arr[j+1]\n    }\n    // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n    l.arrSize--\n    // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n    return num\n}\n\n/* \u5217\u8868\u6269\u5bb9 */\nfunc (l *myList) extendCapacity() {\n    // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 extendRatio \u500d\u7684\u65b0\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    l.arr = append(l.arr, make([]int, l.arrCapacity*(l.extendRatio-1))...)\n    // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n    l.arrCapacity = len(l.arr)\n}\n\n/* \u8fd4\u56de\u6709\u6548\u957f\u5ea6\u7684\u5217\u8868 */\nfunc (l *myList) toArray() []int {\n    // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n    return l.arr[:l.arrSize]\n}\n
my_list.swift
/* \u5217\u8868\u7c7b */\nclass MyList {\n    private var arr: [Int] // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    private var _capacity = 10 // \u5217\u8868\u5bb9\u91cf\n    private var _size = 0 // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n    private let extendRatio = 2 // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n    /* \u6784\u9020\u65b9\u6cd5 */\n    init() {\n        arr = Array(repeating: 0, count: _capacity)\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09*/\n    func size() -> Int {\n        _size\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n    func capacity() -> Int {\n        _capacity\n    }\n\n    /* \u8bbf\u95ee\u5143\u7d20 */\n    func get(index: Int) -> Int {\n        // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\u5219\u629b\u51fa\u9519\u8bef\uff0c\u4e0b\u540c\n        if index < 0 || index >= _size {\n            fatalError(\"\u7d22\u5f15\u8d8a\u754c\")\n        }\n        return arr[index]\n    }\n\n    /* \u66f4\u65b0\u5143\u7d20 */\n    func set(index: Int, num: Int) {\n        if index < 0 || index >= _size {\n            fatalError(\"\u7d22\u5f15\u8d8a\u754c\")\n        }\n        arr[index] = num\n    }\n\n    /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n    func add(num: Int) {\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if _size == _capacity {\n            extendCapacity()\n        }\n        arr[_size] = num\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        _size += 1\n    }\n\n    /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n    func insert(index: Int, num: Int) {\n        if index < 0 || index >= _size {\n            fatalError(\"\u7d22\u5f15\u8d8a\u754c\")\n        }\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if _size == _capacity {\n            extendCapacity()\n        }\n        // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for j in sequence(first: _size - 1, next: { $0 >= index + 1 ? $0 - 1 : nil }) {\n            arr[j + 1] = arr[j]\n        }\n        arr[index] = num\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        _size += 1\n    }\n\n    /* \u5220\u9664\u5143\u7d20 */\n    @discardableResult\n    func remove(index: Int) -> Int {\n        if index < 0 || index >= _size {\n            fatalError(\"\u7d22\u5f15\u8d8a\u754c\")\n        }\n        let num = arr[index]\n        // \u5c06\u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for j in index ..< (_size - 1) {\n            arr[j] = arr[j + 1]\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        _size -= 1\n        // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num\n    }\n\n    /* \u5217\u8868\u6269\u5bb9 */\n    func extendCapacity() {\n        // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 extendRatio \u500d\u7684\u65b0\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        arr = arr + Array(repeating: 0, count: _capacity * (extendRatio - 1))\n        // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n        _capacity = arr.count\n    }\n\n    /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4 */\n    func toArray() -> [Int] {\n        var arr = Array(repeating: 0, count: _size)\n        for i in 0 ..< _size {\n            arr[i] = get(index: i)\n        }\n        return arr\n    }\n}\n
my_list.js
/* \u5217\u8868\u7c7b */\nclass MyList {\n    #arr = new Array(); // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    #capacity = 10; // \u5217\u8868\u5bb9\u91cf\n    #size = 0; // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n    #extendRatio = 2; // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n    /* \u6784\u9020\u65b9\u6cd5 */\n    constructor() {\n        this.#arr = new Array(this.#capacity);\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09*/\n    size() {\n        return this.#size;\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n    capacity() {\n        return this.#capacity;\n    }\n\n    /* \u8bbf\u95ee\u5143\u7d20 */\n    get(index) {\n        // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n        if (index < 0 || index >= this.#size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        return this.#arr[index];\n    }\n\n    /* \u66f4\u65b0\u5143\u7d20 */\n    set(index, num) {\n        if (index < 0 || index >= this.#size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        this.#arr[index] = num;\n    }\n\n    /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n    add(num) {\n        // \u5982\u679c\u957f\u5ea6\u7b49\u4e8e\u5bb9\u91cf\uff0c\u5219\u9700\u8981\u6269\u5bb9\n        if (this.#size === this.#capacity) {\n            this.extendCapacity();\n        }\n        // \u5c06\u65b0\u5143\u7d20\u6dfb\u52a0\u5230\u5217\u8868\u5c3e\u90e8\n        this.#arr[this.#size] = num;\n        this.#size++;\n    }\n\n    /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n    insert(index, num) {\n        if (index < 0 || index >= this.#size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (this.#size === this.#capacity) {\n            this.extendCapacity();\n        }\n        // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for (let j = this.#size - 1; j >= index; j--) {\n            this.#arr[j + 1] = this.#arr[j];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        this.#arr[index] = num;\n        this.#size++;\n    }\n\n    /* \u5220\u9664\u5143\u7d20 */\n    remove(index) {\n        if (index < 0 || index >= this.#size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        let num = this.#arr[index];\n        // \u5c06\u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for (let j = index; j < this.#size - 1; j++) {\n            this.#arr[j] = this.#arr[j + 1];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        this.#size--;\n        // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num;\n    }\n\n    /* \u5217\u8868\u6269\u5bb9 */\n    extendCapacity() {\n        // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 extendRatio \u500d\u7684\u65b0\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        this.#arr = this.#arr.concat(\n            new Array(this.capacity() * (this.#extendRatio - 1))\n        );\n        // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n        this.#capacity = this.#arr.length;\n    }\n\n    /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4 */\n    toArray() {\n        let size = this.size();\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        const arr = new Array(size);\n        for (let i = 0; i < size; i++) {\n            arr[i] = this.get(i);\n        }\n        return arr;\n    }\n}\n
my_list.ts
/* \u5217\u8868\u7c7b */\nclass MyList {\n    private arr: Array<number>; // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    private _capacity: number = 10; // \u5217\u8868\u5bb9\u91cf\n    private _size: number = 0; // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n    private extendRatio: number = 2; // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n    /* \u6784\u9020\u65b9\u6cd5 */\n    constructor() {\n        this.arr = new Array(this._capacity);\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09*/\n    public size(): number {\n        return this._size;\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n    public capacity(): number {\n        return this._capacity;\n    }\n\n    /* \u8bbf\u95ee\u5143\u7d20 */\n    public get(index: number): number {\n        // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n        if (index < 0 || index >= this._size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        return this.arr[index];\n    }\n\n    /* \u66f4\u65b0\u5143\u7d20 */\n    public set(index: number, num: number): void {\n        if (index < 0 || index >= this._size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        this.arr[index] = num;\n    }\n\n    /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n    public add(num: number): void {\n        // \u5982\u679c\u957f\u5ea6\u7b49\u4e8e\u5bb9\u91cf\uff0c\u5219\u9700\u8981\u6269\u5bb9\n        if (this._size === this._capacity) this.extendCapacity();\n        // \u5c06\u65b0\u5143\u7d20\u6dfb\u52a0\u5230\u5217\u8868\u5c3e\u90e8\n        this.arr[this._size] = num;\n        this._size++;\n    }\n\n    /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n    public insert(index: number, num: number): void {\n        if (index < 0 || index >= this._size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (this._size === this._capacity) {\n            this.extendCapacity();\n        }\n        // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for (let j = this._size - 1; j >= index; j--) {\n            this.arr[j + 1] = this.arr[j];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        this.arr[index] = num;\n        this._size++;\n    }\n\n    /* \u5220\u9664\u5143\u7d20 */\n    public remove(index: number): number {\n        if (index < 0 || index >= this._size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        let num = this.arr[index];\n        // \u5c06\u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for (let j = index; j < this._size - 1; j++) {\n            this.arr[j] = this.arr[j + 1];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        this._size--;\n        // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num;\n    }\n\n    /* \u5217\u8868\u6269\u5bb9 */\n    public extendCapacity(): void {\n        // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a size \u7684\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        this.arr = this.arr.concat(\n            new Array(this.capacity() * (this.extendRatio - 1))\n        );\n        // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n        this._capacity = this.arr.length;\n    }\n\n    /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4 */\n    public toArray(): number[] {\n        let size = this.size();\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        const arr = new Array(size);\n        for (let i = 0; i < size; i++) {\n            arr[i] = this.get(i);\n        }\n        return arr;\n    }\n}\n
my_list.dart
/* \u5217\u8868\u7c7b */\nclass MyList {\n  late List<int> _arr; // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n  int _capacity = 10; // \u5217\u8868\u5bb9\u91cf\n  int _size = 0; // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n  int _extendRatio = 2; // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n  /* \u6784\u9020\u65b9\u6cd5 */\n  MyList() {\n    _arr = List.filled(_capacity, 0);\n  }\n\n  /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09*/\n  int size() => _size;\n\n  /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n  int capacity() => _capacity;\n\n  /* \u8bbf\u95ee\u5143\u7d20 */\n  int get(int index) {\n    if (index >= _size) throw RangeError('\u7d22\u5f15\u8d8a\u754c');\n    return _arr[index];\n  }\n\n  /* \u66f4\u65b0\u5143\u7d20 */\n  void set(int index, int _num) {\n    if (index >= _size) throw RangeError('\u7d22\u5f15\u8d8a\u754c');\n    _arr[index] = _num;\n  }\n\n  /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n  void add(int _num) {\n    // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n    if (_size == _capacity) extendCapacity();\n    _arr[_size] = _num;\n    // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n    _size++;\n  }\n\n  /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n  void insert(int index, int _num) {\n    if (index >= _size) throw RangeError('\u7d22\u5f15\u8d8a\u754c');\n    // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n    if (_size == _capacity) extendCapacity();\n    // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for (var j = _size - 1; j >= index; j--) {\n      _arr[j + 1] = _arr[j];\n    }\n    _arr[index] = _num;\n    // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n    _size++;\n  }\n\n  /* \u5220\u9664\u5143\u7d20 */\n  int remove(int index) {\n    if (index >= _size) throw RangeError('\u7d22\u5f15\u8d8a\u754c');\n    int _num = _arr[index];\n    // \u5c06\u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for (var j = index; j < _size - 1; j++) {\n      _arr[j] = _arr[j + 1];\n    }\n    // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n    _size--;\n    // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n    return _num;\n  }\n\n  /* \u5217\u8868\u6269\u5bb9 */\n  void extendCapacity() {\n    // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 _extendRatio \u500d\u7684\u65b0\u6570\u7ec4\n    final _newNums = List.filled(_capacity * _extendRatio, 0);\n    // \u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    List.copyRange(_newNums, 0, _arr);\n    // \u66f4\u65b0 _arr \u7684\u5f15\u7528\n    _arr = _newNums;\n    // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n    _capacity = _arr.length;\n  }\n\n  /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4 */\n  List<int> toArray() {\n    List<int> arr = [];\n    for (var i = 0; i < _size; i++) {\n      arr.add(get(i));\n    }\n    return arr;\n  }\n}\n
my_list.rs
/* \u5217\u8868\u7c7b */\n#[allow(dead_code)]\nstruct MyList {\n    arr: Vec<i32>,       // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    capacity: usize,      // \u5217\u8868\u5bb9\u91cf\n    size: usize,          // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n    extend_ratio: usize,  // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n}\n\n#[allow(unused,unused_comparisons)]\nimpl MyList {\n    /* \u6784\u9020\u65b9\u6cd5 */\n    pub fn new(capacity: usize) -> Self {\n        let mut vec = Vec::new(); \n        vec.resize(capacity, 0);\n        Self {\n            arr: vec,\n            capacity,\n            size: 0,\n            extend_ratio: 2,\n        }\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09*/\n    pub fn size(&self) -> usize {\n        return self.size;\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n    pub fn capacity(&self) -> usize {\n        return self.capacity;\n    }\n\n    /* \u8bbf\u95ee\u5143\u7d20 */\n    pub fn get(&self, index: usize) -> i32 {\n        // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n        if index >= self.size {panic!(\"\u7d22\u5f15\u8d8a\u754c\")};\n        return self.arr[index];\n    }\n\n    /* \u66f4\u65b0\u5143\u7d20 */\n    pub fn set(&mut self, index: usize, num: i32) {\n        if index >= self.size {panic!(\"\u7d22\u5f15\u8d8a\u754c\")};\n        self.arr[index] = num;\n    }\n\n    /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n    pub fn add(&mut self, num: i32) {\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if self.size == self.capacity() {\n            self.extend_capacity();\n        }\n        self.arr[self.size] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        self.size += 1;\n    }\n\n    /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n    pub fn insert(&mut self, index: usize, num: i32) {\n        if index >= self.size() {panic!(\"\u7d22\u5f15\u8d8a\u754c\")};\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if self.size == self.capacity() {\n            self.extend_capacity();\n        }\n        // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for j in (index..self.size).rev() {\n            self.arr[j + 1] = self.arr[j];\n        }\n        self.arr[index] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        self.size += 1;\n    }\n\n    /* \u5220\u9664\u5143\u7d20 */\n    pub fn remove(&mut self, index: usize) -> i32 {\n        if index >= self.size() {panic!(\"\u7d22\u5f15\u8d8a\u754c\")};\n        let num = self.arr[index];\n        // \u5c06\u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for j in (index..self.size - 1) {\n            self.arr[j] = self.arr[j + 1];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        self.size -= 1;\n        // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num;\n    }\n\n    /* \u5217\u8868\u6269\u5bb9 */\n    pub fn extend_capacity(&mut self) {\n        // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 extend_ratio \u500d\u7684\u65b0\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        let new_capacity = self.capacity * self.extend_ratio;\n        self.arr.resize(new_capacity, 0);\n        // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n        self.capacity = new_capacity;\n    }\n\n    /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4 */\n    pub fn to_array(&mut self) -> Vec<i32> {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        let mut arr = Vec::new();\n        for i in 0..self.size {\n            arr.push(self.get(i));\n        }\n        arr\n    }\n}\n
my_list.c
/* \u5217\u8868\u7c7b */\ntypedef struct {\n    int *arr;        // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    int capacity;    // \u5217\u8868\u5bb9\u91cf\n    int size;        // \u5217\u8868\u5927\u5c0f\n    int extendRatio; // \u5217\u8868\u6bcf\u6b21\u6269\u5bb9\u7684\u500d\u6570\n} MyList;\n\n/* \u6784\u9020\u51fd\u6570 */\nMyList *newMyList() {\n    MyList *nums = malloc(sizeof(MyList));\n    nums->capacity = 10;\n    nums->arr = malloc(sizeof(int) * nums->capacity);\n    nums->size = 0;\n    nums->extendRatio = 2;\n    return nums;\n}\n\n/* \u6790\u6784\u51fd\u6570 */\nvoid delMyList(MyList *nums) {\n    free(nums->arr);\n    free(nums);\n}\n\n/* \u83b7\u53d6\u5217\u8868\u957f\u5ea6 */\nint size(MyList *nums) {\n    return nums->size;\n}\n\n/* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\nint capacity(MyList *nums) {\n    return nums->capacity;\n}\n\n/* \u8bbf\u95ee\u5143\u7d20 */\nint get(MyList *nums, int index) {\n    assert(index >= 0 && index < nums->size);\n    return nums->arr[index];\n}\n\n/* \u66f4\u65b0\u5143\u7d20 */\nvoid set(MyList *nums, int index, int num) {\n    assert(index >= 0 && index < nums->size);\n    nums->arr[index] = num;\n}\n\n/* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\nvoid add(MyList *nums, int num) {\n    if (size(nums) == capacity(nums)) {\n        extendCapacity(nums); // \u6269\u5bb9\n    }\n    nums->arr[size(nums)] = num;\n    nums->size++;\n}\n\n/* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\nvoid insert(MyList *nums, int index, int num) {\n    assert(index >= 0 && index < size(nums));\n    // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n    if (size(nums) == capacity(nums)) {\n        extendCapacity(nums); // \u6269\u5bb9\n    }\n    for (int i = size(nums); i > index; --i) {\n        nums->arr[i] = nums->arr[i - 1];\n    }\n    nums->arr[index] = num;\n    nums->size++;\n}\n\n/* \u5220\u9664\u5143\u7d20 */\n// \u6ce8\u610f\uff1astdio.h \u5360\u7528\u4e86 remove \u5173\u952e\u8bcd\nint removeItem(MyList *nums, int index) {\n    assert(index >= 0 && index < size(nums));\n    int num = nums->arr[index];\n    for (int i = index; i < size(nums) - 1; i++) {\n        nums->arr[i] = nums->arr[i + 1];\n    }\n    nums->size--;\n    return num;\n}\n\n/* \u5217\u8868\u6269\u5bb9 */\nvoid extendCapacity(MyList *nums) {\n    // \u5148\u5206\u914d\u7a7a\u95f4\n    int newCapacity = capacity(nums) * nums->extendRatio;\n    int *extend = (int *)malloc(sizeof(int) * newCapacity);\n    int *temp = nums->arr;\n\n    // \u62f7\u8d1d\u65e7\u6570\u636e\u5230\u65b0\u6570\u636e\n    for (int i = 0; i < size(nums); i++)\n        extend[i] = nums->arr[i];\n\n    // \u91ca\u653e\u65e7\u6570\u636e\n    free(temp);\n\n    // \u66f4\u65b0\u65b0\u6570\u636e\n    nums->arr = extend;\n    nums->capacity = newCapacity;\n}\n\n/* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a Array \u7528\u4e8e\u6253\u5370 */\nint *toArray(MyList *nums) {\n    return nums->arr;\n}\n
my_list.zig
// \u5217\u8868\u7c7b\nfn MyList(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        arr: []T = undefined,                        // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n        arrCapacity: usize = 10,                     // \u5217\u8868\u5bb9\u91cf\n        numSize: usize = 0,                           // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n        extendRatio: usize = 2,                       // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n        mem_arena: ?std.heap.ArenaAllocator = null,\n        mem_allocator: std.mem.Allocator = undefined, // \u5185\u5b58\u5206\u914d\u5668\n\n        // \u6784\u9020\u51fd\u6570\uff08\u5206\u914d\u5185\u5b58+\u521d\u59cb\u5316\u5217\u8868\uff09\n        pub fn init(self: *Self, allocator: std.mem.Allocator) !void {\n            if (self.mem_arena == null) {\n                self.mem_arena = std.heap.ArenaAllocator.init(allocator);\n                self.mem_allocator = self.mem_arena.?.allocator();\n            }\n            self.arr = try self.mem_allocator.alloc(T, self.arrCapacity);\n            @memset(self.arr, @as(T, 0));\n        }\n\n        // \u6790\u6784\u51fd\u6570\uff08\u91ca\u653e\u5185\u5b58\uff09\n        pub fn deinit(self: *Self) void {\n            if (self.mem_arena == null) return;\n            self.mem_arena.?.deinit();\n        }\n\n        // \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n        pub fn size(self: *Self) usize {\n            return self.numSize;\n        }\n\n        // \u83b7\u53d6\u5217\u8868\u5bb9\u91cf\n        pub fn capacity(self: *Self) usize {\n            return self.arrCapacity;\n        }\n\n        // \u8bbf\u95ee\u5143\u7d20\n        pub fn get(self: *Self, index: usize) T {\n            // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n            if (index < 0 or index >= self.size()) @panic(\"\u7d22\u5f15\u8d8a\u754c\");\n            return self.arr[index];\n        }  \n\n        // \u66f4\u65b0\u5143\u7d20\n        pub fn set(self: *Self, index: usize, num: T) void {\n            // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n            if (index < 0 or index >= self.size()) @panic(\"\u7d22\u5f15\u8d8a\u754c\");\n            self.arr[index] = num;\n        }  \n\n        // \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20\n        pub fn add(self: *Self, num: T) !void {\n            // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n            if (self.size() == self.capacity()) try self.extendCapacity();\n            self.arr[self.size()] = num;\n            // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n            self.numSize += 1;\n        }  \n\n        // \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20\n        pub fn insert(self: *Self, index: usize, num: T) !void {\n            if (index < 0 or index >= self.size()) @panic(\"\u7d22\u5f15\u8d8a\u754c\");\n            // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n            if (self.size() == self.capacity()) try self.extendCapacity();\n            // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n            var j = self.size() - 1;\n            while (j >= index) : (j -= 1) {\n                self.arr[j + 1] = self.arr[j];\n            }\n            self.arr[index] = num;\n            // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n            self.numSize += 1;\n        }\n\n        // \u5220\u9664\u5143\u7d20\n        pub fn remove(self: *Self, index: usize) T {\n            if (index < 0 or index >= self.size()) @panic(\"\u7d22\u5f15\u8d8a\u754c\");\n            var num = self.arr[index];\n            // \u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n            var j = index;\n            while (j < self.size() - 1) : (j += 1) {\n                self.arr[j] = self.arr[j + 1];\n            }\n            // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n            self.numSize -= 1;\n            // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n            return num;\n        }\n\n        // \u5217\u8868\u6269\u5bb9\n        pub fn extendCapacity(self: *Self) !void {\n            // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a size * extendRatio \u7684\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n            var newCapacity = self.capacity() * self.extendRatio;\n            var extend = try self.mem_allocator.alloc(T, newCapacity);\n            @memset(extend, @as(T, 0));\n            // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n            std.mem.copy(T, extend, self.arr);\n            self.arr = extend;\n            // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n            self.arrCapacity = newCapacity;\n        }\n\n        // \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4\n        pub fn toArray(self: *Self) ![]T {\n            // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n            var arr = try self.mem_allocator.alloc(T, self.size());\n           @memset(arr, @as(T, 0));\n            for (arr, 0..) |*num, i| {\n                num.* = self.get(i);\n            }\n            return arr;\n        }\n    };\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/ram_and_cache/","title":"4.4 \u00a0 Memory and Cache *","text":"

In the first two sections of this chapter, we explored arrays and linked lists, two fundamental and important data structures, representing \"continuous storage\" and \"dispersed storage\" respectively.

In fact, the physical structure largely determines the efficiency of a program's use of memory and cache, which in turn affects the overall performance of the algorithm.

"},{"location":"chapter_array_and_linkedlist/ram_and_cache/#441-computer-storage-devices","title":"4.4.1 \u00a0 Computer Storage Devices","text":"

There are three types of storage devices in computers: \"hard disk,\" \"random-access memory (RAM),\" and \"cache memory.\" The following table shows their different roles and performance characteristics in computer systems.

Table 4-2 \u00a0 Computer Storage Devices

Hard Disk Memory Cache Usage Long-term storage of data, including OS, programs, files, etc. Temporary storage of currently running programs and data being processed Stores frequently accessed data and instructions, reducing the number of CPU accesses to memory Volatility Data is not lost after power off Data is lost after power off Data is lost after power off Capacity Larger, TB level Smaller, GB level Very small, MB level Speed Slower, several hundred to thousands MB/s Faster, several tens of GB/s Very fast, several tens to hundreds of GB/s Price Cheaper, several cents to yuan / GB More expensive, tens to hundreds of yuan / GB Very expensive, priced with CPU

We can imagine the computer storage system as a pyramid structure shown in the Figure 4-9 . The storage devices closer to the top of the pyramid are faster, have smaller capacity, and are more costly. This multi-level design is not accidental, but the result of careful consideration by computer scientists and engineers.

  • Hard disks are difficult to replace with memory. Firstly, data in memory is lost after power off, making it unsuitable for long-term data storage; secondly, the cost of memory is dozens of times that of hard disks, making it difficult to popularize in the consumer market.
  • It is difficult for caches to have both large capacity and high speed. As the capacity of L1, L2, L3 caches gradually increases, their physical size becomes larger, increasing the physical distance from the CPU core, leading to increased data transfer time and higher element access latency. Under current technology, a multi-level cache structure is the best balance between capacity, speed, and cost.

Figure 4-9 \u00a0 Computer Storage System

Note

The storage hierarchy of computers reflects a delicate balance between speed, capacity, and cost. In fact, this kind of trade-off is common in all industrial fields, requiring us to find the best balance between different advantages and limitations.

Overall, hard disks are used for long-term storage of large amounts of data, memory is used for temporary storage of data being processed during program execution, and cache is used to store frequently accessed data and instructions to improve program execution efficiency. Together, they ensure the efficient operation of computer systems.

As shown in the Figure 4-10 , during program execution, data is read from the hard disk into memory for CPU computation. The cache can be considered a part of the CPU, smartly loading data from memory to provide fast data access to the CPU, significantly enhancing program execution efficiency and reducing reliance on slower memory.

Figure 4-10 \u00a0 Data Flow Between Hard Disk, Memory, and Cache

"},{"location":"chapter_array_and_linkedlist/ram_and_cache/#442-memory-efficiency-of-data-structures","title":"4.4.2 \u00a0 Memory Efficiency of Data Structures","text":"

In terms of memory space utilization, arrays and linked lists have their advantages and limitations.

On one hand, memory is limited and cannot be shared by multiple programs, so we hope that data structures can use space as efficiently as possible. The elements of an array are tightly packed without extra space for storing references (pointers) between linked list nodes, making them more space-efficient. However, arrays require allocating sufficient continuous memory space at once, which may lead to memory waste, and array expansion also requires additional time and space costs. In contrast, linked lists allocate and reclaim memory dynamically on a per-node basis, providing greater flexibility.

On the other hand, during program execution, as memory is repeatedly allocated and released, the degree of fragmentation of free memory becomes higher, leading to reduced memory utilization efficiency. Arrays, due to their continuous storage method, are relatively less likely to cause memory fragmentation. In contrast, the elements of a linked list are dispersedly stored, and frequent insertion and deletion operations make memory fragmentation more likely.

"},{"location":"chapter_array_and_linkedlist/ram_and_cache/#443-cache-efficiency-of-data-structures","title":"4.4.3 \u00a0 Cache Efficiency of Data Structures","text":"

Although caches are much smaller in space capacity than memory, they are much faster and play a crucial role in program execution speed. Since the cache's capacity is limited and can only store a small part of frequently accessed data, when the CPU tries to access data not in the cache, a \"cache miss\" occurs, forcing the CPU to load the needed data from slower memory.

Clearly, the fewer the cache misses, the higher the CPU's data read-write efficiency, and the better the program performance. The proportion of successful data retrieval from the cache by the CPU is called the \"cache hit rate,\" a metric often used to measure cache efficiency.

To achieve higher efficiency, caches adopt the following data loading mechanisms.

  • Cache Lines: Caches don't store and load data byte by byte but in units of cache lines. Compared to byte-by-byte transfer, the transmission of cache lines is more efficient.
  • Prefetch Mechanism: Processors try to predict data access patterns (such as sequential access, fixed stride jumping access, etc.) and load data into the cache according to specific patterns to improve the hit rate.
  • Spatial Locality: If data is accessed, data nearby is likely to be accessed in the near future. Therefore, when loading certain data, the cache also loads nearby data to improve the hit rate.
  • Temporal Locality: If data is accessed, it's likely to be accessed again in the near future. Caches use this principle to retain recently accessed data to improve the hit rate.

In fact, arrays and linked lists have different cache utilization efficiencies, mainly reflected in the following aspects.

  • Occupied Space: Linked list elements occupy more space than array elements, resulting in less effective data volume in the cache.
  • Cache Lines: Linked list data is scattered throughout memory, and since caches load \"by line,\" the proportion of loading invalid data is higher.
  • Prefetch Mechanism: The data access pattern of arrays is more \"predictable\" than that of linked lists, meaning the system is more likely to guess which data will be loaded next.
  • Spatial Locality: Arrays are stored in concentrated memory spaces, so the data near the loaded data is more likely to be accessed next.

Overall, arrays have a higher cache hit rate and are generally more efficient in operation than linked lists. This makes data structures based on arrays more popular in solving algorithmic problems.

It should be noted that high cache efficiency does not mean that arrays are always better than linked lists. Which data structure to choose in actual applications should be based on specific requirements. For example, both arrays and linked lists can implement the \"stack\" data structure (which will be detailed in the next chapter), but they are suitable for different scenarios.

  • In algorithm problems, we tend to choose stacks based on arrays because they provide higher operational efficiency and random access capabilities, with the only cost being the need to pre-allocate a certain amount of memory space for the array.
  • If the data volume is very large, highly dynamic, and the expected size of the stack is difficult to estimate, then a stack based on a linked list is more appropriate. Linked lists can disperse a large amount of data in different parts of the memory and avoid the additional overhead of array expansion.
"},{"location":"chapter_array_and_linkedlist/summary/","title":"4.5 \u00a0 Summary","text":""},{"location":"chapter_array_and_linkedlist/summary/#1-key-review","title":"1. \u00a0 Key Review","text":"
  • Arrays and linked lists are two basic data structures, representing two storage methods in computer memory: contiguous space storage and non-contiguous space storage. Their characteristics complement each other.
  • Arrays support random access and use less memory; however, they are inefficient in inserting and deleting elements and have a fixed length after initialization.
  • Linked lists implement efficient node insertion and deletion through changing references (pointers) and can flexibly adjust their length; however, they have lower node access efficiency and consume more memory.
  • Common types of linked lists include singly linked lists, circular linked lists, and doubly linked lists, each with its own application scenarios.
  • Lists are ordered collections of elements that support addition, deletion, and modification, typically implemented based on dynamic arrays, retaining the advantages of arrays while allowing flexible length adjustment.
  • The advent of lists significantly enhanced the practicality of arrays but may lead to some memory space wastage.
  • During program execution, data is mainly stored in memory. Arrays provide higher memory space efficiency, while linked lists are more flexible in memory usage.
  • Caches provide fast data access to CPUs through mechanisms like cache lines, prefetching, spatial locality, and temporal locality, significantly enhancing program execution efficiency.
  • Due to higher cache hit rates, arrays are generally more efficient than linked lists. When choosing a data structure, the appropriate choice should be made based on specific needs and scenarios.
"},{"location":"chapter_array_and_linkedlist/summary/#2-q-a","title":"2. \u00a0 Q & A","text":"

Q: Does storing arrays on the stack versus the heap affect time and space efficiency?

Arrays stored on both the stack and heap are stored in contiguous memory spaces, and data operation efficiency is essentially the same. However, stacks and heaps have their own characteristics, leading to the following differences.

  1. Allocation and release efficiency: The stack is a smaller memory block, allocated automatically by the compiler; the heap memory is relatively larger and can be dynamically allocated in the code, more prone to fragmentation. Therefore, allocation and release operations on the heap are generally slower than on the stack.
  2. Size limitation: Stack memory is relatively small, while the heap size is generally limited by available memory. Therefore, the heap is more suitable for storing large arrays.
  3. Flexibility: The size of arrays on the stack needs to be determined at compile-time, while the size of arrays on the heap can be dynamically determined at runtime.

Q: Why do arrays require elements of the same type, while linked lists do not emphasize same-type elements?

Linked lists consist of nodes connected by references (pointers), and each node can store data of different types, such as int, double, string, object, etc.

In contrast, array elements must be of the same type, allowing the calculation of offsets to access the corresponding element positions. For example, an array containing both int and long types, with single elements occupying 4 bytes and 8 bytes respectively, cannot use the following formula to calculate offsets, as the array contains elements of two different lengths.

# Element memory address = Array memory address + Element length * Element index\n

Q: After deleting a node, is it necessary to set P.next to None?

Not modifying P.next is also acceptable. From the perspective of the linked list, traversing from the head node to the tail node will no longer encounter P. This means that node P has been effectively removed from the list, and where P points no longer affects the list.

From a garbage collection perspective, for languages with automatic garbage collection mechanisms like Java, Python, and Go, whether node P is collected depends on whether there are still references pointing to it, not on the value of P.next. In languages like C and C++, we need to manually free the node's memory.

Q: In linked lists, the time complexity for insertion and deletion operations is O(1). But searching for the element before insertion or deletion takes O(n) time, so why isn't the time complexity O(n)?

If an element is searched first and then deleted, the time complexity is indeed O(n). However, the O(1) advantage of linked lists in insertion and deletion can be realized in other applications. For example, in the implementation of double-ended queues using linked lists, we maintain pointers always pointing to the head and tail nodes, making each insertion and deletion operation O(1).

Q: In the image \"Linked List Definition and Storage Method\", do the light blue storage nodes occupy a single memory address, or do they share half with the node value?

The diagram is just a qualitative representation; quantitative analysis depends on specific situations.

  • Different types of node values occupy different amounts of space, such as int, long, double, and object instances.
  • The memory space occupied by pointer variables depends on the operating system and compilation environment used, usually 8 bytes or 4 bytes.

Q: Is adding elements to the end of a list always O(1)?

If adding an element exceeds the list length, the list needs to be expanded first. The system will request a new memory block and move all elements of the original list over, in which case the time complexity becomes O(n).

Q: The statement \"The emergence of lists greatly improves the practicality of arrays, but may lead to some memory space wastage\" - does this refer to the memory occupied by additional variables like capacity, length, and expansion multiplier?

The space wastage here mainly refers to two aspects: on the one hand, lists are set with an initial length, which we may not always need; on the other hand, to prevent frequent expansion, expansion usually multiplies by a coefficient, such as \\(\\times 1.5\\). This results in many empty slots, which we typically cannot fully fill.

Q: In Python, after initializing n = [1, 2, 3], the addresses of these 3 elements are contiguous, but initializing m = [2, 1, 3] shows that each element's id is not consecutive but identical to those in n. If the addresses of these elements are not contiguous, is m still an array?

If we replace list elements with linked list nodes n = [n1, n2, n3, n4, n5], these 5 node objects are also typically dispersed throughout memory. However, given a list index, we can still access the node's memory address in O(1) time, thereby accessing the corresponding node. This is because the array stores references to the nodes, not the nodes themselves.

Unlike many languages, in Python, numbers are also wrapped as objects, and lists store references to these numbers, not the numbers themselves. Therefore, we find that the same number in two arrays has the same id, and these numbers' memory addresses need not be contiguous.

Q: The std::list in C++ STL has already implemented a doubly linked list, but it seems that some algorithm books don't directly use it. Is there any limitation?

On the one hand, we often prefer to use arrays to implement algorithms, only using linked lists when necessary, mainly for two reasons.

  • Space overhead: Since each element requires two additional pointers (one for the previous element and one for the next), std::list usually occupies more space than std::vector.
  • Cache unfriendly: As the data is not stored continuously, std::list has a lower cache utilization rate. Generally, std::vector performs better.

On the other hand, linked lists are primarily necessary for binary trees and graphs. Stacks and queues are often implemented using the programming language's stack and queue classes, rather than linked lists.

Q: Does initializing a list res = [0] * self.size() result in each element of res referencing the same address?

No. However, this issue arises with two-dimensional arrays, for example, initializing a two-dimensional list res = [[0] * self.size()] would reference the same list [0] multiple times.

Q: In deleting a node, is it necessary to break the reference to its successor node?

From the perspective of data structures and algorithms (problem-solving), it's okay not to break the link, as long as the program's logic is correct. From the perspective of standard libraries, breaking the link is safer and more logically clear. If the link is not broken, and the deleted node is not properly recycled, it could affect the recycling of the successor node's memory.

"},{"location":"chapter_computational_complexity/","title":"Chapter 2. \u00a0 Complexity Analysis","text":"

Abstract

Complexity analysis is like a space-time navigator in the vast universe of algorithms.

It guides us in exploring deeper within the the dimensions of time and space, seeking more elegant solutions.

"},{"location":"chapter_computational_complexity/#chapter-contents","title":"Chapter Contents","text":"
  • 2.1 \u00a0 Algorithm Efficiency Assessment
  • 2.2 \u00a0 Iteration and Recursion
  • 2.3 \u00a0 Time Complexity
  • 2.4 \u00a0 Space Complexity
  • 2.5 \u00a0 Summary
"},{"location":"chapter_computational_complexity/iteration_and_recursion/","title":"2.2 \u00a0 Iteration and Recursion","text":"

In algorithms, repeatedly performing a task is common and closely related to complexity analysis. Therefore, before introducing time complexity and space complexity, let's first understand how to implement task repetition in programs, focusing on two basic programming control structures: iteration and recursion.

"},{"location":"chapter_computational_complexity/iteration_and_recursion/#221-iteration","title":"2.2.1 \u00a0 Iteration","text":"

\"Iteration\" is a control structure for repeatedly performing a task. In iteration, a program repeats a block of code as long as a certain condition is met, until this condition is no longer satisfied.

"},{"location":"chapter_computational_complexity/iteration_and_recursion/#1-for-loop","title":"1. \u00a0 for Loop","text":"

The for loop is one of the most common forms of iteration, suitable for use when the number of iterations is known in advance.

The following function implements the sum \\(1 + 2 + \\dots + n\\) using a for loop, with the sum result recorded in the variable res. Note that in Python, range(a, b) corresponds to a \"left-closed, right-open\" interval, covering \\(a, a + 1, \\dots, b-1\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig iteration.py
def for_loop(n: int) -> int:\n    \"\"\"for \u5faa\u73af\"\"\"\n    res = 0\n    # \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for i in range(1, n + 1):\n        res += i\n    return res\n
iteration.cpp
/* for \u5faa\u73af */\nint forLoop(int n) {\n    int res = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; ++i) {\n        res += i;\n    }\n    return res;\n}\n
iteration.java
/* for \u5faa\u73af */\nint forLoop(int n) {\n    int res = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; i++) {\n        res += i;\n    }\n    return res;\n}\n
iteration.cs
/* for \u5faa\u73af */\nint ForLoop(int n) {\n    int res = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; i++) {\n        res += i;\n    }\n    return res;\n}\n
iteration.go
/* for \u5faa\u73af */\nfunc forLoop(n int) int {\n    res := 0\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for i := 1; i <= n; i++ {\n        res += i\n    }\n    return res\n}\n
iteration.swift
/* for \u5faa\u73af */\nfunc forLoop(n: Int) -> Int {\n    var res = 0\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for i in 1 ... n {\n        res += i\n    }\n    return res\n}\n
iteration.js
/* for \u5faa\u73af */\nfunction forLoop(n) {\n    let res = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for (let i = 1; i <= n; i++) {\n        res += i;\n    }\n    return res;\n}\n
iteration.ts
/* for \u5faa\u73af */\nfunction forLoop(n: number): number {\n    let res = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for (let i = 1; i <= n; i++) {\n        res += i;\n    }\n    return res;\n}\n
iteration.dart
/* for \u5faa\u73af */\nint forLoop(int n) {\n  int res = 0;\n  // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n  for (int i = 1; i <= n; i++) {\n    res += i;\n  }\n  return res;\n}\n
iteration.rs
/* for \u5faa\u73af */\nfn for_loop(n: i32) -> i32 {\n    let mut res = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for i in 1..=n {\n        res += i;\n    }\n    res\n} \n
iteration.c
/* for \u5faa\u73af */\nint forLoop(int n) {\n    int res = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; i++) {\n        res += i;\n    }\n    return res;\n}\n
iteration.zig
// for \u5faa\u73af\nfn forLoop(n: usize) i32 {\n    var res: i32 = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for (1..n+1) |i| {\n        res = res + @as(i32, @intCast(i));\n    }\n    return res;\n} \n
Visualizing Code

Full Screen >

The flowchart below represents this sum function.

Figure 2-1 \u00a0 Flowchart of the Sum Function

The number of operations in this sum function is proportional to the input data size \\(n\\), or in other words, it has a \"linear relationship\". This is actually what time complexity describes. This topic will be detailed in the next section.

"},{"location":"chapter_computational_complexity/iteration_and_recursion/#2-while-loop","title":"2. \u00a0 while Loop","text":"

Similar to the for loop, the while loop is another method to implement iteration. In a while loop, the program checks the condition in each round; if the condition is true, it continues, otherwise, the loop ends.

Below we use a while loop to implement the sum \\(1 + 2 + \\dots + n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig iteration.py
def while_loop(n: int) -> int:\n    \"\"\"while \u5faa\u73af\"\"\"\n    res = 0\n    i = 1  # \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    # \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while i <= n:\n        res += i\n        i += 1  # \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    return res\n
iteration.cpp
/* while \u5faa\u73af */\nint whileLoop(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while (i <= n) {\n        res += i;\n        i++; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    return res;\n}\n
iteration.java
/* while \u5faa\u73af */\nint whileLoop(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while (i <= n) {\n        res += i;\n        i++; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    return res;\n}\n
iteration.cs
/* while \u5faa\u73af */\nint WhileLoop(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while (i <= n) {\n        res += i;\n        i += 1; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    return res;\n}\n
iteration.go
/* while \u5faa\u73af */\nfunc whileLoop(n int) int {\n    res := 0\n    // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    i := 1\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for i <= n {\n        res += i\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i++\n    }\n    return res\n}\n
iteration.swift
/* while \u5faa\u73af */\nfunc whileLoop(n: Int) -> Int {\n    var res = 0\n    var i = 1 // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while i <= n {\n        res += i\n        i += 1 // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    return res\n}\n
iteration.js
/* while \u5faa\u73af */\nfunction whileLoop(n) {\n    let res = 0;\n    let i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while (i <= n) {\n        res += i;\n        i++; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    return res;\n}\n
iteration.ts
/* while \u5faa\u73af */\nfunction whileLoop(n: number): number {\n    let res = 0;\n    let i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while (i <= n) {\n        res += i;\n        i++; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    return res;\n}\n
iteration.dart
/* while \u5faa\u73af */\nint whileLoop(int n) {\n  int res = 0;\n  int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n  // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n  while (i <= n) {\n    res += i;\n    i++; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n  }\n  return res;\n}\n
iteration.rs
/* while \u5faa\u73af */\nfn while_loop(n: i32) -> i32 {\n    let mut res = 0;\n    let mut i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while i <= n {\n        res += i;\n        i += 1; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    res\n}\n
iteration.c
/* while \u5faa\u73af */\nint whileLoop(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while (i <= n) {\n        res += i;\n        i++; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    return res;\n}\n
iteration.zig
// while \u5faa\u73af\nfn whileLoop(n: i32) i32 {\n    var res: i32 = 0;\n    var i: i32 = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while (i <= n) {\n        res += @intCast(i);\n        i += 1;\n    }\n    return res;\n}\n
Visualizing Code

Full Screen >

The while loop is more flexible than the for loop. In a while loop, we can freely design the initialization and update steps of the condition variable.

For example, in the following code, the condition variable \\(i\\) is updated twice in each round, which would be inconvenient to implement with a for loop:

PythonC++JavaC#GoSwiftJSTSDartRustCZig iteration.py
def while_loop_ii(n: int) -> int:\n    \"\"\"while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09\"\"\"\n    res = 0\n    i = 1  # \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    # \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while i <= n:\n        res += i\n        # \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i += 1\n        i *= 2\n    return res\n
iteration.cpp
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nint whileLoopII(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while (i <= n) {\n        res += i;\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i++;\n        i *= 2;\n    }\n    return res;\n}\n
iteration.java
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nint whileLoopII(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while (i <= n) {\n        res += i;\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i++;\n        i *= 2;\n    }\n    return res;\n}\n
iteration.cs
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nint WhileLoopII(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, 4, 5...\n    while (i <= n) {\n        res += i;\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i += 1; \n        i *= 2;\n    }\n    return res;\n}\n
iteration.go
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nfunc whileLoopII(n int) int {\n    res := 0\n    // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    i := 1\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    for i <= n {\n        res += i\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i++\n        i *= 2\n    }\n    return res\n}\n
iteration.swift
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nfunc whileLoopII(n: Int) -> Int {\n    var res = 0\n    var i = 1 // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while i <= n {\n        res += i\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i += 1\n        i *= 2\n    }\n    return res\n}\n
iteration.js
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nfunction whileLoopII(n) {\n    let res = 0;\n    let i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while (i <= n) {\n        res += i;\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i++;\n        i *= 2;\n    }\n    return res;\n}\n
iteration.ts
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nfunction whileLoopII(n: number): number {\n    let res = 0;\n    let i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while (i <= n) {\n        res += i;\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i++;\n        i *= 2;\n    }\n    return res;\n}\n
iteration.dart
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nint whileLoopII(int n) {\n  int res = 0;\n  int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n  // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n  while (i <= n) {\n    res += i;\n    // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    i++;\n    i *= 2;\n  }\n  return res;\n}\n
iteration.rs
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nfn while_loop_ii(n: i32) -> i32 {\n    let mut res = 0;\n    let mut i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while i <= n {\n        res += i;\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i += 1;\n        i *= 2;\n    }\n    res\n}\n
iteration.c
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nint whileLoopII(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while (i <= n) {\n        res += i;\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i++;\n        i *= 2;\n    }\n    return res;\n}\n
iteration.zig
//  while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09\nfn whileLoopII(n: i32) i32 {\n    var res: i32 = 0;\n    var i: i32 = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while (i <= n) {\n        res += @intCast(i);\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i += 1;\n        i *= 2;\n    }\n    return res;\n}\n
Visualizing Code

Full Screen >

Overall, for loops are more concise, while while loops are more flexible. Both can implement iterative structures. Which one to use should be determined based on the specific requirements of the problem.

"},{"location":"chapter_computational_complexity/iteration_and_recursion/#3-nested-loops","title":"3. \u00a0 Nested Loops","text":"

We can nest one loop structure within another. Below is an example using for loops:

PythonC++JavaC#GoSwiftJSTSDartRustCZig iteration.py
def nested_for_loop(n: int) -> str:\n    \"\"\"\u53cc\u5c42 for \u5faa\u73af\"\"\"\n    res = \"\"\n    # \u5faa\u73af i = 1, 2, ..., n-1, n\n    for i in range(1, n + 1):\n        # \u5faa\u73af j = 1, 2, ..., n-1, n\n        for j in range(1, n + 1):\n            res += f\"({i}, {j}), \"\n    return res\n
iteration.cpp
/* \u53cc\u5c42 for \u5faa\u73af */\nstring nestedForLoop(int n) {\n    ostringstream res;\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; ++i) {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for (int j = 1; j <= n; ++j) {\n            res << \"(\" << i << \", \" << j << \"), \";\n        }\n    }\n    return res.str();\n}\n
iteration.java
/* \u53cc\u5c42 for \u5faa\u73af */\nString nestedForLoop(int n) {\n    StringBuilder res = new StringBuilder();\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; i++) {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for (int j = 1; j <= n; j++) {\n            res.append(\"(\" + i + \", \" + j + \"), \");\n        }\n    }\n    return res.toString();\n}\n
iteration.cs
/* \u53cc\u5c42 for \u5faa\u73af */\nstring NestedForLoop(int n) {\n    StringBuilder res = new();\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; i++) {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for (int j = 1; j <= n; j++) {\n            res.Append($\"({i}, {j}), \");\n        }\n    }\n    return res.ToString();\n}\n
iteration.go
/* \u53cc\u5c42 for \u5faa\u73af */\nfunc nestedForLoop(n int) string {\n    res := \"\"\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for i := 1; i <= n; i++ {\n        for j := 1; j <= n; j++ {\n            // \u5faa\u73af j = 1, 2, ..., n-1, n\n            res += fmt.Sprintf(\"(%d, %d), \", i, j)\n        }\n    }\n    return res\n}\n
iteration.swift
/* \u53cc\u5c42 for \u5faa\u73af */\nfunc nestedForLoop(n: Int) -> String {\n    var res = \"\"\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for i in 1 ... n {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for j in 1 ... n {\n            res.append(\"(\\(i), \\(j)), \")\n        }\n    }\n    return res\n}\n
iteration.js
/* \u53cc\u5c42 for \u5faa\u73af */\nfunction nestedForLoop(n) {\n    let res = '';\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for (let i = 1; i <= n; i++) {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for (let j = 1; j <= n; j++) {\n            res += `(${i}, ${j}), `;\n        }\n    }\n    return res;\n}\n
iteration.ts
/* \u53cc\u5c42 for \u5faa\u73af */\nfunction nestedForLoop(n: number): string {\n    let res = '';\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for (let i = 1; i <= n; i++) {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for (let j = 1; j <= n; j++) {\n            res += `(${i}, ${j}), `;\n        }\n    }\n    return res;\n}\n
iteration.dart
/* \u53cc\u5c42 for \u5faa\u73af */\nString nestedForLoop(int n) {\n  String res = \"\";\n  // \u5faa\u73af i = 1, 2, ..., n-1, n\n  for (int i = 1; i <= n; i++) {\n    // \u5faa\u73af j = 1, 2, ..., n-1, n\n    for (int j = 1; j <= n; j++) {\n      res += \"($i, $j), \";\n    }\n  }\n  return res;\n}\n
iteration.rs
/* \u53cc\u5c42 for \u5faa\u73af */\nfn nested_for_loop(n: i32) -> String {\n    let mut res = vec![];\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for i in 1..=n {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for j in 1..=n {\n            res.push(format!(\"({}, {}), \", i, j));\n        }\n    }\n    res.join(\"\")\n}\n
iteration.c
/* \u53cc\u5c42 for \u5faa\u73af */\nchar *nestedForLoop(int n) {\n    // n * n \u4e3a\u5bf9\u5e94\u70b9\u6570\u91cf\uff0c\"(i, j), \" \u5bf9\u5e94\u5b57\u7b26\u4e32\u957f\u6700\u5927\u4e3a 6+10*2\uff0c\u52a0\u4e0a\u6700\u540e\u4e00\u4e2a\u7a7a\u5b57\u7b26 \\0 \u7684\u989d\u5916\u7a7a\u95f4\n    int size = n * n * 26 + 1;\n    char *res = malloc(size * sizeof(char));\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; i++) {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for (int j = 1; j <= n; j++) {\n            char tmp[26];\n            snprintf(tmp, sizeof(tmp), \"(%d, %d), \", i, j);\n            strncat(res, tmp, size - strlen(res) - 1);\n        }\n    }\n    return res;\n}\n
iteration.zig
// \u53cc\u5c42 for \u5faa\u73af\nfn nestedForLoop(allocator: Allocator, n: usize) ![]const u8 {\n    var res = std.ArrayList(u8).init(allocator);\n    defer res.deinit();\n    var buffer: [20]u8 = undefined;\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for (1..n+1) |i| {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for (1..n+1) |j| {\n            var _str = try std.fmt.bufPrint(&buffer, \"({d}, {d}), \", .{i, j});\n            try res.appendSlice(_str);\n        }\n    }\n    return res.toOwnedSlice();\n}\n
Visualizing Code

Full Screen >

The flowchart below represents this nested loop.

Figure 2-2 \u00a0 Flowchart of the Nested Loop

In this case, the number of operations in the function is proportional to \\(n^2\\), or the algorithm's running time and the input data size \\(n\\) have a \"quadratic relationship\".

We can continue adding nested loops, each nesting is a \"dimensional escalation,\" which will increase the time complexity to \"cubic,\" \"quartic,\" and so on.

"},{"location":"chapter_computational_complexity/iteration_and_recursion/#222-recursion","title":"2.2.2 \u00a0 Recursion","text":"

\"Recursion\" is an algorithmic strategy that solves problems by having a function call itself. It mainly consists of two phases.

  1. Recursion: The program continuously calls itself, usually with smaller or more simplified parameters, until reaching a \"termination condition.\"
  2. Return: Upon triggering the \"termination condition,\" the program begins to return from the deepest recursive function, aggregating the results of each layer.

From an implementation perspective, recursive code mainly includes three elements.

  1. Termination Condition: Determines when to switch from \"recursion\" to \"return.\"
  2. Recursive Call: Corresponds to \"recursion,\" where the function calls itself, usually with smaller or more simplified parameters.
  3. Return Result: Corresponds to \"return,\" where the result of the current recursion level is returned to the previous layer.

Observe the following code, where calling the function recur(n) completes the computation of \\(1 + 2 + \\dots + n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig recursion.py
def recur(n: int) -> int:\n    \"\"\"\u9012\u5f52\"\"\"\n    # \u7ec8\u6b62\u6761\u4ef6\n    if n == 1:\n        return 1\n    # \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    res = recur(n - 1)\n    # \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res\n
recursion.cpp
/* \u9012\u5f52 */\nint recur(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 1)\n        return 1;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    int res = recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res;\n}\n
recursion.java
/* \u9012\u5f52 */\nint recur(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 1)\n        return 1;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    int res = recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res;\n}\n
recursion.cs
/* \u9012\u5f52 */\nint Recur(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 1)\n        return 1;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    int res = Recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res;\n}\n
recursion.go
/* \u9012\u5f52 */\nfunc recur(n int) int {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if n == 1 {\n        return 1\n    }\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    res := recur(n - 1)\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res\n}\n
recursion.swift
/* \u9012\u5f52 */\nfunc recur(n: Int) -> Int {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if n == 1 {\n        return 1\n    }\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    let res = recur(n: n - 1)\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res\n}\n
recursion.js
/* \u9012\u5f52 */\nfunction recur(n) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n === 1) return 1;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    const res = recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res;\n}\n
recursion.ts
/* \u9012\u5f52 */\nfunction recur(n: number): number {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n === 1) return 1;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    const res = recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res;\n}\n
recursion.dart
/* \u9012\u5f52 */\nint recur(int n) {\n  // \u7ec8\u6b62\u6761\u4ef6\n  if (n == 1) return 1;\n  // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n  int res = recur(n - 1);\n  // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n  return n + res;\n}\n
recursion.rs
/* \u9012\u5f52 */\nfn recur(n: i32) -> i32 {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if n == 1 {\n        return 1;\n    }\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    let res = recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    n + res\n}\n
recursion.c
/* \u9012\u5f52 */\nint recur(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 1)\n        return 1;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    int res = recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res;\n}\n
recursion.zig
// \u9012\u5f52\u51fd\u6570\nfn recur(n: i32) i32 {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 1) {\n        return 1;\n    }\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    var res: i32 = recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res;\n}\n
Visualizing Code

Full Screen >

The Figure 2-3 shows the recursive process of this function.

Figure 2-3 \u00a0 Recursive Process of the Sum Function

Although iteration and recursion can achieve the same results from a computational standpoint, they represent two entirely different paradigms of thinking and solving problems.

  • Iteration: Solves problems \"from the bottom up.\" It starts with the most basic steps, then repeatedly adds or accumulates these steps until the task is complete.
  • Recursion: Solves problems \"from the top down.\" It breaks down the original problem into smaller sub-problems, each of which has the same form as the original problem. These sub-problems are then further decomposed into even smaller sub-problems, stopping at the base case (whose solution is known).

Taking the sum function as an example, let's define the problem as \\(f(n) = 1 + 2 + \\dots + n\\).

  • Iteration: In a loop, simulate the summing process, iterating from \\(1\\) to \\(n\\), performing the sum operation in each round, to obtain \\(f(n)\\).
  • Recursion: Break down the problem into sub-problems \\(f(n) = n + f(n-1)\\), continuously (recursively) decomposing until reaching the base case \\(f(1) = 1\\) and then stopping.
"},{"location":"chapter_computational_complexity/iteration_and_recursion/#1-call-stack","title":"1. \u00a0 Call Stack","text":"

Each time a recursive function calls itself, the system allocates memory for the newly initiated function to store local variables, call addresses, and other information. This leads to two main consequences.

  • The function's context data is stored in a memory area called \"stack frame space\" and is only released after the function returns. Therefore, recursion generally consumes more memory space than iteration.
  • Recursive calls introduce additional overhead. Hence, recursion is usually less time-efficient than loops.

As shown in the Figure 2-4 , there are \\(n\\) unreturned recursive functions before triggering the termination condition, indicating a recursion depth of \\(n\\).

Figure 2-4 \u00a0 Recursion Call Depth

In practice, the depth of recursion allowed by programming languages is usually limited, and excessively deep recursion can lead to stack overflow errors.

"},{"location":"chapter_computational_complexity/iteration_and_recursion/#2-tail-recursion","title":"2. \u00a0 Tail Recursion","text":"

Interestingly, if a function makes its recursive call as the last step before returning, it can be optimized by compilers or interpreters to be as space-efficient as iteration. This scenario is known as \"tail recursion\".

  • Regular Recursion: The function needs to perform more code after returning to the previous level, so the system needs to save the context of the previous call.
  • Tail Recursion: The recursive call is the last operation before the function returns, meaning no further actions are required upon returning to the previous level, so the system doesn't need to save the context of the previous level's function.

For example, in calculating \\(1 + 2 + \\dots + n\\), we can make the result variable res a parameter of the function, thereby achieving tail recursion:

PythonC++JavaC#GoSwiftJSTSDartRustCZig recursion.py
def tail_recur(n, res):\n    \"\"\"\u5c3e\u9012\u5f52\"\"\"\n    # \u7ec8\u6b62\u6761\u4ef6\n    if n == 0:\n        return res\n    # \u5c3e\u9012\u5f52\u8c03\u7528\n    return tail_recur(n - 1, res + n)\n
recursion.cpp
/* \u5c3e\u9012\u5f52 */\nint tailRecur(int n, int res) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 0)\n        return res;\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n - 1, res + n);\n}\n
recursion.java
/* \u5c3e\u9012\u5f52 */\nint tailRecur(int n, int res) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 0)\n        return res;\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n - 1, res + n);\n}\n
recursion.cs
/* \u5c3e\u9012\u5f52 */\nint TailRecur(int n, int res) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 0)\n        return res;\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return TailRecur(n - 1, res + n);\n}\n
recursion.go
/* \u5c3e\u9012\u5f52 */\nfunc tailRecur(n int, res int) int {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if n == 0 {\n        return res\n    }\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n-1, res+n)\n}\n
recursion.swift
/* \u5c3e\u9012\u5f52 */\nfunc tailRecur(n: Int, res: Int) -> Int {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if n == 0 {\n        return res\n    }\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n: n - 1, res: res + n)\n}\n
recursion.js
/* \u5c3e\u9012\u5f52 */\nfunction tailRecur(n, res) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n === 0) return res;\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n - 1, res + n);\n}\n
recursion.ts
/* \u5c3e\u9012\u5f52 */\nfunction tailRecur(n: number, res: number): number {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n === 0) return res;\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n - 1, res + n);\n}\n
recursion.dart
/* \u5c3e\u9012\u5f52 */\nint tailRecur(int n, int res) {\n  // \u7ec8\u6b62\u6761\u4ef6\n  if (n == 0) return res;\n  // \u5c3e\u9012\u5f52\u8c03\u7528\n  return tailRecur(n - 1, res + n);\n}\n
recursion.rs
/* \u5c3e\u9012\u5f52 */\nfn tail_recur(n: i32, res: i32) -> i32 {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if n == 0 {\n        return res;\n    }\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    tail_recur(n - 1, res + n)\n}\n
recursion.c
/* \u5c3e\u9012\u5f52 */\nint tailRecur(int n, int res) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 0)\n        return res;\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n - 1, res + n);\n}\n
recursion.zig
// \u5c3e\u9012\u5f52\u51fd\u6570\nfn tailRecur(n: i32, res: i32) i32 {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 0) {\n        return res;\n    }\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n - 1, res + n);\n}\n
Visualizing Code

Full Screen >

The execution process of tail recursion is shown in the following figure. Comparing regular recursion and tail recursion, the point of the summation operation is different.

  • Regular Recursion: The summation operation occurs during the \"return\" phase, requiring another summation after each layer returns.
  • Tail Recursion: The summation operation occurs during the \"recursion\" phase, and the \"return\" phase only involves returning through each layer.

Figure 2-5 \u00a0 Tail Recursion Process

Tip

Note that many compilers or interpreters do not support tail recursion optimization. For example, Python does not support tail recursion optimization by default, so even if the function is in the form of tail recursion, it may still encounter stack overflow issues.

"},{"location":"chapter_computational_complexity/iteration_and_recursion/#3-recursion-tree","title":"3. \u00a0 Recursion Tree","text":"

When dealing with algorithms related to \"divide and conquer\", recursion often offers a more intuitive approach and more readable code than iteration. Take the \"Fibonacci sequence\" as an example.

Question

Given a Fibonacci sequence \\(0, 1, 1, 2, 3, 5, 8, 13, \\dots\\), find the \\(n\\)th number in the sequence.

Let the \\(n\\)th number of the Fibonacci sequence be \\(f(n)\\), it's easy to deduce two conclusions:

  • The first two numbers of the sequence are \\(f(1) = 0\\) and \\(f(2) = 1\\).
  • Each number in the sequence is the sum of the two preceding ones, that is, \\(f(n) = f(n - 1) + f(n - 2)\\).

Using the recursive relation, and considering the first two numbers as termination conditions, we can write the recursive code. Calling fib(n) will yield the \\(n\\)th number of the Fibonacci sequence:

PythonC++JavaC#GoSwiftJSTSDartRustCZig recursion.py
def fib(n: int) -> int:\n    \"\"\"\u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52\"\"\"\n    # \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if n == 1 or n == 2:\n        return n - 1\n    # \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    res = fib(n - 1) + fib(n - 2)\n    # \u8fd4\u56de\u7ed3\u679c f(n)\n    return res\n
recursion.cpp
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nint fib(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if (n == 1 || n == 2)\n        return n - 1;\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    int res = fib(n - 1) + fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res;\n}\n
recursion.java
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nint fib(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if (n == 1 || n == 2)\n        return n - 1;\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    int res = fib(n - 1) + fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res;\n}\n
recursion.cs
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nint Fib(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if (n == 1 || n == 2)\n        return n - 1;\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    int res = Fib(n - 1) + Fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res;\n}\n
recursion.go
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nfunc fib(n int) int {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if n == 1 || n == 2 {\n        return n - 1\n    }\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    res := fib(n-1) + fib(n-2)\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res\n}\n
recursion.swift
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nfunc fib(n: Int) -> Int {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if n == 1 || n == 2 {\n        return n - 1\n    }\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    let res = fib(n: n - 1) + fib(n: n - 2)\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res\n}\n
recursion.js
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nfunction fib(n) {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if (n === 1 || n === 2) return n - 1;\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    const res = fib(n - 1) + fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res;\n}\n
recursion.ts
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nfunction fib(n: number): number {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if (n === 1 || n === 2) return n - 1;\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    const res = fib(n - 1) + fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res;\n}\n
recursion.dart
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nint fib(int n) {\n  // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n  if (n == 1 || n == 2) return n - 1;\n  // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n  int res = fib(n - 1) + fib(n - 2);\n  // \u8fd4\u56de\u7ed3\u679c f(n)\n  return res;\n}\n
recursion.rs
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nfn fib(n: i32) -> i32 {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if n == 1 || n == 2 {\n        return n - 1;\n    }\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    let res = fib(n - 1) + fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c\n    res\n}\n
recursion.c
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nint fib(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if (n == 1 || n == 2)\n        return n - 1;\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    int res = fib(n - 1) + fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res;\n}\n
recursion.zig
// \u6590\u6ce2\u90a3\u5951\u6570\u5217\nfn fib(n: i32) i32 {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if (n == 1 or n == 2) {\n        return n - 1;\n    }\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    var res: i32 = fib(n - 1) + fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res;\n}\n
Visualizing Code

Full Screen >

Observing the above code, we see that it recursively calls two functions within itself, meaning that one call generates two branching calls. As illustrated below, this continuous recursive calling eventually creates a \"recursion tree\" with a depth of \\(n\\).

Figure 2-6 \u00a0 Fibonacci Sequence Recursion Tree

Fundamentally, recursion embodies the paradigm of \"breaking down a problem into smaller sub-problems.\" This divide-and-conquer strategy is crucial.

  • From an algorithmic perspective, many important strategies like searching, sorting, backtracking, divide-and-conquer, and dynamic programming directly or indirectly use this way of thinking.
  • From a data structure perspective, recursion is naturally suited for dealing with linked lists, trees, and graphs, as they are well suited for analysis using the divide-and-conquer approach.
"},{"location":"chapter_computational_complexity/iteration_and_recursion/#223-comparison","title":"2.2.3 \u00a0 Comparison","text":"

Summarizing the above content, the following table shows the differences between iteration and recursion in terms of implementation, performance, and applicability.

Table: Comparison of Iteration and Recursion Characteristics

Iteration Recursion Approach Loop structure Function calls itself Time Efficiency Generally higher efficiency, no function call overhead Each function call generates overhead Memory Usage Typically uses a fixed size of memory space Accumulative function calls can use a substantial amount of stack frame space Suitable Problems Suitable for simple loop tasks, intuitive and readable code Suitable for problem decomposition, like trees, graphs, divide-and-conquer, backtracking, etc., concise and clear code structure

Tip

If you find the following content difficult to understand, consider revisiting it after reading the \"Stack\" chapter.

So, what is the intrinsic connection between iteration and recursion? Taking the above recursive function as an example, the summation operation occurs during the recursion's \"return\" phase. This means that the initially called function is actually the last to complete its summation operation, mirroring the \"last in, first out\" principle of a stack.

In fact, recursive terms like \"call stack\" and \"stack frame space\" hint at the close relationship between recursion and stacks.

  1. Recursion: When a function is called, the system allocates a new stack frame on the \"call stack\" for that function, storing local variables, parameters, return addresses, and other data.
  2. Return: When a function completes execution and returns, the corresponding stack frame is removed from the \"call stack,\" restoring the execution environment of the previous function.

Therefore, we can use an explicit stack to simulate the behavior of the call stack, thus transforming recursion into an iterative form:

PythonC++JavaC#GoSwiftJSTSDartRustCZig recursion.py
def for_loop_recur(n: int) -> int:\n    \"\"\"\u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52\"\"\"\n    # \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    stack = []\n    res = 0\n    # \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for i in range(n, 0, -1):\n        # \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.append(i)\n    # \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while stack:\n        # \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.pop()\n    # res = 1+2+3+...+n\n    return res\n
recursion.cpp
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nint forLoopRecur(int n) {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    stack<int> stack;\n    int res = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for (int i = n; i > 0; i--) {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.push(i);\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while (!stack.empty()) {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.top();\n        stack.pop();\n    }\n    // res = 1+2+3+...+n\n    return res;\n}\n
recursion.java
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nint forLoopRecur(int n) {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    Stack<Integer> stack = new Stack<>();\n    int res = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for (int i = n; i > 0; i--) {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.push(i);\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while (!stack.isEmpty()) {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.pop();\n    }\n    // res = 1+2+3+...+n\n    return res;\n}\n
recursion.cs
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nint ForLoopRecur(int n) {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    Stack<int> stack = new();\n    int res = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for (int i = n; i > 0; i--) {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.Push(i);\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while (stack.Count > 0) {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.Pop();\n    }\n    // res = 1+2+3+...+n\n    return res;\n}\n
recursion.go
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nfunc forLoopRecur(n int) int {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    stack := list.New()\n    res := 0\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for i := n; i > 0; i-- {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.PushBack(i)\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    for stack.Len() != 0 {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.Back().Value.(int)\n        stack.Remove(stack.Back())\n    }\n    // res = 1+2+3+...+n\n    return res\n}\n
recursion.swift
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nfunc forLoopRecur(n: Int) -> Int {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    var stack: [Int] = []\n    var res = 0\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for i in stride(from: n, to: 0, by: -1) {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.append(i)\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while !stack.isEmpty {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.removeLast()\n    }\n    // res = 1+2+3+...+n\n    return res\n}\n
recursion.js
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nfunction forLoopRecur(n) {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    const stack = [];\n    let res = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for (let i = n; i > 0; i--) {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.push(i);\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while (stack.length) {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.pop();\n    }\n    // res = 1+2+3+...+n\n    return res;\n}\n
recursion.ts
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nfunction forLoopRecur(n: number): number {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808 \n    const stack: number[] = [];\n    let res: number = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for (let i = n; i > 0; i--) {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.push(i);\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while (stack.length) {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.pop();\n    }\n    // res = 1+2+3+...+n\n    return res;\n}\n
recursion.dart
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nint forLoopRecur(int n) {\n  // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n  List<int> stack = [];\n  int res = 0;\n  // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n  for (int i = n; i > 0; i--) {\n    // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n    stack.add(i);\n  }\n  // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n  while (!stack.isEmpty) {\n    // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n    res += stack.removeLast();\n  }\n  // res = 1+2+3+...+n\n  return res;\n}\n
recursion.rs
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nfn for_loop_recur(n: i32) -> i32 {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    let mut stack = Vec::new();\n    let mut res = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for i in (1..=n).rev() {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.push(i);\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while !stack.is_empty() {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.pop().unwrap();\n    }\n    // res = 1+2+3+...+n\n    res\n}\n
recursion.c
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nint forLoopRecur(int n) {\n    int stack[1000]; // \u501f\u52a9\u4e00\u4e2a\u5927\u6570\u7ec4\u6765\u6a21\u62df\u6808\n    int top = -1;    // \u6808\u9876\u7d22\u5f15\n    int res = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for (int i = n; i > 0; i--) {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack[1 + top++] = i;\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while (top >= 0) {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack[top--];\n    }\n    // res = 1+2+3+...+n\n    return res;\n}\n
recursion.zig
// \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52\nfn forLoopRecur(comptime n: i32) i32 {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    var stack: [n]i32 = undefined;\n    var res: i32 = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    var i: usize = n;\n    while (i > 0) {\n        stack[i - 1] = @intCast(i);\n        i -= 1;\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    var index: usize = n;\n    while (index > 0) {\n        index -= 1;\n        res += stack[index];\n    }\n    // res = 1+2+3+...+n\n    return res;\n}\n
Visualizing Code

Full Screen >

Observing the above code, when recursion is transformed into iteration, the code becomes more complex. Although iteration and recursion can often be transformed into each other, it's not always advisable to do so for two reasons:

  • The transformed code may become harder to understand and less readable.
  • For some complex problems, simulating the behavior of the system's call stack can be quite challenging.

In summary, choosing between iteration and recursion depends on the nature of the specific problem. In programming practice, weighing the pros and cons of each and choosing the appropriate method for the situation is essential.

"},{"location":"chapter_computational_complexity/performance_evaluation/","title":"2.1 \u00a0 Algorithm Efficiency Assessment","text":"

In algorithm design, we pursue the following two objectives in sequence.

  1. Finding a Solution to the Problem: The algorithm should reliably find the correct solution within the stipulated range of inputs.
  2. Seeking the Optimal Solution: For the same problem, multiple solutions might exist, and we aim to find the most efficient algorithm possible.

In other words, under the premise of being able to solve the problem, algorithm efficiency has become the main criterion for evaluating the merits of an algorithm, which includes the following two dimensions.

  • Time Efficiency: The speed at which an algorithm runs.
  • Space Efficiency: The size of the memory space occupied by an algorithm.

In short, our goal is to design data structures and algorithms that are both fast and memory-efficient. Effectively assessing algorithm efficiency is crucial because only then can we compare various algorithms and guide the process of algorithm design and optimization.

There are mainly two methods of efficiency assessment: actual testing and theoretical estimation.

"},{"location":"chapter_computational_complexity/performance_evaluation/#211-actual-testing","title":"2.1.1 \u00a0 Actual Testing","text":"

Suppose we have algorithms A and B, both capable of solving the same problem, and we need to compare their efficiencies. The most direct method is to use a computer to run these two algorithms and monitor and record their runtime and memory usage. This assessment method reflects the actual situation but has significant limitations.

On one hand, it's difficult to eliminate interference from the testing environment. Hardware configurations can affect algorithm performance. For example, algorithm A might run faster than B on one computer, but the opposite result may occur on another computer with different configurations. This means we would need to test on a variety of machines to calculate average efficiency, which is impractical.

On the other hand, conducting a full test is very resource-intensive. As the volume of input data changes, the efficiency of the algorithms may vary. For example, with smaller data volumes, algorithm A might run faster than B, but the opposite might be true with larger data volumes. Therefore, to draw convincing conclusions, we need to test a wide range of input data sizes, which requires significant computational resources.

"},{"location":"chapter_computational_complexity/performance_evaluation/#212-theoretical-estimation","title":"2.1.2 \u00a0 Theoretical Estimation","text":"

Due to the significant limitations of actual testing, we can consider evaluating algorithm efficiency solely through calculations. This estimation method is known as \"asymptotic complexity analysis,\" or simply \"complexity analysis.\"

Complexity analysis reflects the relationship between the time and space resources required for algorithm execution and the size of the input data. It describes the trend of growth in the time and space required by the algorithm as the size of the input data increases. This definition might sound complex, but we can break it down into three key points to understand it better.

  • \"Time and space resources\" correspond to \"time complexity\" and \"space complexity,\" respectively.
  • \"As the size of input data increases\" means that complexity reflects the relationship between algorithm efficiency and the volume of input data.
  • \"The trend of growth in time and space\" indicates that complexity analysis focuses not on the specific values of runtime or space occupied but on the \"rate\" at which time or space grows.

Complexity analysis overcomes the disadvantages of actual testing methods, reflected in the following aspects:

  • It is independent of the testing environment and applicable to all operating platforms.
  • It can reflect algorithm efficiency under different data volumes, especially in the performance of algorithms with large data volumes.

Tip

If you're still confused about the concept of complexity, don't worry. We will introduce it in detail in subsequent chapters.

Complexity analysis provides us with a \"ruler\" to measure the time and space resources needed to execute an algorithm and compare the efficiency between different algorithms.

Complexity is a mathematical concept and may be abstract and challenging for beginners. From this perspective, complexity analysis might not be the best content to introduce first. However, when discussing the characteristics of a particular data structure or algorithm, it's hard to avoid analyzing its speed and space usage.

In summary, it's recommended that you establish a preliminary understanding of complexity analysis before diving deep into data structures and algorithms, so that you can carry out simple complexity analyses of algorithms.

"},{"location":"chapter_computational_complexity/space_complexity/","title":"2.4 \u00a0 Space Complexity","text":"

\"Space complexity\" is used to measure the growth trend of the memory space occupied by an algorithm as the amount of data increases. This concept is very similar to time complexity, except that \"running time\" is replaced with \"occupied memory space\".

"},{"location":"chapter_computational_complexity/space_complexity/#241-space-related-to-algorithms","title":"2.4.1 \u00a0 Space Related to Algorithms","text":"

The memory space used by an algorithm during its execution mainly includes the following types.

  • Input Space: Used to store the input data of the algorithm.
  • Temporary Space: Used to store variables, objects, function contexts, and other data during the algorithm's execution.
  • Output Space: Used to store the output data of the algorithm.

Generally, the scope of space complexity statistics includes both \"Temporary Space\" and \"Output Space\".

Temporary space can be further divided into three parts.

  • Temporary Data: Used to save various constants, variables, objects, etc., during the algorithm's execution.
  • Stack Frame Space: Used to save the context data of the called function. The system creates a stack frame at the top of the stack each time a function is called, and the stack frame space is released after the function returns.
  • Instruction Space: Used to store compiled program instructions, which are usually negligible in actual statistics.

When analyzing the space complexity of a program, we typically count the Temporary Data, Stack Frame Space, and Output Data, as shown in the Figure 2-15 .

Figure 2-15 \u00a0 Space Types Used in Algorithms

The relevant code is as follows:

PythonC++JavaC#GoSwiftJSTSDartRustCZig
class Node:\n    \"\"\"Classes\"\"\"\"\n    def __init__(self, x: int):\n        self.val: int = x               # node value\n        self.next: Node | None = None   # reference to the next node\n\ndef function() -> int:\n    \"\"\"\"Functions\"\"\"\"\"\n    # Perform certain operations...\n    return 0\n\ndef algorithm(n) -> int:    # input data\n    A = 0                   # temporary data (constant, usually in uppercase)\n    b = 0                   # temporary data (variable)\n    node = Node(0)          # temporary data (object)\n    c = function()          # Stack frame space (call function)\n    return A + b + c        # output data\n
/* Structures */\nstruct Node {\n    int val;\n    Node *next;\n    Node(int x) : val(x), next(nullptr) {}\n};\n\n/* Functions */\nint func() {\n    // Perform certain operations...\n    return 0;\n}\n\nint algorithm(int n) {          // input data\n    const int a = 0;            // temporary data (constant)\n    int b = 0;                  // temporary data (variable)\n    Node* node = new Node(0);   // temporary data (object)\n    int c = func();             // stack frame space (call function)\n    return a + b + c;           // output data\n}\n
/* Classes */\nclass Node {\n    int val;\n    Node next;\n    Node(int x) { val = x; }\n}\n\n/* Functions */\nint function() {\n    // Perform certain operations...\n    return 0;\n}\n\nint algorithm(int n) {          // input data\n    final int a = 0;            // temporary data (constant)\n    int b = 0;                  // temporary data (variable)\n    Node node = new Node(0);    // temporary data (object)\n    int c = function();         // stack frame space (call function)\n    return a + b + c;           // output data\n}\n
/* Classes */\nclass Node {\n    int val;\n    Node next;\n    Node(int x) { val = x; }\n}\n\n/* Functions */\nint Function() {\n    // Perform certain operations...\n    return 0;\n}\n\nint Algorithm(int n) {  // input data\n    const int a = 0;    // temporary data (constant)\n    int b = 0;          // temporary data (variable)\n    Node node = new(0); // temporary data (object)\n    int c = Function(); // stack frame space (call function)\n    return a + b + c;   // output data\n}\n
/* Structures */\ntype node struct {\n    val  int\n    next *node\n}\n\n/* Create node structure */\nfunc newNode(val int) *node {\n    return &node{val: val}\n}\n\n/* Functions */\nfunc function() int {\n    // Perform certain operations...\n    return 0\n}\n\nfunc algorithm(n int) int { // input data\n    const a = 0             // temporary data (constant)\n    b := 0                  // temporary storage of data (variable)\n    newNode(0)              // temporary data (object)\n    c := function()         // stack frame space (call function)\n    return a + b + c        // output data\n}\n
/* Classes */\nclass Node {\n    var val: Int\n    var next: Node?\n\n    init(x: Int) {\n        val = x\n    }\n}\n\n/* Functions */\nfunc function() -> Int {\n    // Perform certain operations...\n    return 0\n}\n\nfunc algorithm(n: Int) -> Int { // input data\n    let a = 0                   // temporary data (constant)\n    var b = 0                   // temporary data (variable)\n    let node = Node(x: 0)       // temporary data (object)\n    let c = function()          // stack frame space (call function)\n    return a + b + c            // output data\n}\n
/* Classes */\nclass Node {\n    val;\n    next;\n    constructor(val) {\n        this.val = val === undefined ? 0 : val; // node value\n        this.next = null;                       // reference to the next node\n    }\n}\n\n/* Functions */\nfunction constFunc() {\n    // Perform certain operations\n    return 0;\n}\n\nfunction algorithm(n) {         // input data\n    const a = 0;                // temporary data (constant)\n    let b = 0;                  // temporary data (variable)\n    const node = new Node(0);   // temporary data (object)\n    const c = constFunc();      // Stack frame space (calling function)\n    return a + b + c;           // output data\n}\n
/* Classes */\nclass Node {\n    val: number;\n    next: Node | null;\n    constructor(val?: number) {\n        this.val = val === undefined ? 0 : val; // node value\n        this.next = null;                       // reference to the next node\n    }\n}\n\n/* Functions */\nfunction constFunc(): number {\n    // Perform certain operations\n    return 0;\n}\n\nfunction algorithm(n: number): number { // input data\n    const a = 0;                        // temporary data (constant)\n    let b = 0;                          // temporary data (variable)\n    const node = new Node(0);           // temporary data (object)\n    const c = constFunc();              // Stack frame space (calling function)\n    return a + b + c;                   // output data\n}\n
/* Classes */\nclass Node {\n  int val;\n  Node next;\n  Node(this.val, [this.next]);\n}\n\n/* Functions */\nint function() {\n  // Perform certain operations...\n  return 0;\n}\n\nint algorithm(int n) {  // input data\n  const int a = 0;      // temporary data (constant)\n  int b = 0;            // temporary data (variable)\n  Node node = Node(0);  // temporary data (object)\n  int c = function();   // stack frame space (call function)\n  return a + b + c;     // output data\n}\n
use std::rc::Rc;\nuse std::cell::RefCell;\n\n/* Structures */\nstruct Node {\n    val: i32,\n    next: Option<Rc<RefCell<Node>>>,\n}\n\n/* Creating a Node structure */\nimpl Node {\n    fn new(val: i32) -> Self {\n        Self { val: val, next: None }\n    }\n}\n\n/* Functions */\nfn function() -> i32 {     \n    // Perform certain operations...\n    return 0;\n}\n\nfn algorithm(n: i32) -> i32 {   // input data\n    const a: i32 = 0;           // temporary data (constant)\n    let mut b = 0;              // temporary data (variable)\n    let node = Node::new(0);    // temporary data (object)\n    let c = function();         // stack frame space (call function)\n    return a + b + c;           // output data\n}\n
/* Functions */\nint func() {\n    // Perform certain operations...\n    return 0;\n}\n\nint algorithm(int n) {  // input data\n    const int a = 0;    // temporary data (constant)\n    int b = 0;          // temporary data (variable)\n    int c = func();     // stack frame space (call function)\n    return a + b + c;   // output data\n}\n
\n
"},{"location":"chapter_computational_complexity/space_complexity/#242-calculation-method","title":"2.4.2 \u00a0 Calculation Method","text":"

The method for calculating space complexity is roughly similar to that of time complexity, with the only change being the shift of the statistical object from \"number of operations\" to \"size of used space\".

However, unlike time complexity, we usually only focus on the worst-case space complexity. This is because memory space is a hard requirement, and we must ensure that there is enough memory space reserved under all input data.

Consider the following code, the term \"worst-case\" in worst-case space complexity has two meanings.

  1. Based on the worst input data: When \\(n < 10\\), the space complexity is \\(O(1)\\); but when \\(n > 10\\), the initialized array nums occupies \\(O(n)\\) space, thus the worst-case space complexity is \\(O(n)\\).
  2. Based on the peak memory used during the algorithm's execution: For example, before executing the last line, the program occupies \\(O(1)\\) space; when initializing the array nums, the program occupies \\(O(n)\\) space, hence the worst-case space complexity is \\(O(n)\\).
PythonC++JavaC#GoSwiftJSTSDartRustCZig
def algorithm(n: int):\n    a = 0               # O(1)\n    b = [0] * 10000     # O(1)\n    if n > 10:\n        nums = [0] * n  # O(n)\n
void algorithm(int n) {\n    int a = 0;               // O(1)\n    vector<int> b(10000);    // O(1)\n    if (n > 10)\n        vector<int> nums(n); // O(n)\n}\n
void algorithm(int n) {\n    int a = 0;                   // O(1)\n    int[] b = new int[10000];    // O(1)\n    if (n > 10)\n        int[] nums = new int[n]; // O(n)\n}\n
void Algorithm(int n) {\n    int a = 0;                   // O(1)\n    int[] b = new int[10000];    // O(1)\n    if (n > 10) {\n        int[] nums = new int[n]; // O(n)\n    }\n}\n
func algorithm(n int) {\n    a := 0                      // O(1)\n    b := make([]int, 10000)     // O(1)\n    var nums []int\n    if n > 10 {\n        nums := make([]int, n)  // O(n)\n    }\n    fmt.Println(a, b, nums)\n}\n
func algorithm(n: Int) {\n    let a = 0 // O(1)\n    let b = Array(repeating: 0, count: 10000) // O(1)\n    if n > 10 {\n        let nums = Array(repeating: 0, count: n) // O(n)\n    }\n}\n
function algorithm(n) {\n    const a = 0;                   // O(1)\n    const b = new Array(10000);    // O(1)\n    if (n > 10) {\n        const nums = new Array(n); // O(n)\n    }\n}\n
function algorithm(n: number): void {\n    const a = 0;                   // O(1)\n    const b = new Array(10000);    // O(1)\n    if (n > 10) {\n        const nums = new Array(n); // O(n)\n    }\n}\n
void algorithm(int n) {\n  int a = 0;                            // O(1)\n  List<int> b = List.filled(10000, 0);  // O(1)\n  if (n > 10) {\n    List<int> nums = List.filled(n, 0); // O(n)\n  }\n}\n
fn algorithm(n: i32) {\n    let a = 0;                              // O(1)\n    let b = [0; 10000];                     // O(1)\n    if n > 10 {\n        let nums = vec![0; n as usize];     // O(n)\n    }\n}\n
void algorithm(int n) {\n    int a = 0;               // O(1)\n    int b[10000];            // O(1)\n    if (n > 10)\n        int nums[n] = {0};   // O(n)\n}\n
\n

In recursive functions, stack frame space must be taken into count. Consider the following code:

PythonC++JavaC#GoSwiftJSTSDartRustCZig
def function() -> int:\n    # Perform certain operations\n    return 0\n\ndef loop(n: int):\n    \"\"\"Loop O(1)\"\"\"\"\"\n    for _ in range(n):\n        function()\n\ndef recur(n: int) -> int:\n    \"\"\"Recursion O(n)\"\"\"\"\"\n    if n == 1: return\n    return recur(n - 1)\n
int func() {\n    // Perform certain operations\n    return 0;\n}\n/* Cycle O(1) */\nvoid loop(int n) {\n    for (int i = 0; i < n; i++) {\n        func();\n    }\n}\n/* Recursion O(n) */\nvoid recur(int n) {\n    if (n == 1) return;\n    return recur(n - 1);\n}\n
int function() {\n    // Perform certain operations\n    return 0;\n}\n/* Cycle O(1) */\nvoid loop(int n) {\n    for (int i = 0; i < n; i++) {\n        function();\n    }\n}\n/* Recursion O(n) */\nvoid recur(int n) {\n    if (n == 1) return;\n    return recur(n - 1);\n}\n
int Function() {\n    // Perform certain operations\n    return 0;\n}\n/* Cycle O(1) */\nvoid Loop(int n) {\n    for (int i = 0; i < n; i++) {\n        Function();\n    }\n}\n/* Recursion O(n) */\nint Recur(int n) {\n    if (n == 1) return 1;\n    return Recur(n - 1);\n}\n
func function() int {\n    // Perform certain operations\n    return 0\n}\n\n/* Cycle O(1) */\nfunc loop(n int) {\n    for i := 0; i < n; i++ {\n        function()\n    }\n}\n\n/* Recursion O(n) */\nfunc recur(n int) {\n    if n == 1 {\n        return\n    }\n    recur(n - 1)\n}\n
@discardableResult\nfunc function() -> Int {\n    // Perform certain operations\n    return 0\n}\n\n/* Cycle O(1) */\nfunc loop(n: Int) {\n    for _ in 0 ..< n {\n        function()\n    }\n}\n\n/* Recursion O(n) */\nfunc recur(n: Int) {\n    if n == 1 {\n        return\n    }\n    recur(n: n - 1)\n}\n
function constFunc() {\n    // Perform certain operations\n    return 0;\n}\n/* Cycle O(1) */\nfunction loop(n) {\n    for (let i = 0; i < n; i++) {\n        constFunc();\n    }\n}\n/* Recursion O(n) */\nfunction recur(n) {\n    if (n === 1) return;\n    return recur(n - 1);\n}\n
function constFunc(): number {\n    // Perform certain operations\n    return 0;\n}\n/* Cycle O(1) */\nfunction loop(n: number): void {\n    for (let i = 0; i < n; i++) {\n        constFunc();\n    }\n}\n/* Recursion O(n) */\nfunction recur(n: number): void {\n    if (n === 1) return;\n    return recur(n - 1);\n}\n
int function() {\n  // Perform certain operations\n  return 0;\n}\n/* Cycle O(1) */\nvoid loop(int n) {\n  for (int i = 0; i < n; i++) {\n    function();\n  }\n}\n/* Recursion O(n) */\nvoid recur(int n) {\n  if (n == 1) return;\n  return recur(n - 1);\n}\n
fn function() -> i32 {\n    // Perform certain operations\n    return 0;\n}\n/* Cycle O(1) */\nfn loop(n: i32) {\n    for i in 0..n {\n        function();\n    }\n}\n/* Recursion O(n) */\nvoid recur(n: i32) {\n    if n == 1 {\n        return;\n    }\n    recur(n - 1);\n}\n
int func() {\n    // Perform certain operations\n    return 0;\n}\n/* Cycle O(1) */\nvoid loop(int n) {\n    for (int i = 0; i < n; i++) {\n        func();\n    }\n}\n/* Recursion O(n) */\nvoid recur(int n) {\n    if (n == 1) return;\n    return recur(n - 1);\n}\n
\n

The time complexity of both loop() and recur() functions is \\(O(n)\\), but their space complexities differ.

  • The loop() function calls function() \\(n\\) times in a loop, where each iteration's function() returns and releases its stack frame space, so the space complexity remains \\(O(1)\\).
  • The recursive function recur() will have \\(n\\) instances of unreturned recur() existing simultaneously during its execution, thus occupying \\(O(n)\\) stack frame space.
"},{"location":"chapter_computational_complexity/space_complexity/#243-common-types","title":"2.4.3 \u00a0 Common Types","text":"

Let the size of the input data be \\(n\\), the following chart displays common types of space complexities (arranged from low to high).

\\[ \\begin{aligned} O(1) < O(\\log n) < O(n) < O(n^2) < O(2^n) \\newline \\text{Constant Order} < \\text{Logarithmic Order} < \\text{Linear Order} < \\text{Quadratic Order} < \\text{Exponential Order} \\end{aligned} \\]

Figure 2-16 \u00a0 Common Types of Space Complexity

"},{"location":"chapter_computational_complexity/space_complexity/#1-constant-order-o1","title":"1. \u00a0 Constant Order \\(O(1)\\)","text":"

Constant order is common in constants, variables, objects that are independent of the size of input data \\(n\\).

Note that memory occupied by initializing variables or calling functions in a loop, which is released upon entering the next cycle, does not accumulate over space, thus the space complexity remains \\(O(1)\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig space_complexity.py
def function() -> int:\n    \"\"\"\u51fd\u6570\"\"\"\n    # \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0\n\ndef constant(n: int):\n    \"\"\"\u5e38\u6570\u9636\"\"\"\n    # \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    a = 0\n    nums = [0] * 10000\n    node = ListNode(0)\n    # \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for _ in range(n):\n        c = 0\n    # \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for _ in range(n):\n        function()\n
space_complexity.cpp
/* \u51fd\u6570 */\nint func() {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n/* \u5e38\u6570\u9636 */\nvoid constant(int n) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    const int a = 0;\n    int b = 0;\n    vector<int> nums(10000);\n    ListNode node(0);\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        int c = 0;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        func();\n    }\n}\n
space_complexity.java
/* \u51fd\u6570 */\nint function() {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n/* \u5e38\u6570\u9636 */\nvoid constant(int n) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    final int a = 0;\n    int b = 0;\n    int[] nums = new int[10000];\n    ListNode node = new ListNode(0);\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        int c = 0;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        function();\n    }\n}\n
space_complexity.cs
/* \u51fd\u6570 */\nint Function() {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n/* \u5e38\u6570\u9636 */\nvoid Constant(int n) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    int a = 0;\n    int b = 0;\n    int[] nums = new int[10000];\n    ListNode node = new(0);\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        int c = 0;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        Function();\n    }\n}\n
space_complexity.go
/* \u51fd\u6570 */\nfunc function() int {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c...\n    return 0\n}\n\n/* \u5e38\u6570\u9636 */\nfunc spaceConstant(n int) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    const a = 0\n    b := 0\n    nums := make([]int, 10000)\n    node := newNode(0)\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    var c int\n    for i := 0; i < n; i++ {\n        c = 0\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for i := 0; i < n; i++ {\n        function()\n    }\n    b += 0\n    c += 0\n    nums[0] = 0\n    node.val = 0\n}\n
space_complexity.swift
/* \u51fd\u6570 */\n@discardableResult\nfunc function() -> Int {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0\n}\n\n/* \u5e38\u6570\u9636 */\nfunc constant(n: Int) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    let a = 0\n    var b = 0\n    let nums = Array(repeating: 0, count: 10000)\n    let node = ListNode(x: 0)\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for _ in 0 ..< n {\n        let c = 0\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for _ in 0 ..< n {\n        function()\n    }\n}\n
space_complexity.js
/* \u51fd\u6570 */\nfunction constFunc() {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n/* \u5e38\u6570\u9636 */\nfunction constant(n) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    const a = 0;\n    const b = 0;\n    const nums = new Array(10000);\n    const node = new ListNode(0);\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for (let i = 0; i < n; i++) {\n        const c = 0;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for (let i = 0; i < n; i++) {\n        constFunc();\n    }\n}\n
space_complexity.ts
/* \u51fd\u6570 */\nfunction constFunc(): number {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n/* \u5e38\u6570\u9636 */\nfunction constant(n: number): void {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    const a = 0;\n    const b = 0;\n    const nums = new Array(10000);\n    const node = new ListNode(0);\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for (let i = 0; i < n; i++) {\n        const c = 0;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for (let i = 0; i < n; i++) {\n        constFunc();\n    }\n}\n
space_complexity.dart
/* \u51fd\u6570 */\nint function() {\n  // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n  return 0;\n}\n\n/* \u5e38\u6570\u9636 */\nvoid constant(int n) {\n  // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n  final int a = 0;\n  int b = 0;\n  List<int> nums = List.filled(10000, 0);\n  ListNode node = ListNode(0);\n  // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n  for (var i = 0; i < n; i++) {\n    int c = 0;\n  }\n  // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n  for (var i = 0; i < n; i++) {\n    function();\n  }\n}\n
space_complexity.rs
/* \u51fd\u6570 */\nfn function() ->i32 {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n/* \u5e38\u6570\u9636 */\n#[allow(unused)]\nfn constant(n: i32) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    const A: i32 = 0;\n    let b = 0;\n    let nums = vec![0; 10000];\n    let node = ListNode::new(0);\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for i in 0..n {\n        let c = 0;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for i in 0..n {\n        function();\n    }\n}\n
space_complexity.c
/* \u51fd\u6570 */\nint func() {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n/* \u5e38\u6570\u9636 */\nvoid constant(int n) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    const int a = 0;\n    int b = 0;\n    int nums[1000];\n    ListNode *node = newListNode(0);\n    free(node);\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        int c = 0;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        func();\n    }\n}\n
space_complexity.zig
// \u51fd\u6570\nfn function() i32 {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n// \u5e38\u6570\u9636\nfn constant(n: i32) void {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    const a: i32 = 0;\n    var b: i32 = 0;\n    var nums = [_]i32{0}**10000;\n    var node = inc.ListNode(i32){.val = 0};\n    var i: i32 = 0;\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    while (i < n) : (i += 1) {\n        var c: i32 = 0;\n        _ = c;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    i = 0;\n    while (i < n) : (i += 1) {\n        _ = function();\n    }\n    _ = a;\n    _ = b;\n    _ = nums;\n    _ = node;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_computational_complexity/space_complexity/#2-linear-order-on","title":"2. \u00a0 Linear Order \\(O(n)\\)","text":"

Linear order is common in arrays, linked lists, stacks, queues, etc., where the number of elements is proportional to \\(n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig space_complexity.py
def linear(n: int):\n    \"\"\"\u7ebf\u6027\u9636\"\"\"\n    # \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    nums = [0] * n\n    # \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    hmap = dict[int, str]()\n    for i in range(n):\n        hmap[i] = str(i)\n
space_complexity.cpp
/* \u7ebf\u6027\u9636 */\nvoid linear(int n) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    vector<int> nums(n);\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    vector<ListNode> nodes;\n    for (int i = 0; i < n; i++) {\n        nodes.push_back(ListNode(i));\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    unordered_map<int, string> map;\n    for (int i = 0; i < n; i++) {\n        map[i] = to_string(i);\n    }\n}\n
space_complexity.java
/* \u7ebf\u6027\u9636 */\nvoid linear(int n) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    int[] nums = new int[n];\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    List<ListNode> nodes = new ArrayList<>();\n    for (int i = 0; i < n; i++) {\n        nodes.add(new ListNode(i));\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    Map<Integer, String> map = new HashMap<>();\n    for (int i = 0; i < n; i++) {\n        map.put(i, String.valueOf(i));\n    }\n}\n
space_complexity.cs
/* \u7ebf\u6027\u9636 */\nvoid Linear(int n) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    int[] nums = new int[n];\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    List<ListNode> nodes = [];\n    for (int i = 0; i < n; i++) {\n        nodes.Add(new ListNode(i));\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    Dictionary<int, string> map = [];\n    for (int i = 0; i < n; i++) {\n        map.Add(i, i.ToString());\n    }\n}\n
space_complexity.go
/* \u7ebf\u6027\u9636 */\nfunc spaceLinear(n int) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    _ = make([]int, n)\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    var nodes []*node\n    for i := 0; i < n; i++ {\n        nodes = append(nodes, newNode(i))\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    m := make(map[int]string, n)\n    for i := 0; i < n; i++ {\n        m[i] = strconv.Itoa(i)\n    }\n}\n
space_complexity.swift
/* \u7ebf\u6027\u9636 */\nfunc linear(n: Int) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    let nums = Array(repeating: 0, count: n)\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    let nodes = (0 ..< n).map { ListNode(x: $0) }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    let map = Dictionary(uniqueKeysWithValues: (0 ..< n).map { ($0, \"\\($0)\") })\n}\n
space_complexity.js
/* \u7ebf\u6027\u9636 */\nfunction linear(n) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    const nums = new Array(n);\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    const nodes = [];\n    for (let i = 0; i < n; i++) {\n        nodes.push(new ListNode(i));\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    const map = new Map();\n    for (let i = 0; i < n; i++) {\n        map.set(i, i.toString());\n    }\n}\n
space_complexity.ts
/* \u7ebf\u6027\u9636 */\nfunction linear(n: number): void {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    const nums = new Array(n);\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    const nodes: ListNode[] = [];\n    for (let i = 0; i < n; i++) {\n        nodes.push(new ListNode(i));\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    const map = new Map();\n    for (let i = 0; i < n; i++) {\n        map.set(i, i.toString());\n    }\n}\n
space_complexity.dart
/* \u7ebf\u6027\u9636 */\nvoid linear(int n) {\n  // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n  List<int> nums = List.filled(n, 0);\n  // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n  List<ListNode> nodes = [];\n  for (var i = 0; i < n; i++) {\n    nodes.add(ListNode(i));\n  }\n  // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n  Map<int, String> map = HashMap();\n  for (var i = 0; i < n; i++) {\n    map.putIfAbsent(i, () => i.toString());\n  }\n}\n
space_complexity.rs
/* \u7ebf\u6027\u9636 */\n#[allow(unused)]\nfn linear(n: i32) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    let mut nums = vec![0; n as usize];\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    let mut nodes = Vec::new();\n    for i in 0..n {\n        nodes.push(ListNode::new(i))\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    let mut map = HashMap::new();\n    for i in 0..n {\n        map.insert(i, i.to_string());\n    }\n}\n
space_complexity.c
/* \u54c8\u5e0c\u8868 */\ntypedef struct {\n    int key;\n    int val;\n    UT_hash_handle hh; // \u57fa\u4e8e uthash.h \u5b9e\u73b0\n} HashTable;\n\n/* \u7ebf\u6027\u9636 */\nvoid linear(int n) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    int *nums = malloc(sizeof(int) * n);\n    free(nums);\n\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    ListNode **nodes = malloc(sizeof(ListNode *) * n);\n    for (int i = 0; i < n; i++) {\n        nodes[i] = newListNode(i);\n    }\n    // \u5185\u5b58\u91ca\u653e\n    for (int i = 0; i < n; i++) {\n        free(nodes[i]);\n    }\n    free(nodes);\n\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    HashTable *h = NULL;\n    for (int i = 0; i < n; i++) {\n        HashTable *tmp = malloc(sizeof(HashTable));\n        tmp->key = i;\n        tmp->val = i;\n        HASH_ADD_INT(h, key, tmp);\n    }\n\n    // \u5185\u5b58\u91ca\u653e\n    HashTable *curr, *tmp;\n    HASH_ITER(hh, h, curr, tmp) {\n        HASH_DEL(h, curr);\n        free(curr);\n    }\n}\n
space_complexity.zig
// \u7ebf\u6027\u9636\nfn linear(comptime n: i32) !void {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    var nums = [_]i32{0}**n;\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    var nodes = std.ArrayList(i32).init(std.heap.page_allocator);\n    defer nodes.deinit();\n    var i: i32 = 0;\n    while (i < n) : (i += 1) {\n        try nodes.append(i);\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    var map = std.AutoArrayHashMap(i32, []const u8).init(std.heap.page_allocator);\n    defer map.deinit();\n    var j: i32 = 0;\n    while (j < n) : (j += 1) {\n        const string = try std.fmt.allocPrint(std.heap.page_allocator, \"{d}\", .{j});\n        defer std.heap.page_allocator.free(string);\n        try map.put(i, string);\n    }\n    _ = nums;\n}\n
Visualizing Code

Full Screen >

As shown below, this function's recursive depth is \\(n\\), meaning there are \\(n\\) instances of unreturned linear_recur() function, using \\(O(n)\\) size of stack frame space:

PythonC++JavaC#GoSwiftJSTSDartRustCZig space_complexity.py
def linear_recur(n: int):\n    \"\"\"\u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\"\"\"\n    print(\"\u9012\u5f52 n =\", n)\n    if n == 1:\n        return\n    linear_recur(n - 1)\n
space_complexity.cpp
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nvoid linearRecur(int n) {\n    cout << \"\u9012\u5f52 n = \" << n << endl;\n    if (n == 1)\n        return;\n    linearRecur(n - 1);\n}\n
space_complexity.java
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nvoid linearRecur(int n) {\n    System.out.println(\"\u9012\u5f52 n = \" + n);\n    if (n == 1)\n        return;\n    linearRecur(n - 1);\n}\n
space_complexity.cs
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nvoid LinearRecur(int n) {\n    Console.WriteLine(\"\u9012\u5f52 n = \" + n);\n    if (n == 1) return;\n    LinearRecur(n - 1);\n}\n
space_complexity.go
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunc spaceLinearRecur(n int) {\n    fmt.Println(\"\u9012\u5f52 n =\", n)\n    if n == 1 {\n        return\n    }\n    spaceLinearRecur(n - 1)\n}\n
space_complexity.swift
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunc linearRecur(n: Int) {\n    print(\"\u9012\u5f52 n = \\(n)\")\n    if n == 1 {\n        return\n    }\n    linearRecur(n: n - 1)\n}\n
space_complexity.js
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction linearRecur(n) {\n    console.log(`\u9012\u5f52 n = ${n}`);\n    if (n === 1) return;\n    linearRecur(n - 1);\n}\n
space_complexity.ts
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction linearRecur(n: number): void {\n    console.log(`\u9012\u5f52 n = ${n}`);\n    if (n === 1) return;\n    linearRecur(n - 1);\n}\n
space_complexity.dart
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nvoid linearRecur(int n) {\n  print('\u9012\u5f52 n = $n');\n  if (n == 1) return;\n  linearRecur(n - 1);\n}\n
space_complexity.rs
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfn linear_recur(n: i32) {\n    println!(\"\u9012\u5f52 n = {}\", n);\n    if n == 1 {return};\n    linear_recur(n - 1);\n}\n
space_complexity.c
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nvoid linearRecur(int n) {\n    printf(\"\u9012\u5f52 n = %d\\r\\n\", n);\n    if (n == 1)\n        return;\n    linearRecur(n - 1);\n}\n
space_complexity.zig
// \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\nfn linearRecur(comptime n: i32) void {\n    std.debug.print(\"\u9012\u5f52 n = {}\\n\", .{n});\n    if (n == 1) return;\n    linearRecur(n - 1);\n}\n
Visualizing Code

Full Screen >

Figure 2-17 \u00a0 Recursive Function Generating Linear Order Space Complexity

"},{"location":"chapter_computational_complexity/space_complexity/#3-quadratic-order-on2","title":"3. \u00a0 Quadratic Order \\(O(n^2)\\)","text":"

Quadratic order is common in matrices and graphs, where the number of elements is quadratic to \\(n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig space_complexity.py
def quadratic(n: int):\n    \"\"\"\u5e73\u65b9\u9636\"\"\"\n    # \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    num_matrix = [[0] * n for _ in range(n)]\n
space_complexity.cpp
/* \u5e73\u65b9\u9636 */\nvoid quadratic(int n) {\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    vector<vector<int>> numMatrix;\n    for (int i = 0; i < n; i++) {\n        vector<int> tmp;\n        for (int j = 0; j < n; j++) {\n            tmp.push_back(0);\n        }\n        numMatrix.push_back(tmp);\n    }\n}\n
space_complexity.java
/* \u5e73\u65b9\u9636 */\nvoid quadratic(int n) {\n    // \u77e9\u9635\u5360\u7528 O(n^2) \u7a7a\u95f4\n    int[][] numMatrix = new int[n][n];\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    List<List<Integer>> numList = new ArrayList<>();\n    for (int i = 0; i < n; i++) {\n        List<Integer> tmp = new ArrayList<>();\n        for (int j = 0; j < n; j++) {\n            tmp.add(0);\n        }\n        numList.add(tmp);\n    }\n}\n
space_complexity.cs
/* \u5e73\u65b9\u9636 */\nvoid Quadratic(int n) {\n    // \u77e9\u9635\u5360\u7528 O(n^2) \u7a7a\u95f4\n    int[,] numMatrix = new int[n, n];\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    List<List<int>> numList = [];\n    for (int i = 0; i < n; i++) {\n        List<int> tmp = [];\n        for (int j = 0; j < n; j++) {\n            tmp.Add(0);\n        }\n        numList.Add(tmp);\n    }\n}\n
space_complexity.go
/* \u5e73\u65b9\u9636 */\nfunc spaceQuadratic(n int) {\n    // \u77e9\u9635\u5360\u7528 O(n^2) \u7a7a\u95f4\n    numMatrix := make([][]int, n)\n    for i := 0; i < n; i++ {\n        numMatrix[i] = make([]int, n)\n    }\n}\n
space_complexity.swift
/* \u5e73\u65b9\u9636 */\nfunc quadratic(n: Int) {\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    let numList = Array(repeating: Array(repeating: 0, count: n), count: n)\n}\n
space_complexity.js
/* \u5e73\u65b9\u9636 */\nfunction quadratic(n) {\n    // \u77e9\u9635\u5360\u7528 O(n^2) \u7a7a\u95f4\n    const numMatrix = Array(n)\n        .fill(null)\n        .map(() => Array(n).fill(null));\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    const numList = [];\n    for (let i = 0; i < n; i++) {\n        const tmp = [];\n        for (let j = 0; j < n; j++) {\n            tmp.push(0);\n        }\n        numList.push(tmp);\n    }\n}\n
space_complexity.ts
/* \u5e73\u65b9\u9636 */\nfunction quadratic(n: number): void {\n    // \u77e9\u9635\u5360\u7528 O(n^2) \u7a7a\u95f4\n    const numMatrix = Array(n)\n        .fill(null)\n        .map(() => Array(n).fill(null));\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    const numList = [];\n    for (let i = 0; i < n; i++) {\n        const tmp = [];\n        for (let j = 0; j < n; j++) {\n            tmp.push(0);\n        }\n        numList.push(tmp);\n    }\n}\n
space_complexity.dart
/* \u5e73\u65b9\u9636 */\nvoid quadratic(int n) {\n  // \u77e9\u9635\u5360\u7528 O(n^2) \u7a7a\u95f4\n  List<List<int>> numMatrix = List.generate(n, (_) => List.filled(n, 0));\n  // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n  List<List<int>> numList = [];\n  for (var i = 0; i < n; i++) {\n    List<int> tmp = [];\n    for (int j = 0; j < n; j++) {\n      tmp.add(0);\n    }\n    numList.add(tmp);\n  }\n}\n
space_complexity.rs
/* \u5e73\u65b9\u9636 */\n#[allow(unused)]\nfn quadratic(n: i32) {\n    // \u77e9\u9635\u5360\u7528 O(n^2) \u7a7a\u95f4\n    let num_matrix = vec![vec![0; n as usize]; n as usize];\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    let mut num_list = Vec::new();\n    for i in 0..n {\n        let mut tmp = Vec::new();\n        for j in 0..n {\n            tmp.push(0);\n        }\n        num_list.push(tmp);\n    }\n}\n
space_complexity.c
/* \u5e73\u65b9\u9636 */\nvoid quadratic(int n) {\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    int **numMatrix = malloc(sizeof(int *) * n);\n    for (int i = 0; i < n; i++) {\n        int *tmp = malloc(sizeof(int) * n);\n        for (int j = 0; j < n; j++) {\n            tmp[j] = 0;\n        }\n        numMatrix[i] = tmp;\n    }\n\n    // \u5185\u5b58\u91ca\u653e\n    for (int i = 0; i < n; i++) {\n        free(numMatrix[i]);\n    }\n    free(numMatrix);\n}\n
space_complexity.zig
// \u5e73\u65b9\u9636\nfn quadratic(n: i32) !void {\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    var nodes = std.ArrayList(std.ArrayList(i32)).init(std.heap.page_allocator);\n    defer nodes.deinit();\n    var i: i32 = 0;\n    while (i < n) : (i += 1) {\n        var tmp = std.ArrayList(i32).init(std.heap.page_allocator);\n        defer tmp.deinit();\n        var j: i32 = 0;\n        while (j < n) : (j += 1) {\n            try tmp.append(0);\n        }\n        try nodes.append(tmp);\n    }\n}\n
Visualizing Code

Full Screen >

As shown below, the recursive depth of this function is \\(n\\), and in each recursive call, an array is initialized with lengths \\(n\\), \\(n-1\\), \\(\\dots\\), \\(2\\), \\(1\\), averaging \\(n/2\\), thus overall occupying \\(O(n^2)\\) space:

PythonC++JavaC#GoSwiftJSTSDartRustCZig space_complexity.py
def quadratic_recur(n: int) -> int:\n    \"\"\"\u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\"\"\"\n    if n <= 0:\n        return 0\n    # \u6570\u7ec4 nums \u957f\u5ea6\u4e3a n, n-1, ..., 2, 1\n    nums = [0] * n\n    return quadratic_recur(n - 1)\n
space_complexity.cpp
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint quadraticRecur(int n) {\n    if (n <= 0)\n        return 0;\n    vector<int> nums(n);\n    cout << \"\u9012\u5f52 n = \" << n << \" \u4e2d\u7684 nums \u957f\u5ea6 = \" << nums.size() << endl;\n    return quadraticRecur(n - 1);\n}\n
space_complexity.java
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint quadraticRecur(int n) {\n    if (n <= 0)\n        return 0;\n    // \u6570\u7ec4 nums \u957f\u5ea6\u4e3a n, n-1, ..., 2, 1\n    int[] nums = new int[n];\n    System.out.println(\"\u9012\u5f52 n = \" + n + \" \u4e2d\u7684 nums \u957f\u5ea6 = \" + nums.length);\n    return quadraticRecur(n - 1);\n}\n
space_complexity.cs
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint QuadraticRecur(int n) {\n    if (n <= 0) return 0;\n    int[] nums = new int[n];\n    Console.WriteLine(\"\u9012\u5f52 n = \" + n + \" \u4e2d\u7684 nums \u957f\u5ea6 = \" + nums.Length);\n    return QuadraticRecur(n - 1);\n}\n
space_complexity.go
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunc spaceQuadraticRecur(n int) int {\n    if n <= 0 {\n        return 0\n    }\n    nums := make([]int, n)\n    fmt.Printf(\"\u9012\u5f52 n = %d \u4e2d\u7684 nums \u957f\u5ea6 = %d \\n\", n, len(nums))\n    return spaceQuadraticRecur(n - 1)\n}\n
space_complexity.swift
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\n@discardableResult\nfunc quadraticRecur(n: Int) -> Int {\n    if n <= 0 {\n        return 0\n    }\n    // \u6570\u7ec4 nums \u957f\u5ea6\u4e3a n, n-1, ..., 2, 1\n    let nums = Array(repeating: 0, count: n)\n    print(\"\u9012\u5f52 n = \\(n) \u4e2d\u7684 nums \u957f\u5ea6 = \\(nums.count)\")\n    return quadraticRecur(n: n - 1)\n}\n
space_complexity.js
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction quadraticRecur(n) {\n    if (n <= 0) return 0;\n    const nums = new Array(n);\n    console.log(`\u9012\u5f52 n = ${n} \u4e2d\u7684 nums \u957f\u5ea6 = ${nums.length}`);\n    return quadraticRecur(n - 1);\n}\n
space_complexity.ts
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction quadraticRecur(n: number): number {\n    if (n <= 0) return 0;\n    const nums = new Array(n);\n    console.log(`\u9012\u5f52 n = ${n} \u4e2d\u7684 nums \u957f\u5ea6 = ${nums.length}`);\n    return quadraticRecur(n - 1);\n}\n
space_complexity.dart
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint quadraticRecur(int n) {\n  if (n <= 0) return 0;\n  List<int> nums = List.filled(n, 0);\n  print('\u9012\u5f52 n = $n \u4e2d\u7684 nums \u957f\u5ea6 = ${nums.length}');\n  return quadraticRecur(n - 1);\n}\n
space_complexity.rs
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfn quadratic_recur(n: i32) -> i32 {\n    if n <= 0 {return 0};\n    // \u6570\u7ec4 nums \u957f\u5ea6\u4e3a n, n-1, ..., 2, 1\n    let nums = vec![0; n as usize];\n    println!(\"\u9012\u5f52 n = {} \u4e2d\u7684 nums \u957f\u5ea6 = {}\", n, nums.len());\n    return quadratic_recur(n - 1);\n}\n
space_complexity.c
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint quadraticRecur(int n) {\n    if (n <= 0)\n        return 0;\n    int *nums = malloc(sizeof(int) * n);\n    printf(\"\u9012\u5f52 n = %d \u4e2d\u7684 nums \u957f\u5ea6 = %d\\r\\n\", n, n);\n    int res = quadraticRecur(n - 1);\n    free(nums);\n    return res;\n}\n
space_complexity.zig
// \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\nfn quadraticRecur(comptime n: i32) i32 {\n    if (n <= 0) return 0;\n    var nums = [_]i32{0}**n;\n    std.debug.print(\"\u9012\u5f52 n = {} \u4e2d\u7684 nums \u957f\u5ea6 = {}\\n\", .{n, nums.len});\n    return quadraticRecur(n - 1);\n}\n
Visualizing Code

Full Screen >

Figure 2-18 \u00a0 Recursive Function Generating Quadratic Order Space Complexity

"},{"location":"chapter_computational_complexity/space_complexity/#4-exponential-order-o2n","title":"4. \u00a0 Exponential Order \\(O(2^n)\\)","text":"

Exponential order is common in binary trees. Observe the below image, a \"full binary tree\" with \\(n\\) levels has \\(2^n - 1\\) nodes, occupying \\(O(2^n)\\) space:

PythonC++JavaC#GoSwiftJSTSDartRustCZig space_complexity.py
def build_tree(n: int) -> TreeNode | None:\n    \"\"\"\u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09\"\"\"\n    if n == 0:\n        return None\n    root = TreeNode(0)\n    root.left = build_tree(n - 1)\n    root.right = build_tree(n - 1)\n    return root\n
space_complexity.cpp
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nTreeNode *buildTree(int n) {\n    if (n == 0)\n        return nullptr;\n    TreeNode *root = new TreeNode(0);\n    root->left = buildTree(n - 1);\n    root->right = buildTree(n - 1);\n    return root;\n}\n
space_complexity.java
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nTreeNode buildTree(int n) {\n    if (n == 0)\n        return null;\n    TreeNode root = new TreeNode(0);\n    root.left = buildTree(n - 1);\n    root.right = buildTree(n - 1);\n    return root;\n}\n
space_complexity.cs
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nTreeNode? BuildTree(int n) {\n    if (n == 0) return null;\n    TreeNode root = new(0) {\n        left = BuildTree(n - 1),\n        right = BuildTree(n - 1)\n    };\n    return root;\n}\n
space_complexity.go
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nfunc buildTree(n int) *TreeNode {\n    if n == 0 {\n        return nil\n    }\n    root := NewTreeNode(0)\n    root.Left = buildTree(n - 1)\n    root.Right = buildTree(n - 1)\n    return root\n}\n
space_complexity.swift
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nfunc buildTree(n: Int) -> TreeNode? {\n    if n == 0 {\n        return nil\n    }\n    let root = TreeNode(x: 0)\n    root.left = buildTree(n: n - 1)\n    root.right = buildTree(n: n - 1)\n    return root\n}\n
space_complexity.js
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nfunction buildTree(n) {\n    if (n === 0) return null;\n    const root = new TreeNode(0);\n    root.left = buildTree(n - 1);\n    root.right = buildTree(n - 1);\n    return root;\n}\n
space_complexity.ts
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nfunction buildTree(n: number): TreeNode | null {\n    if (n === 0) return null;\n    const root = new TreeNode(0);\n    root.left = buildTree(n - 1);\n    root.right = buildTree(n - 1);\n    return root;\n}\n
space_complexity.dart
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nTreeNode? buildTree(int n) {\n  if (n == 0) return null;\n  TreeNode root = TreeNode(0);\n  root.left = buildTree(n - 1);\n  root.right = buildTree(n - 1);\n  return root;\n}\n
space_complexity.rs
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nfn build_tree(n: i32) -> Option<Rc<RefCell<TreeNode>>> {\n    if n == 0 {return None};\n    let root = TreeNode::new(0);\n    root.borrow_mut().left = build_tree(n - 1);\n    root.borrow_mut().right = build_tree(n - 1);\n    return Some(root);\n}\n
space_complexity.c
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nTreeNode *buildTree(int n) {\n    if (n == 0)\n        return NULL;\n    TreeNode *root = newTreeNode(0);\n    root->left = buildTree(n - 1);\n    root->right = buildTree(n - 1);\n    return root;\n}\n
space_complexity.zig
// \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09\nfn buildTree(mem_allocator: std.mem.Allocator, n: i32) !?*inc.TreeNode(i32) {\n    if (n == 0) return null;\n    const root = try mem_allocator.create(inc.TreeNode(i32));\n    root.init(0);\n    root.left = try buildTree(mem_allocator, n - 1);\n    root.right = try buildTree(mem_allocator, n - 1);\n    return root;\n}\n
Visualizing Code

Full Screen >

Figure 2-19 \u00a0 Full Binary Tree Generating Exponential Order Space Complexity

"},{"location":"chapter_computational_complexity/space_complexity/#5-logarithmic-order-olog-n","title":"5. \u00a0 Logarithmic Order \\(O(\\log n)\\)","text":"

Logarithmic order is common in divide-and-conquer algorithms. For example, in merge sort, an array of length \\(n\\) is recursively divided in half each round, forming a recursion tree of height \\(\\log n\\), using \\(O(\\log n)\\) stack frame space.

Another example is converting a number to a string. Given a positive integer \\(n\\), its number of digits is \\(\\log_{10} n + 1\\), corresponding to the length of the string, thus the space complexity is \\(O(\\log_{10} n + 1) = O(\\log n)\\).

"},{"location":"chapter_computational_complexity/space_complexity/#244-balancing-time-and-space","title":"2.4.4 \u00a0 Balancing Time and Space","text":"

Ideally, we aim for both time complexity and space complexity to be optimal. However, in practice, optimizing both simultaneously is often difficult.

Lowering time complexity usually comes at the cost of increased space complexity, and vice versa. The approach of sacrificing memory space to improve algorithm speed is known as \"space-time tradeoff\"; the reverse is known as \"time-space tradeoff\".

The choice depends on which aspect we value more. In most cases, time is more precious than space, so \"space-time tradeoff\" is often the more common strategy. Of course, controlling space complexity is also very important when dealing with large volumes of data.

"},{"location":"chapter_computational_complexity/summary/","title":"2.5 \u00a0 Summary","text":""},{"location":"chapter_computational_complexity/summary/#1-key-review","title":"1. \u00a0 Key Review","text":"

Algorithm Efficiency Assessment

  • Time efficiency and space efficiency are the two main criteria for assessing the merits of an algorithm.
  • We can assess algorithm efficiency through actual testing, but it's challenging to eliminate the influence of the test environment, and it consumes substantial computational resources.
  • Complexity analysis can overcome the disadvantages of actual testing. Its results are applicable across all operating platforms and can reveal the efficiency of algorithms at different data scales.

Time Complexity

  • Time complexity measures the trend of an algorithm's running time with the increase in data volume, effectively assessing algorithm efficiency. However, it can fail in certain cases, such as with small input data volumes or when time complexities are the same, making it challenging to precisely compare the efficiency of algorithms.
  • Worst-case time complexity is denoted using big O notation, representing the asymptotic upper bound, reflecting the growth level of the number of operations \\(T(n)\\) as \\(n\\) approaches infinity.
  • Calculating time complexity involves two steps: first counting the number of operations, then determining the asymptotic upper bound.
  • Common time complexities, arranged from low to high, include \\(O(1)\\), \\(O(\\log n)\\), \\(O(n)\\), \\(O(n \\log n)\\), \\(O(n^2)\\), \\(O(2^n)\\), and \\(O(n!)\\), among others.
  • The time complexity of some algorithms is not fixed and depends on the distribution of input data. Time complexities are divided into worst, best, and average cases. The best case is rarely used because input data generally needs to meet strict conditions to achieve the best case.
  • Average time complexity reflects the efficiency of an algorithm under random data inputs, closely resembling the algorithm's performance in actual applications. Calculating average time complexity requires accounting for the distribution of input data and the subsequent mathematical expectation.

Space Complexity

  • Space complexity, similar to time complexity, measures the trend of memory space occupied by an algorithm with the increase in data volume.
  • The relevant memory space used during the algorithm's execution can be divided into input space, temporary space, and output space. Generally, input space is not included in space complexity calculations. Temporary space can be divided into temporary data, stack frame space, and instruction space, where stack frame space usually affects space complexity only in recursive functions.
  • We usually focus only on the worst-case space complexity, which means calculating the space complexity of the algorithm under the worst input data and at the worst moment of operation.
  • Common space complexities, arranged from low to high, include \\(O(1)\\), \\(O(\\log n)\\), \\(O(n)\\), \\(O(n^2)\\), and \\(O(2^n)\\), among others.
"},{"location":"chapter_computational_complexity/summary/#2-q-a","title":"2. \u00a0 Q & A","text":"

Q: Is the space complexity of tail recursion \\(O(1)\\)?

Theoretically, the space complexity of a tail-recursive function can be optimized to \\(O(1)\\). However, most programming languages (such as Java, Python, C++, Go, C#) do not support automatic optimization of tail recursion, so it's generally considered to have a space complexity of \\(O(n)\\).

Q: What is the difference between the terms \"function\" and \"method\"?

A \"function\" can be executed independently, with all parameters passed explicitly. A \"method\" is associated with an object and is implicitly passed to the object calling it, able to operate on the data contained within an instance of a class.

Here are some examples from common programming languages:

  • C is a procedural programming language without object-oriented concepts, so it only has functions. However, we can simulate object-oriented programming by creating structures (struct), and functions associated with these structures are equivalent to methods in other programming languages.
  • Java and C# are object-oriented programming languages where code blocks (methods) are typically part of a class. Static methods behave like functions because they are bound to the class and cannot access specific instance variables.
  • C++ and Python support both procedural programming (functions) and object-oriented programming (methods).

Q: Does the \"Common Types of Space Complexity\" figure reflect the absolute size of occupied space?

No, the figure shows space complexities, which reflect growth trends, not the absolute size of the occupied space.

If you take \\(n = 8\\), you might find that the values of each curve don't correspond to their functions. This is because each curve includes a constant term, intended to compress the value range into a visually comfortable range.

In practice, since we usually don't know the \"constant term\" complexity of each method, it's generally not possible to choose the best solution for \\(n = 8\\) based solely on complexity. However, for \\(n = 8^5\\), it's much easier to choose, as the growth trend becomes dominant.

"},{"location":"chapter_computational_complexity/time_complexity/","title":"2.3 \u00a0 Time Complexity","text":"

Time complexity is a concept used to measure how the run time of an algorithm increases with the size of the input data. Understanding time complexity is crucial for accurately assessing the efficiency of an algorithm.

  1. Determining the Running Platform: This includes hardware configuration, programming language, system environment, etc., all of which can affect the efficiency of code execution.
  2. Evaluating the Run Time for Various Computational Operations: For instance, an addition operation + might take 1 ns, a multiplication operation * might take 10 ns, a print operation print() might take 5 ns, etc.
  3. Counting All the Computational Operations in the Code: Summing the execution times of all these operations gives the total run time.

For example, consider the following code with an input size of \\(n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig
# Under an operating platform\ndef algorithm(n: int):\n    a = 2      # 1 ns\n    a = a + 1  # 1 ns\n    a = a * 2  # 10 ns\n    # Cycle n times\n    for _ in range(n):  # 1 ns\n        print(0)        # 5 ns\n
// Under a particular operating platform\nvoid algorithm(int n) {\n    int a = 2;  // 1 ns\n    a = a + 1;  // 1 ns\n    a = a * 2;  // 10 ns\n    // Loop n times\n    for (int i = 0; i < n; i++) {  // 1 ns , every round i++ is executed\n        cout << 0 << endl;         // 5 ns\n    }\n}\n
// Under a particular operating platform\nvoid algorithm(int n) {\n    int a = 2;  // 1 ns\n    a = a + 1;  // 1 ns\n    a = a * 2;  // 10 ns\n    // Loop n times\n    for (int i = 0; i < n; i++) {  // 1 ns , every round i++ is executed\n        System.out.println(0);     // 5 ns\n    }\n}\n
// Under a particular operating platform\nvoid Algorithm(int n) {\n    int a = 2;  // 1 ns\n    a = a + 1;  // 1 ns\n    a = a * 2;  // 10 ns\n    // Loop n times\n    for (int i = 0; i < n; i++) {  // 1 ns , every round i++ is executed\n        Console.WriteLine(0);      // 5 ns\n    }\n}\n
// Under a particular operating platform\nfunc algorithm(n int) {\n    a := 2     // 1 ns\n    a = a + 1  // 1 ns\n    a = a * 2  // 10 ns\n    // Loop n times\n    for i := 0; i < n; i++ {  // 1 ns\n        fmt.Println(a)        // 5 ns\n    }\n}\n
// Under a particular operating platform\nfunc algorithm(n: Int) {\n    var a = 2 // 1 ns\n    a = a + 1 // 1 ns\n    a = a * 2 // 10 ns\n    // Loop n times\n    for _ in 0 ..< n { // 1 ns\n        print(0) // 5 ns\n    }\n}\n
// Under a particular operating platform\nfunction algorithm(n) {\n    var a = 2; // 1 ns\n    a = a + 1; // 1 ns\n    a = a * 2; // 10 ns\n    // Loop n times\n    for(let i = 0; i < n; i++) { // 1 ns , every round i++ is executed\n        console.log(0); // 5 ns\n    }\n}\n
// Under a particular operating platform\nfunction algorithm(n: number): void {\n    var a: number = 2; // 1 ns\n    a = a + 1; // 1 ns\n    a = a * 2; // 10 ns\n    // Loop n times\n    for(let i = 0; i < n; i++) { // 1 ns , every round i++ is executed\n        console.log(0); // 5 ns\n    }\n}\n
// Under a particular operating platform\nvoid algorithm(int n) {\n  int a = 2; // 1 ns\n  a = a + 1; // 1 ns\n  a = a * 2; // 10 ns\n  // Loop n times\n  for (int i = 0; i < n; i++) { // 1 ns , every round i++ is executed\n    print(0); // 5 ns\n  }\n}\n
// Under a particular operating platform\nfn algorithm(n: i32) {\n    let mut a = 2;      // 1 ns\n    a = a + 1;          // 1 ns\n    a = a * 2;          // 10 ns\n    // Loop n times\n    for _ in 0..n {     // 1 ns for each round i++\n        println!(\"{}\", 0);  // 5 ns\n    }\n}\n
// Under a particular operating platform\nvoid algorithm(int n) {\n    int a = 2;  // 1 ns\n    a = a + 1;  // 1 ns\n    a = a * 2;  // 10 ns\n    // Loop n times\n    for (int i = 0; i < n; i++) {   // 1 ns , every round i++ is executed\n        printf(\"%d\", 0);            // 5 ns\n    }\n}\n
// Under a particular operating platform\nfn algorithm(n: usize) void {\n    var a: i32 = 2; // 1 ns\n    a += 1; // 1 ns\n    a *= 2; // 10 ns\n    // Loop n times\n    for (0..n) |_| { // 1 ns\n        std.debug.print(\"{}\\n\", .{0}); // 5 ns\n    }\n}\n

Using the above method, the run time of the algorithm can be calculated as \\((6n + 12)\\) ns:

\\[ 1 + 1 + 10 + (1 + 5) \\times n = 6n + 12 \\]

However, in practice, counting the run time of an algorithm is neither practical nor reasonable. First, we don't want to tie the estimated time to the running platform, as algorithms need to run on various platforms. Second, it's challenging to know the run time for each type of operation, making the estimation process difficult.

"},{"location":"chapter_computational_complexity/time_complexity/#231-assessing-time-growth-trend","title":"2.3.1 \u00a0 Assessing Time Growth Trend","text":"

Time complexity analysis does not count the algorithm's run time, but rather the growth trend of the run time as the data volume increases.

Let's understand this concept of \"time growth trend\" with an example. Assume the input data size is \\(n\\), and consider three algorithms A, B, and C:

PythonC++JavaC#GoSwiftJSTSDartRustCZig
# Time complexity of algorithm A: constant order\ndef algorithm_A(n: int):\n    print(0)\n# Time complexity of algorithm B: linear order\ndef algorithm_B(n: int):\n    for _ in range(n):\n        print(0)\n# Time complexity of algorithm C: constant order\ndef algorithm_C(n: int):\n    for _ in range(1000000):\n        print(0)\n
// Time complexity of algorithm A: constant order\nvoid algorithm_A(int n) {\n    cout << 0 << endl;\n}\n// Time complexity of algorithm B: linear order\nvoid algorithm_B(int n) {\n    for (int i = 0; i < n; i++) {\n        cout << 0 << endl;\n    }\n}\n// Time complexity of algorithm C: constant order\nvoid algorithm_C(int n) {\n    for (int i = 0; i < 1000000; i++) {\n        cout << 0 << endl;\n    }\n}\n
// Time complexity of algorithm A: constant order\nvoid algorithm_A(int n) {\n    System.out.println(0);\n}\n// Time complexity of algorithm B: linear order\nvoid algorithm_B(int n) {\n    for (int i = 0; i < n; i++) {\n        System.out.println(0);\n    }\n}\n// Time complexity of algorithm C: constant order\nvoid algorithm_C(int n) {\n    for (int i = 0; i < 1000000; i++) {\n        System.out.println(0);\n    }\n}\n
// Time complexity of algorithm A: constant order\nvoid AlgorithmA(int n) {\n    Console.WriteLine(0);\n}\n// Time complexity of algorithm B: linear order\nvoid AlgorithmB(int n) {\n    for (int i = 0; i < n; i++) {\n        Console.WriteLine(0);\n    }\n}\n// Time complexity of algorithm C: constant order\nvoid AlgorithmC(int n) {\n    for (int i = 0; i < 1000000; i++) {\n        Console.WriteLine(0);\n    }\n}\n
// Time complexity of algorithm A: constant order\nfunc algorithm_A(n int) {\n    fmt.Println(0)\n}\n// Time complexity of algorithm B: linear order\nfunc algorithm_B(n int) {\n    for i := 0; i < n; i++ {\n        fmt.Println(0)\n    }\n}\n// Time complexity of algorithm C: constant order\nfunc algorithm_C(n int) {\n    for i := 0; i < 1000000; i++ {\n        fmt.Println(0)\n    }\n}\n
// Time complexity of algorithm A: constant order\nfunc algorithmA(n: Int) {\n    print(0)\n}\n\n// Time complexity of algorithm B: linear order\nfunc algorithmB(n: Int) {\n    for _ in 0 ..< n {\n        print(0)\n    }\n}\n\n// Time complexity of algorithm C: constant order\nfunc algorithmC(n: Int) {\n    for _ in 0 ..< 1000000 {\n        print(0)\n    }\n}\n
// Time complexity of algorithm A: constant order\nfunction algorithm_A(n) {\n    console.log(0);\n}\n// Time complexity of algorithm B: linear order\nfunction algorithm_B(n) {\n    for (let i = 0; i < n; i++) {\n        console.log(0);\n    }\n}\n// Time complexity of algorithm C: constant order\nfunction algorithm_C(n) {\n    for (let i = 0; i < 1000000; i++) {\n        console.log(0);\n    }\n}\n
// Time complexity of algorithm A: constant order\nfunction algorithm_A(n: number): void {\n    console.log(0);\n}\n// Time complexity of algorithm B: linear order\nfunction algorithm_B(n: number): void {\n    for (let i = 0; i < n; i++) {\n        console.log(0);\n    }\n}\n// Time complexity of algorithm C: constant order\nfunction algorithm_C(n: number): void {\n    for (let i = 0; i < 1000000; i++) {\n        console.log(0);\n    }\n}\n
// Time complexity of algorithm A: constant order\nvoid algorithmA(int n) {\n  print(0);\n}\n// Time complexity of algorithm B: linear order\nvoid algorithmB(int n) {\n  for (int i = 0; i < n; i++) {\n    print(0);\n  }\n}\n// Time complexity of algorithm C: constant order\nvoid algorithmC(int n) {\n  for (int i = 0; i < 1000000; i++) {\n    print(0);\n  }\n}\n
// Time complexity of algorithm A: constant order\nfn algorithm_A(n: i32) {\n    println!(\"{}\", 0);\n}\n// Time complexity of algorithm B: linear order\nfn algorithm_B(n: i32) {\n    for _ in 0..n {\n        println!(\"{}\", 0);\n    }\n}\n// Time complexity of algorithm C: constant order\nfn algorithm_C(n: i32) {\n    for _ in 0..1000000 {\n        println!(\"{}\", 0);\n    }\n}\n
// Time complexity of algorithm A: constant order\nvoid algorithm_A(int n) {\n    printf(\"%d\", 0);\n}\n// Time complexity of algorithm B: linear order\nvoid algorithm_B(int n) {\n    for (int i = 0; i < n; i++) {\n        printf(\"%d\", 0);\n    }\n}\n// Time complexity of algorithm C: constant order\nvoid algorithm_C(int n) {\n    for (int i = 0; i < 1000000; i++) {\n        printf(\"%d\", 0);\n    }\n}\n
// Time complexity of algorithm A: constant order\nfn algorithm_A(n: usize) void {\n    _ = n;\n    std.debug.print(\"{}\\n\", .{0});\n}\n// Time complexity of algorithm B: linear order\nfn algorithm_B(n: i32) void {\n    for (0..n) |_| {\n        std.debug.print(\"{}\\n\", .{0});\n    }\n}\n// Time complexity of algorithm C: constant order\nfn algorithm_C(n: i32) void {\n    _ = n;\n    for (0..1000000) |_| {\n        std.debug.print(\"{}\\n\", .{0});\n    }\n}\n

The following figure shows the time complexities of these three algorithms.

  • Algorithm A has just one print operation, and its run time does not grow with \\(n\\). Its time complexity is considered \"constant order.\"
  • Algorithm B involves a print operation looping \\(n\\) times, and its run time grows linearly with \\(n\\). Its time complexity is \"linear order.\"
  • Algorithm C has a print operation looping 1,000,000 times. Although it takes a long time, it is independent of the input data size \\(n\\). Therefore, the time complexity of C is the same as A, which is \"constant order.\"

Figure 2-7 \u00a0 Time Growth Trend of Algorithms A, B, and C

Compared to directly counting the run time of an algorithm, what are the characteristics of time complexity analysis?

  • Time complexity effectively assesses algorithm efficiency. For instance, algorithm B has linearly growing run time, which is slower than algorithm A when \\(n > 1\\) and slower than C when \\(n > 1,000,000\\). In fact, as long as the input data size \\(n\\) is sufficiently large, a \"constant order\" complexity algorithm will always be better than a \"linear order\" one, demonstrating the essence of time growth trend.
  • Time complexity analysis is more straightforward. Obviously, the running platform and the types of computational operations are irrelevant to the trend of run time growth. Therefore, in time complexity analysis, we can simply treat the execution time of all computational operations as the same \"unit time,\" simplifying the \"computational operation run time count\" to a \"computational operation count.\" This significantly reduces the complexity of estimation.
  • Time complexity has its limitations. For example, although algorithms A and C have the same time complexity, their actual run times can be quite different. Similarly, even though algorithm B has a higher time complexity than C, it is clearly superior when the input data size \\(n\\) is small. In these cases, it's difficult to judge the efficiency of algorithms based solely on time complexity. Nonetheless, despite these issues, complexity analysis remains the most effective and commonly used method for evaluating algorithm efficiency.
"},{"location":"chapter_computational_complexity/time_complexity/#232-asymptotic-upper-bound","title":"2.3.2 \u00a0 Asymptotic Upper Bound","text":"

Consider a function with an input size of \\(n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig
def algorithm(n: int):\n    a = 1      # +1\n    a = a + 1  # +1\n    a = a * 2  # +1\n    # Cycle n times\n    for i in range(n):  # +1\n        print(0)        # +1\n
void algorithm(int n) {\n    int a = 1;  // +1\n    a = a + 1;  // +1\n    a = a * 2;  // +1\n    // Loop n times\n    for (int i = 0; i < n; i++) { // +1 (execute i ++ every round)\n        cout << 0 << endl;    // +1\n    }\n}\n
void algorithm(int n) {\n    int a = 1;  // +1\n    a = a + 1;  // +1\n    a = a * 2;  // +1\n    // Loop n times\n    for (int i = 0; i < n; i++) { // +1 (execute i ++ every round)\n        System.out.println(0);    // +1\n    }\n}\n
void Algorithm(int n) {\n    int a = 1;  // +1\n    a = a + 1;  // +1\n    a = a * 2;  // +1\n    // Loop n times\n    for (int i = 0; i < n; i++) {   // +1 (execute i ++ every round)\n        Console.WriteLine(0);   // +1\n    }\n}\n
func algorithm(n int) {\n    a := 1      // +1\n    a = a + 1   // +1\n    a = a * 2   // +1\n    // Loop n times\n    for i := 0; i < n; i++ {   // +1\n        fmt.Println(a)         // +1\n    }\n}\n
func algorithm(n: Int) {\n    var a = 1 // +1\n    a = a + 1 // +1\n    a = a * 2 // +1\n    // Loop n times\n    for _ in 0 ..< n { // +1\n        print(0) // +1\n    }\n}\n
function algorithm(n) {\n    var a = 1; // +1\n    a += 1; // +1\n    a *= 2; // +1\n    // Loop n times\n    for(let i = 0; i < n; i++){ // +1 (execute i ++ every round)\n        console.log(0); // +1\n    }\n}\n
function algorithm(n: number): void{\n    var a: number = 1; // +1\n    a += 1; // +1\n    a *= 2; // +1\n    // Loop n times\n    for(let i = 0; i < n; i++){ // +1 (execute i ++ every round)\n        console.log(0); // +1\n    }\n}\n
void algorithm(int n) {\n  int a = 1; // +1\n  a = a + 1; // +1\n  a = a * 2; // +1\n  // Loop n times\n  for (int i = 0; i < n; i++) { // +1 (execute i ++ every round)\n    print(0); // +1\n  }\n}\n
fn algorithm(n: i32) {\n    let mut a = 1;   // +1\n    a = a + 1;      // +1\n    a = a * 2;      // +1\n\n    // Loop n times\n    for _ in 0..n { // +1 (execute i ++ every round)\n        println!(\"{}\", 0); // +1\n    }\n}\n
void algorithm(int n) {\n    int a = 1;  // +1\n    a = a + 1;  // +1\n    a = a * 2;  // +1\n    // Loop n times\n    for (int i = 0; i < n; i++) {   // +1 (execute i ++ every round)\n        printf(\"%d\", 0);            // +1\n    }\n} \n
fn algorithm(n: usize) void {\n    var a: i32 = 1; // +1\n    a += 1; // +1\n    a *= 2; // +1\n    // Loop n times\n    for (0..n) |_| { // +1 (execute i ++ every round)\n        std.debug.print(\"{}\\n\", .{0}); // +1\n    }\n}\n

Given a function that represents the number of operations of an algorithm as a function of the input size \\(n\\), denoted as \\(T(n)\\), consider the following example:

\\[ T(n) = 3 + 2n \\]

Since \\(T(n)\\) is a linear function, its growth trend is linear, and therefore, its time complexity is of linear order, denoted as \\(O(n)\\). This mathematical notation, known as \"big-O notation,\" represents the \"asymptotic upper bound\" of the function \\(T(n)\\).

In essence, time complexity analysis is about finding the asymptotic upper bound of the \"number of operations \\(T(n)\\)\". It has a precise mathematical definition.

Asymptotic Upper Bound

If there exist positive real numbers \\(c\\) and \\(n_0\\) such that for all \\(n > n_0\\), \\(T(n) \\leq c \\cdot f(n)\\), then \\(f(n)\\) is considered an asymptotic upper bound of \\(T(n)\\), denoted as \\(T(n) = O(f(n))\\).

As illustrated below, calculating the asymptotic upper bound involves finding a function \\(f(n)\\) such that, as \\(n\\) approaches infinity, \\(T(n)\\) and \\(f(n)\\) have the same growth order, differing only by a constant factor \\(c\\).

Figure 2-8 \u00a0 Asymptotic Upper Bound of a Function

"},{"location":"chapter_computational_complexity/time_complexity/#233-calculation-method","title":"2.3.3 \u00a0 Calculation Method","text":"

While the concept of asymptotic upper bound might seem mathematically dense, you don't need to fully grasp it right away. Let's first understand the method of calculation, which can be practiced and comprehended over time.

Once \\(f(n)\\) is determined, we obtain the time complexity \\(O(f(n))\\). But how do we determine the asymptotic upper bound \\(f(n)\\)? This process generally involves two steps: counting the number of operations and determining the asymptotic upper bound.

"},{"location":"chapter_computational_complexity/time_complexity/#1-step-1-counting-the-number-of-operations","title":"1. \u00a0 Step 1: Counting the Number of Operations","text":"

This step involves going through the code line by line. However, due to the presence of the constant \\(c\\) in \\(c \\cdot f(n)\\), all coefficients and constant terms in \\(T(n)\\) can be ignored. This principle allows for simplification techniques in counting operations.

  1. Ignore constant terms in \\(T(n)\\), as they do not affect the time complexity being independent of \\(n\\).
  2. Omit all coefficients. For example, looping \\(2n\\), \\(5n + 1\\) times, etc., can be simplified to \\(n\\) times since the coefficient before \\(n\\) does not impact the time complexity.
  3. Use multiplication for nested loops. The total number of operations equals the product of the number of operations in each loop, applying the simplification techniques from points 1 and 2 for each loop level.

Given a function, we can use these techniques to count operations:

PythonC++JavaC#GoSwiftJSTSDartRustCZig
def algorithm(n: int):\n    a = 1      # +0 (trick 1)\n    a = a + n  # +0 (trick 1)\n    # +n (technique 2)\n    for i in range(5 * n + 1):\n        print(0)\n    # +n*n (technique 3)\n    for i in range(2 * n):\n        for j in range(n + 1):\n            print(0)\n
void algorithm(int n) {\n    int a = 1;  // +0 (trick 1)\n    a = a + n;  // +0 (trick 1)\n    // +n (technique 2)\n    for (int i = 0; i < 5 * n + 1; i++) {\n        cout << 0 << endl;\n    }\n    // +n*n (technique 3)\n    for (int i = 0; i < 2 * n; i++) {\n        for (int j = 0; j < n + 1; j++) {\n            cout << 0 << endl;\n        }\n    }\n}\n
void algorithm(int n) {\n    int a = 1;  // +0 (trick 1)\n    a = a + n;  // +0 (trick 1)\n    // +n (technique 2)\n    for (int i = 0; i < 5 * n + 1; i++) {\n        System.out.println(0);\n    }\n    // +n*n (technique 3)\n    for (int i = 0; i < 2 * n; i++) {\n        for (int j = 0; j < n + 1; j++) {\n            System.out.println(0);\n        }\n    }\n}\n
void Algorithm(int n) {\n    int a = 1;  // +0 (trick 1)\n    a = a + n;  // +0 (trick 1)\n    // +n (technique 2)\n    for (int i = 0; i < 5 * n + 1; i++) {\n        Console.WriteLine(0);\n    }\n    // +n*n (technique 3)\n    for (int i = 0; i < 2 * n; i++) {\n        for (int j = 0; j < n + 1; j++) {\n            Console.WriteLine(0);\n        }\n    }\n}\n
func algorithm(n int) {\n    a := 1     // +0 (trick 1)\n    a = a + n  // +0 (trick 1)\n    // +n (technique 2)\n    for i := 0; i < 5 * n + 1; i++ {\n        fmt.Println(0)\n    }\n    // +n*n (technique 3)\n    for i := 0; i < 2 * n; i++ {\n        for j := 0; j < n + 1; j++ {\n            fmt.Println(0)\n        }\n    }\n}\n
func algorithm(n: Int) {\n    var a = 1 // +0 (trick 1)\n    a = a + n // +0 (trick 1)\n    // +n (technique 2)\n    for _ in 0 ..< (5 * n + 1) {\n        print(0)\n    }\n    // +n*n (technique 3)\n    for _ in 0 ..< (2 * n) {\n        for _ in 0 ..< (n + 1) {\n            print(0)\n        }\n    }\n}\n
function algorithm(n) {\n    let a = 1;  // +0 (trick 1)\n    a = a + n;  // +0 (trick 1)\n    // +n (technique 2)\n    for (let i = 0; i < 5 * n + 1; i++) {\n        console.log(0);\n    }\n    // +n*n (technique 3)\n    for (let i = 0; i < 2 * n; i++) {\n        for (let j = 0; j < n + 1; j++) {\n            console.log(0);\n        }\n    }\n}\n
function algorithm(n: number): void {\n    let a = 1;  // +0 (trick 1)\n    a = a + n;  // +0 (trick 1)\n    // +n (technique 2)\n    for (let i = 0; i < 5 * n + 1; i++) {\n        console.log(0);\n    }\n    // +n*n (technique 3)\n    for (let i = 0; i < 2 * n; i++) {\n        for (let j = 0; j < n + 1; j++) {\n            console.log(0);\n        }\n    }\n}\n
void algorithm(int n) {\n  int a = 1; // +0 (trick 1)\n  a = a + n; // +0 (trick 1)\n  // +n (technique 2)\n  for (int i = 0; i < 5 * n + 1; i++) {\n    print(0);\n  }\n  // +n*n (technique 3)\n  for (int i = 0; i < 2 * n; i++) {\n    for (int j = 0; j < n + 1; j++) {\n      print(0);\n    }\n  }\n}\n
fn algorithm(n: i32) {\n    let mut a = 1;     // +0 (trick 1)\n    a = a + n;        // +0 (trick 1)\n\n    // +n (technique 2)\n    for i in 0..(5 * n + 1) {\n        println!(\"{}\", 0);\n    }\n\n    // +n*n (technique 3)\n    for i in 0..(2 * n) {\n        for j in 0..(n + 1) {\n            println!(\"{}\", 0);\n        }\n    }\n}\n
void algorithm(int n) {\n    int a = 1;  // +0 (trick 1)\n    a = a + n;  // +0 (trick 1)\n    // +n (technique 2)\n    for (int i = 0; i < 5 * n + 1; i++) {\n        printf(\"%d\", 0);\n    }\n    // +n*n (technique 3)\n    for (int i = 0; i < 2 * n; i++) {\n        for (int j = 0; j < n + 1; j++) {\n            printf(\"%d\", 0);\n        }\n    }\n}\n
fn algorithm(n: usize) void {\n    var a: i32 = 1;     // +0 (trick 1)\n    a = a + @as(i32, @intCast(n));        // +0 (trick 1)\n\n    // +n (technique 2)\n    for(0..(5 * n + 1)) |_| {\n        std.debug.print(\"{}\\n\", .{0});\n    }\n\n    // +n*n (technique 3)\n    for(0..(2 * n)) |_| {\n        for(0..(n + 1)) |_| {\n            std.debug.print(\"{}\\n\", .{0});\n        }\n    }\n}\n

The formula below shows the counting results before and after simplification, both leading to a time complexity of \\(O(n^2)\\):

\\[ \\begin{aligned} T(n) & = 2n(n + 1) + (5n + 1) + 2 & \\text{Complete Count (-.-|||)} \\newline & = 2n^2 + 7n + 3 \\newline T(n) & = n^2 + n & \\text{Simplified Count (o.O)} \\end{aligned} \\]"},{"location":"chapter_computational_complexity/time_complexity/#2-step-2-determining-the-asymptotic-upper-bound","title":"2. \u00a0 Step 2: Determining the Asymptotic Upper Bound","text":"

The time complexity is determined by the highest order term in \\(T(n)\\). This is because, as \\(n\\) approaches infinity, the highest order term dominates, rendering the influence of other terms negligible.

The following table illustrates examples of different operation counts and their corresponding time complexities. Some exaggerated values are used to emphasize that coefficients cannot alter the order of growth. When \\(n\\) becomes very large, these constants become insignificant.

Table: Time Complexity for Different Operation Counts

Operation Count \\(T(n)\\) Time Complexity \\(O(f(n))\\) \\(100000\\) \\(O(1)\\) \\(3n + 2\\) \\(O(n)\\) \\(2n^2 + 3n + 2\\) \\(O(n^2)\\) \\(n^3 + 10000n^2\\) \\(O(n^3)\\) \\(2^n + 10000n^{10000}\\) \\(O(2^n)\\)"},{"location":"chapter_computational_complexity/time_complexity/#234-common-types-of-time-complexity","title":"2.3.4 \u00a0 Common Types of Time Complexity","text":"

Let's consider the input data size as \\(n\\). The common types of time complexities are illustrated below, arranged from lowest to highest:

\\[ \\begin{aligned} O(1) < O(\\log n) < O(n) < O(n \\log n) < O(n^2) < O(2^n) < O(n!) \\newline \\text{Constant Order} < \\text{Logarithmic Order} < \\text{Linear Order} < \\text{Linear-Logarithmic Order} < \\text{Quadratic Order} < \\text{Exponential Order} < \\text{Factorial Order} \\end{aligned} \\]

Figure 2-9 \u00a0 Common Types of Time Complexity

"},{"location":"chapter_computational_complexity/time_complexity/#1-constant-order-o1","title":"1. \u00a0 Constant Order \\(O(1)\\)","text":"

Constant order means the number of operations is independent of the input data size \\(n\\). In the following function, although the number of operations size might be large, the time complexity remains \\(O(1)\\) as it's unrelated to \\(n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def constant(n: int) -> int:\n    \"\"\"\u5e38\u6570\u9636\"\"\"\n    count = 0\n    size = 100000\n    for _ in range(size):\n        count += 1\n    return count\n
time_complexity.cpp
/* \u5e38\u6570\u9636 */\nint constant(int n) {\n    int count = 0;\n    int size = 100000;\n    for (int i = 0; i < size; i++)\n        count++;\n    return count;\n}\n
time_complexity.java
/* \u5e38\u6570\u9636 */\nint constant(int n) {\n    int count = 0;\n    int size = 100000;\n    for (int i = 0; i < size; i++)\n        count++;\n    return count;\n}\n
time_complexity.cs
/* \u5e38\u6570\u9636 */\nint Constant(int n) {\n    int count = 0;\n    int size = 100000;\n    for (int i = 0; i < size; i++)\n        count++;\n    return count;\n}\n
time_complexity.go
/* \u5e38\u6570\u9636 */\nfunc constant(n int) int {\n    count := 0\n    size := 100000\n    for i := 0; i < size; i++ {\n        count++\n    }\n    return count\n}\n
time_complexity.swift
/* \u5e38\u6570\u9636 */\nfunc constant(n: Int) -> Int {\n    var count = 0\n    let size = 100_000\n    for _ in 0 ..< size {\n        count += 1\n    }\n    return count\n}\n
time_complexity.js
/* \u5e38\u6570\u9636 */\nfunction constant(n) {\n    let count = 0;\n    const size = 100000;\n    for (let i = 0; i < size; i++) count++;\n    return count;\n}\n
time_complexity.ts
/* \u5e38\u6570\u9636 */\nfunction constant(n: number): number {\n    let count = 0;\n    const size = 100000;\n    for (let i = 0; i < size; i++) count++;\n    return count;\n}\n
time_complexity.dart
/* \u5e38\u6570\u9636 */\nint constant(int n) {\n  int count = 0;\n  int size = 100000;\n  for (var i = 0; i < size; i++) {\n    count++;\n  }\n  return count;\n}\n
time_complexity.rs
/* \u5e38\u6570\u9636 */\nfn constant(n: i32) -> i32 {\n    _ = n;\n    let mut count = 0;\n    let size = 100_000;\n    for _ in 0..size {\n        count += 1;\n    }\n    count\n}\n
time_complexity.c
/* \u5e38\u6570\u9636 */\nint constant(int n) {\n    int count = 0;\n    int size = 100000;\n    int i = 0;\n    for (int i = 0; i < size; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.zig
// \u5e38\u6570\u9636\nfn constant(n: i32) i32 {\n    _ = n;\n    var count: i32 = 0;\n    const size: i32 = 100_000;\n    var i: i32 = 0;\n    while(i<size) : (i += 1) {\n        count += 1;\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_computational_complexity/time_complexity/#2-linear-order-on","title":"2. \u00a0 Linear Order \\(O(n)\\)","text":"

Linear order indicates the number of operations grows linearly with the input data size \\(n\\). Linear order commonly appears in single-loop structures:

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def linear(n: int) -> int:\n    \"\"\"\u7ebf\u6027\u9636\"\"\"\n    count = 0\n    for _ in range(n):\n        count += 1\n    return count\n
time_complexity.cpp
/* \u7ebf\u6027\u9636 */\nint linear(int n) {\n    int count = 0;\n    for (int i = 0; i < n; i++)\n        count++;\n    return count;\n}\n
time_complexity.java
/* \u7ebf\u6027\u9636 */\nint linear(int n) {\n    int count = 0;\n    for (int i = 0; i < n; i++)\n        count++;\n    return count;\n}\n
time_complexity.cs
/* \u7ebf\u6027\u9636 */\nint Linear(int n) {\n    int count = 0;\n    for (int i = 0; i < n; i++)\n        count++;\n    return count;\n}\n
time_complexity.go
/* \u7ebf\u6027\u9636 */\nfunc linear(n int) int {\n    count := 0\n    for i := 0; i < n; i++ {\n        count++\n    }\n    return count\n}\n
time_complexity.swift
/* \u7ebf\u6027\u9636 */\nfunc linear(n: Int) -> Int {\n    var count = 0\n    for _ in 0 ..< n {\n        count += 1\n    }\n    return count\n}\n
time_complexity.js
/* \u7ebf\u6027\u9636 */\nfunction linear(n) {\n    let count = 0;\n    for (let i = 0; i < n; i++) count++;\n    return count;\n}\n
time_complexity.ts
/* \u7ebf\u6027\u9636 */\nfunction linear(n: number): number {\n    let count = 0;\n    for (let i = 0; i < n; i++) count++;\n    return count;\n}\n
time_complexity.dart
/* \u7ebf\u6027\u9636 */\nint linear(int n) {\n  int count = 0;\n  for (var i = 0; i < n; i++) {\n    count++;\n  }\n  return count;\n}\n
time_complexity.rs
/* \u7ebf\u6027\u9636 */\nfn linear(n: i32) -> i32 {\n    let mut count = 0;\n    for _ in 0..n {\n        count += 1;\n    }\n    count\n}\n
time_complexity.c
/* \u7ebf\u6027\u9636 */\nint linear(int n) {\n    int count = 0;\n    for (int i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.zig
// \u7ebf\u6027\u9636\nfn linear(n: i32) i32 {\n    var count: i32 = 0;\n    var i: i32 = 0;\n    while (i < n) : (i += 1) {\n        count += 1;\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

Operations like array traversal and linked list traversal have a time complexity of \\(O(n)\\), where \\(n\\) is the length of the array or list:

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def array_traversal(nums: list[int]) -> int:\n    \"\"\"\u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09\"\"\"\n    count = 0\n    # \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for num in nums:\n        count += 1\n    return count\n
time_complexity.cpp
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nint arrayTraversal(vector<int> &nums) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for (int num : nums) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.java
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nint arrayTraversal(int[] nums) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for (int num : nums) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.cs
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nint ArrayTraversal(int[] nums) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    foreach (int num in nums) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.go
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nfunc arrayTraversal(nums []int) int {\n    count := 0\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for range nums {\n        count++\n    }\n    return count\n}\n
time_complexity.swift
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nfunc arrayTraversal(nums: [Int]) -> Int {\n    var count = 0\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for _ in nums {\n        count += 1\n    }\n    return count\n}\n
time_complexity.js
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nfunction arrayTraversal(nums) {\n    let count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for (let i = 0; i < nums.length; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.ts
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nfunction arrayTraversal(nums: number[]): number {\n    let count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for (let i = 0; i < nums.length; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.dart
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nint arrayTraversal(List<int> nums) {\n  int count = 0;\n  // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n  for (var _num in nums) {\n    count++;\n  }\n  return count;\n}\n
time_complexity.rs
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nfn array_traversal(nums: &[i32]) -> i32 {\n    let mut count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for _ in nums {\n        count += 1;\n    }\n    count\n}\n
time_complexity.c
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nint arrayTraversal(int *nums, int n) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for (int i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.zig
// \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09\nfn arrayTraversal(nums: []i32) i32 {\n    var count: i32 = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for (nums) |_| {\n        count += 1;\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

It's important to note that the input data size \\(n\\) should be determined based on the type of input data. For example, in the first example, \\(n\\) represents the input data size, while in the second example, the length of the array \\(n\\) is the data size.

"},{"location":"chapter_computational_complexity/time_complexity/#3-quadratic-order-on2","title":"3. \u00a0 Quadratic Order \\(O(n^2)\\)","text":"

Quadratic order means the number of operations grows quadratically with the input data size \\(n\\). Quadratic order typically appears in nested loops, where both the outer and inner loops have a time complexity of \\(O(n)\\), resulting in an overall complexity of \\(O(n^2)\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def quadratic(n: int) -> int:\n    \"\"\"\u5e73\u65b9\u9636\"\"\"\n    count = 0\n    # \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for i in range(n):\n        for j in range(n):\n            count += 1\n    return count\n
time_complexity.cpp
/* \u5e73\u65b9\u9636 */\nint quadratic(int n) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            count++;\n        }\n    }\n    return count;\n}\n
time_complexity.java
/* \u5e73\u65b9\u9636 */\nint quadratic(int n) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            count++;\n        }\n    }\n    return count;\n}\n
time_complexity.cs
/* \u5e73\u65b9\u9636 */\nint Quadratic(int n) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            count++;\n        }\n    }\n    return count;\n}\n
time_complexity.go
/* \u5e73\u65b9\u9636 */\nfunc quadratic(n int) int {\n    count := 0\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for i := 0; i < n; i++ {\n        for j := 0; j < n; j++ {\n            count++\n        }\n    }\n    return count\n}\n
time_complexity.swift
/* \u5e73\u65b9\u9636 */\nfunc quadratic(n: Int) -> Int {\n    var count = 0\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for _ in 0 ..< n {\n        for _ in 0 ..< n {\n            count += 1\n        }\n    }\n    return count\n}\n
time_complexity.js
/* \u5e73\u65b9\u9636 */\nfunction quadratic(n) {\n    let count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for (let i = 0; i < n; i++) {\n        for (let j = 0; j < n; j++) {\n            count++;\n        }\n    }\n    return count;\n}\n
time_complexity.ts
/* \u5e73\u65b9\u9636 */\nfunction quadratic(n: number): number {\n    let count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for (let i = 0; i < n; i++) {\n        for (let j = 0; j < n; j++) {\n            count++;\n        }\n    }\n    return count;\n}\n
time_complexity.dart
/* \u5e73\u65b9\u9636 */\nint quadratic(int n) {\n  int count = 0;\n  // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n  for (int i = 0; i < n; i++) {\n    for (int j = 0; j < n; j++) {\n      count++;\n    }\n  }\n  return count;\n}\n
time_complexity.rs
/* \u5e73\u65b9\u9636 */\nfn quadratic(n: i32) -> i32 {\n    let mut count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for _ in 0..n {\n        for _ in 0..n {\n            count += 1;\n        }\n    }\n    count\n}\n
time_complexity.c
/* \u5e73\u65b9\u9636 */\nint quadratic(int n) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            count++;\n        }\n    }\n    return count;\n}\n
time_complexity.zig
// \u5e73\u65b9\u9636\nfn quadratic(n: i32) i32 {\n    var count: i32 = 0;\n    var i: i32 = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    while (i < n) : (i += 1) {\n        var j: i32 = 0;\n        while (j < n) : (j += 1) {\n            count += 1;\n        }\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

The following image compares constant order, linear order, and quadratic order time complexities.

Figure 2-10 \u00a0 Constant, Linear, and Quadratic Order Time Complexities

For instance, in bubble sort, the outer loop runs \\(n - 1\\) times, and the inner loop runs \\(n-1\\), \\(n-2\\), ..., \\(2\\), \\(1\\) times, averaging \\(n / 2\\) times, resulting in a time complexity of \\(O((n - 1) n / 2) = O(n^2)\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def bubble_sort(nums: list[int]) -> int:\n    \"\"\"\u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09\"\"\"\n    count = 0  # \u8ba1\u6570\u5668\n    # \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for i in range(len(nums) - 1, 0, -1):\n        # \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n        for j in range(i):\n            if nums[j] > nums[j + 1]:\n                # \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                tmp: int = nums[j]\n                nums[j] = nums[j + 1]\n                nums[j + 1] = tmp\n                count += 3  # \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n    return count\n
time_complexity.cpp
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nint bubbleSort(vector<int> &nums) {\n    int count = 0; // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for (int i = nums.size() - 1; i > 0; i--) {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n        for (int j = 0; j < i; j++) {\n            if (nums[j] > nums[j + 1]) {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                int tmp = nums[j];\n                nums[j] = nums[j + 1];\n                nums[j + 1] = tmp;\n                count += 3; // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count;\n}\n
time_complexity.java
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nint bubbleSort(int[] nums) {\n    int count = 0; // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for (int i = nums.length - 1; i > 0; i--) {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n        for (int j = 0; j < i; j++) {\n            if (nums[j] > nums[j + 1]) {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                int tmp = nums[j];\n                nums[j] = nums[j + 1];\n                nums[j + 1] = tmp;\n                count += 3; // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count;\n}\n
time_complexity.cs
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nint BubbleSort(int[] nums) {\n    int count = 0;  // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for (int i = nums.Length - 1; i > 0; i--) {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef \n        for (int j = 0; j < i; j++) {\n            if (nums[j] > nums[j + 1]) {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                (nums[j + 1], nums[j]) = (nums[j], nums[j + 1]);\n                count += 3;  // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count;\n}\n
time_complexity.go
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nfunc bubbleSort(nums []int) int {\n    count := 0 // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for i := len(nums) - 1; i > 0; i-- {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n        for j := 0; j < i; j++ {\n            if nums[j] > nums[j+1] {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                tmp := nums[j]\n                nums[j] = nums[j+1]\n                nums[j+1] = tmp\n                count += 3 // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count\n}\n
time_complexity.swift
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nfunc bubbleSort(nums: inout [Int]) -> Int {\n    var count = 0 // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for i in stride(from: nums.count - 1, to: 0, by: -1) {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef \n        for j in 0 ..< i {\n            if nums[j] > nums[j + 1] {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                let tmp = nums[j]\n                nums[j] = nums[j + 1]\n                nums[j + 1] = tmp\n                count += 3 // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count\n}\n
time_complexity.js
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nfunction bubbleSort(nums) {\n    let count = 0; // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for (let i = nums.length - 1; i > 0; i--) {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n        for (let j = 0; j < i; j++) {\n            if (nums[j] > nums[j + 1]) {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                let tmp = nums[j];\n                nums[j] = nums[j + 1];\n                nums[j + 1] = tmp;\n                count += 3; // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count;\n}\n
time_complexity.ts
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nfunction bubbleSort(nums: number[]): number {\n    let count = 0; // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for (let i = nums.length - 1; i > 0; i--) {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n        for (let j = 0; j < i; j++) {\n            if (nums[j] > nums[j + 1]) {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                let tmp = nums[j];\n                nums[j] = nums[j + 1];\n                nums[j + 1] = tmp;\n                count += 3; // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count;\n}\n
time_complexity.dart
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nint bubbleSort(List<int> nums) {\n  int count = 0; // \u8ba1\u6570\u5668\n  // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n  for (var i = nums.length - 1; i > 0; i--) {\n    // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n    for (var j = 0; j < i; j++) {\n      if (nums[j] > nums[j + 1]) {\n        // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n        int tmp = nums[j];\n        nums[j] = nums[j + 1];\n        nums[j + 1] = tmp;\n        count += 3; // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n      }\n    }\n  }\n  return count;\n}\n
time_complexity.rs
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nfn bubble_sort(nums: &mut [i32]) -> i32 {\n    let mut count = 0; // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for i in (1..nums.len()).rev() {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef \n        for j in 0..i {\n            if nums[j] > nums[j + 1] {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                let tmp = nums[j];\n                nums[j] = nums[j + 1];\n                nums[j + 1] = tmp;\n                count += 3; // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    count\n}\n
time_complexity.c
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nint bubbleSort(int *nums, int n) {\n    int count = 0; // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for (int i = n - 1; i > 0; i--) {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n        for (int j = 0; j < i; j++) {\n            if (nums[j] > nums[j + 1]) {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                int tmp = nums[j];\n                nums[j] = nums[j + 1];\n                nums[j + 1] = tmp;\n                count += 3; // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count;\n}\n
time_complexity.zig
// \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09\nfn bubbleSort(nums: []i32) i32 {\n    var count: i32 = 0;  // \u8ba1\u6570\u5668 \n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    var i: i32 = @as(i32, @intCast(nums.len)) - 1;\n    while (i > 0) : (i -= 1) {\n        var j: usize = 0;\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef \n        while (j < i) : (j += 1) {\n            if (nums[j] > nums[j + 1]) {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                var tmp = nums[j];\n                nums[j] = nums[j + 1];\n                nums[j + 1] = tmp;\n                count += 3;  // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_computational_complexity/time_complexity/#4-exponential-order-o2n","title":"4. \u00a0 Exponential Order \\(O(2^n)\\)","text":"

Biological \"cell division\" is a classic example of exponential order growth: starting with one cell, it becomes two after one division, four after two divisions, and so on, resulting in \\(2^n\\) cells after \\(n\\) divisions.

The following image and code simulate the cell division process, with a time complexity of \\(O(2^n)\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def exponential(n: int) -> int:\n    \"\"\"\u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09\"\"\"\n    count = 0\n    base = 1\n    # \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for _ in range(n):\n        for _ in range(base):\n            count += 1\n        base *= 2\n    # count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count\n
time_complexity.cpp
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint exponential(int n) {\n    int count = 0, base = 1;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < base; j++) {\n            count++;\n        }\n        base *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count;\n}\n
time_complexity.java
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint exponential(int n) {\n    int count = 0, base = 1;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < base; j++) {\n            count++;\n        }\n        base *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count;\n}\n
time_complexity.cs
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint Exponential(int n) {\n    int count = 0, bas = 1;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < bas; j++) {\n            count++;\n        }\n        bas *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count;\n}\n
time_complexity.go
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09*/\nfunc exponential(n int) int {\n    count, base := 0, 1\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for i := 0; i < n; i++ {\n        for j := 0; j < base; j++ {\n            count++\n        }\n        base *= 2\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count\n}\n
time_complexity.swift
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfunc exponential(n: Int) -> Int {\n    var count = 0\n    var base = 1\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for _ in 0 ..< n {\n        for _ in 0 ..< base {\n            count += 1\n        }\n        base *= 2\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count\n}\n
time_complexity.js
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfunction exponential(n) {\n    let count = 0,\n        base = 1;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for (let i = 0; i < n; i++) {\n        for (let j = 0; j < base; j++) {\n            count++;\n        }\n        base *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count;\n}\n
time_complexity.ts
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfunction exponential(n: number): number {\n    let count = 0,\n        base = 1;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for (let i = 0; i < n; i++) {\n        for (let j = 0; j < base; j++) {\n            count++;\n        }\n        base *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count;\n}\n
time_complexity.dart
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint exponential(int n) {\n  int count = 0, base = 1;\n  // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n  for (var i = 0; i < n; i++) {\n    for (var j = 0; j < base; j++) {\n      count++;\n    }\n    base *= 2;\n  }\n  // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n  return count;\n}\n
time_complexity.rs
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfn exponential(n: i32) -> i32 {\n    let mut count = 0;\n    let mut base = 1;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for _ in 0..n {\n        for _ in 0..base {\n            count += 1\n        }\n        base *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    count\n}\n
time_complexity.c
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint exponential(int n) {\n    int count = 0;\n    int bas = 1;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < bas; j++) {\n            count++;\n        }\n        bas *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count;\n}\n
time_complexity.zig
// \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09\nfn exponential(n: i32) i32 {\n    var count: i32 = 0;\n    var bas: i32 = 1;\n    var i: i32 = 0;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    while (i < n) : (i += 1) {\n        var j: i32 = 0;\n        while (j < bas) : (j += 1) {\n            count += 1;\n        }\n        bas *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count;\n}\n
Visualizing Code

Full Screen >

Figure 2-11 \u00a0 Exponential Order Time Complexity

In practice, exponential order often appears in recursive functions. For example, in the code below, it recursively splits into two halves, stopping after \\(n\\) divisions:

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def exp_recur(n: int) -> int:\n    \"\"\"\u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\"\"\"\n    if n == 1:\n        return 1\n    return exp_recur(n - 1) + exp_recur(n - 1) + 1\n
time_complexity.cpp
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint expRecur(int n) {\n    if (n == 1)\n        return 1;\n    return expRecur(n - 1) + expRecur(n - 1) + 1;\n}\n
time_complexity.java
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint expRecur(int n) {\n    if (n == 1)\n        return 1;\n    return expRecur(n - 1) + expRecur(n - 1) + 1;\n}\n
time_complexity.cs
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint ExpRecur(int n) {\n    if (n == 1) return 1;\n    return ExpRecur(n - 1) + ExpRecur(n - 1) + 1;\n}\n
time_complexity.go
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09*/\nfunc expRecur(n int) int {\n    if n == 1 {\n        return 1\n    }\n    return expRecur(n-1) + expRecur(n-1) + 1\n}\n
time_complexity.swift
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunc expRecur(n: Int) -> Int {\n    if n == 1 {\n        return 1\n    }\n    return expRecur(n: n - 1) + expRecur(n: n - 1) + 1\n}\n
time_complexity.js
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction expRecur(n) {\n    if (n === 1) return 1;\n    return expRecur(n - 1) + expRecur(n - 1) + 1;\n}\n
time_complexity.ts
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction expRecur(n: number): number {\n    if (n === 1) return 1;\n    return expRecur(n - 1) + expRecur(n - 1) + 1;\n}\n
time_complexity.dart
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint expRecur(int n) {\n  if (n == 1) return 1;\n  return expRecur(n - 1) + expRecur(n - 1) + 1;\n}\n
time_complexity.rs
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfn exp_recur(n: i32) -> i32 {\n    if n == 1 {\n        return 1;\n    }\n    exp_recur(n - 1) + exp_recur(n - 1) + 1\n}\n
time_complexity.c
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint expRecur(int n) {\n    if (n == 1)\n        return 1;\n    return expRecur(n - 1) + expRecur(n - 1) + 1;\n}\n
time_complexity.zig
// \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\nfn expRecur(n: i32) i32 {\n    if (n == 1) return 1;\n    return expRecur(n - 1) + expRecur(n - 1) + 1;\n}\n
Visualizing Code

Full Screen >

Exponential order growth is extremely rapid and is commonly seen in exhaustive search methods (brute force, backtracking, etc.). For large-scale problems, exponential order is unacceptable, often requiring dynamic programming or greedy algorithms as solutions.

"},{"location":"chapter_computational_complexity/time_complexity/#5-logarithmic-order-olog-n","title":"5. \u00a0 Logarithmic Order \\(O(\\log n)\\)","text":"

In contrast to exponential order, logarithmic order reflects situations where \"the size is halved each round.\" Given an input data size \\(n\\), since the size is halved each round, the number of iterations is \\(\\log_2 n\\), the inverse function of \\(2^n\\).

The following image and code simulate the \"halving each round\" process, with a time complexity of \\(O(\\log_2 n)\\), commonly abbreviated as \\(O(\\log n)\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def logarithmic(n: float) -> int:\n    \"\"\"\u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09\"\"\"\n    count = 0\n    while n > 1:\n        n = n / 2\n        count += 1\n    return count\n
time_complexity.cpp
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint logarithmic(float n) {\n    int count = 0;\n    while (n > 1) {\n        n = n / 2;\n        count++;\n    }\n    return count;\n}\n
time_complexity.java
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint logarithmic(float n) {\n    int count = 0;\n    while (n > 1) {\n        n = n / 2;\n        count++;\n    }\n    return count;\n}\n
time_complexity.cs
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint Logarithmic(float n) {\n    int count = 0;\n    while (n > 1) {\n        n /= 2;\n        count++;\n    }\n    return count;\n}\n
time_complexity.go
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09*/\nfunc logarithmic(n float64) int {\n    count := 0\n    for n > 1 {\n        n = n / 2\n        count++\n    }\n    return count\n}\n
time_complexity.swift
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfunc logarithmic(n: Double) -> Int {\n    var count = 0\n    var n = n\n    while n > 1 {\n        n = n / 2\n        count += 1\n    }\n    return count\n}\n
time_complexity.js
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfunction logarithmic(n) {\n    let count = 0;\n    while (n > 1) {\n        n = n / 2;\n        count++;\n    }\n    return count;\n}\n
time_complexity.ts
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfunction logarithmic(n: number): number {\n    let count = 0;\n    while (n > 1) {\n        n = n / 2;\n        count++;\n    }\n    return count;\n}\n
time_complexity.dart
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint logarithmic(num n) {\n  int count = 0;\n  while (n > 1) {\n    n = n / 2;\n    count++;\n  }\n  return count;\n}\n
time_complexity.rs
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfn logarithmic(mut n: f32) -> i32 {\n    let mut count = 0;\n    while n > 1.0 {\n        n = n / 2.0;\n        count += 1;\n    }\n    count\n}\n
time_complexity.c
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint logarithmic(float n) {\n    int count = 0;\n    while (n > 1) {\n        n = n / 2;\n        count++;\n    }\n    return count;\n}\n
time_complexity.zig
// \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09\nfn logarithmic(n: f32) i32 {\n    var count: i32 = 0;\n    var n_var = n;\n    while (n_var > 1)\n    {\n        n_var = n_var / 2;\n        count +=1;\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

Figure 2-12 \u00a0 Logarithmic Order Time Complexity

Like exponential order, logarithmic order also frequently appears in recursive functions. The code below forms a recursive tree of height \\(\\log_2 n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def log_recur(n: float) -> int:\n    \"\"\"\u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\"\"\"\n    if n <= 1:\n        return 0\n    return log_recur(n / 2) + 1\n
time_complexity.cpp
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint logRecur(float n) {\n    if (n <= 1)\n        return 0;\n    return logRecur(n / 2) + 1;\n}\n
time_complexity.java
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint logRecur(float n) {\n    if (n <= 1)\n        return 0;\n    return logRecur(n / 2) + 1;\n}\n
time_complexity.cs
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint LogRecur(float n) {\n    if (n <= 1) return 0;\n    return LogRecur(n / 2) + 1;\n}\n
time_complexity.go
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09*/\nfunc logRecur(n float64) int {\n    if n <= 1 {\n        return 0\n    }\n    return logRecur(n/2) + 1\n}\n
time_complexity.swift
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunc logRecur(n: Double) -> Int {\n    if n <= 1 {\n        return 0\n    }\n    return logRecur(n: n / 2) + 1\n}\n
time_complexity.js
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction logRecur(n) {\n    if (n <= 1) return 0;\n    return logRecur(n / 2) + 1;\n}\n
time_complexity.ts
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction logRecur(n: number): number {\n    if (n <= 1) return 0;\n    return logRecur(n / 2) + 1;\n}\n
time_complexity.dart
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint logRecur(num n) {\n  if (n <= 1) return 0;\n  return logRecur(n / 2) + 1;\n}\n
time_complexity.rs
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfn log_recur(n: f32) -> i32 {\n    if n <= 1.0 {\n        return 0;\n    }\n    log_recur(n / 2.0) + 1\n}\n
time_complexity.c
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint logRecur(float n) {\n    if (n <= 1)\n        return 0;\n    return logRecur(n / 2) + 1;\n}\n
time_complexity.zig
// \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\nfn logRecur(n: f32) i32 {\n    if (n <= 1) return 0;\n    return logRecur(n / 2) + 1;\n}\n
Visualizing Code

Full Screen >

Logarithmic order is typical in algorithms based on the divide-and-conquer strategy, embodying the \"split into many\" and \"simplify complex problems\" approach. It's slow-growing and is the most ideal time complexity after constant order.

What is the base of \\(O(\\log n)\\)?

Technically, \"splitting into \\(m\\)\" corresponds to a time complexity of \\(O(\\log_m n)\\). Using the logarithm base change formula, we can equate different logarithmic complexities:

\\[ O(\\log_m n) = O(\\log_k n / \\log_k m) = O(\\log_k n) \\]

This means the base \\(m\\) can be changed without affecting the complexity. Therefore, we often omit the base \\(m\\) and simply denote logarithmic order as \\(O(\\log n)\\).

"},{"location":"chapter_computational_complexity/time_complexity/#6-linear-logarithmic-order-on-log-n","title":"6. \u00a0 Linear-Logarithmic Order \\(O(n \\log n)\\)","text":"

Linear-logarithmic order often appears in nested loops, with the complexities of the two loops being \\(O(\\log n)\\) and \\(O(n)\\) respectively. The related code is as follows:

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def linear_log_recur(n: float) -> int:\n    \"\"\"\u7ebf\u6027\u5bf9\u6570\u9636\"\"\"\n    if n <= 1:\n        return 1\n    count: int = linear_log_recur(n // 2) + linear_log_recur(n // 2)\n    for _ in range(n):\n        count += 1\n    return count\n
time_complexity.cpp
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nint linearLogRecur(float n) {\n    if (n <= 1)\n        return 1;\n    int count = linearLogRecur(n / 2) + linearLogRecur(n / 2);\n    for (int i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.java
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nint linearLogRecur(float n) {\n    if (n <= 1)\n        return 1;\n    int count = linearLogRecur(n / 2) + linearLogRecur(n / 2);\n    for (int i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.cs
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nint LinearLogRecur(float n) {\n    if (n <= 1) return 1;\n    int count = LinearLogRecur(n / 2) + LinearLogRecur(n / 2);\n    for (int i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.go
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nfunc linearLogRecur(n float64) int {\n    if n <= 1 {\n        return 1\n    }\n    count := linearLogRecur(n/2) + linearLogRecur(n/2)\n    for i := 0.0; i < n; i++ {\n        count++\n    }\n    return count\n}\n
time_complexity.swift
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nfunc linearLogRecur(n: Double) -> Int {\n    if n <= 1 {\n        return 1\n    }\n    var count = linearLogRecur(n: n / 2) + linearLogRecur(n: n / 2)\n    for _ in stride(from: 0, to: n, by: 1) {\n        count += 1\n    }\n    return count\n}\n
time_complexity.js
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nfunction linearLogRecur(n) {\n    if (n <= 1) return 1;\n    let count = linearLogRecur(n / 2) + linearLogRecur(n / 2);\n    for (let i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.ts
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nfunction linearLogRecur(n: number): number {\n    if (n <= 1) return 1;\n    let count = linearLogRecur(n / 2) + linearLogRecur(n / 2);\n    for (let i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.dart
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nint linearLogRecur(num n) {\n  if (n <= 1) return 1;\n  int count = linearLogRecur(n / 2) + linearLogRecur(n / 2);\n  for (var i = 0; i < n; i++) {\n    count++;\n  }\n  return count;\n}\n
time_complexity.rs
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nfn linear_log_recur(n: f32) -> i32 {\n    if n <= 1.0 {\n        return 1;\n    }\n    let mut count = linear_log_recur(n / 2.0) + linear_log_recur(n / 2.0);\n    for _ in 0 ..n as i32 {\n        count += 1;\n    }\n    return count\n}\n
time_complexity.c
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nint linearLogRecur(float n) {\n    if (n <= 1)\n        return 1;\n    int count = linearLogRecur(n / 2) + linearLogRecur(n / 2);\n    for (int i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.zig
// \u7ebf\u6027\u5bf9\u6570\u9636\nfn linearLogRecur(n: f32) i32 {\n    if (n <= 1) return 1;\n    var count: i32 = linearLogRecur(n / 2) + linearLogRecur(n / 2);\n    var i: f32 = 0;\n    while (i < n) : (i += 1) {\n        count += 1;\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

The image below demonstrates how linear-logarithmic order is generated. Each level of a binary tree has \\(n\\) operations, and the tree has \\(\\log_2 n + 1\\) levels, resulting in a time complexity of \\(O(n \\log n)\\).

Figure 2-13 \u00a0 Linear-Logarithmic Order Time Complexity

Mainstream sorting algorithms typically have a time complexity of \\(O(n \\log n)\\), such as quicksort, mergesort, and heapsort.

"},{"location":"chapter_computational_complexity/time_complexity/#7-factorial-order-on","title":"7. \u00a0 Factorial Order \\(O(n!)\\)","text":"

Factorial order corresponds to the mathematical problem of \"full permutation.\" Given \\(n\\) distinct elements, the total number of possible permutations is:

\\[ n! = n \\times (n - 1) \\times (n - 2) \\times \\dots \\times 2 \\times 1 \\]

Factorials are typically implemented using recursion. As shown in the image and code below, the first level splits into \\(n\\) branches, the second level into \\(n - 1\\) branches, and so on, stopping after the \\(n\\)th level:

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def factorial_recur(n: int) -> int:\n    \"\"\"\u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\"\"\"\n    if n == 0:\n        return 1\n    count = 0\n    # \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for _ in range(n):\n        count += factorial_recur(n - 1)\n    return count\n
time_complexity.cpp
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint factorialRecur(int n) {\n    if (n == 0)\n        return 1;\n    int count = 0;\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for (int i = 0; i < n; i++) {\n        count += factorialRecur(n - 1);\n    }\n    return count;\n}\n
time_complexity.java
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint factorialRecur(int n) {\n    if (n == 0)\n        return 1;\n    int count = 0;\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for (int i = 0; i < n; i++) {\n        count += factorialRecur(n - 1);\n    }\n    return count;\n}\n
time_complexity.cs
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint FactorialRecur(int n) {\n    if (n == 0) return 1;\n    int count = 0;\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for (int i = 0; i < n; i++) {\n        count += FactorialRecur(n - 1);\n    }\n    return count;\n}\n
time_complexity.go
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunc factorialRecur(n int) int {\n    if n == 0 {\n        return 1\n    }\n    count := 0\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for i := 0; i < n; i++ {\n        count += factorialRecur(n - 1)\n    }\n    return count\n}\n
time_complexity.swift
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunc factorialRecur(n: Int) -> Int {\n    if n == 0 {\n        return 1\n    }\n    var count = 0\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for _ in 0 ..< n {\n        count += factorialRecur(n: n - 1)\n    }\n    return count\n}\n
time_complexity.js
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction factorialRecur(n) {\n    if (n === 0) return 1;\n    let count = 0;\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for (let i = 0; i < n; i++) {\n        count += factorialRecur(n - 1);\n    }\n    return count;\n}\n
time_complexity.ts
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction factorialRecur(n: number): number {\n    if (n === 0) return 1;\n    let count = 0;\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for (let i = 0; i < n; i++) {\n        count += factorialRecur(n - 1);\n    }\n    return count;\n}\n
time_complexity.dart
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint factorialRecur(int n) {\n  if (n == 0) return 1;\n  int count = 0;\n  // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n  for (var i = 0; i < n; i++) {\n    count += factorialRecur(n - 1);\n  }\n  return count;\n}\n
time_complexity.rs
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfn factorial_recur(n: i32) -> i32 {\n    if n == 0 {\n        return 1;\n    }\n    let mut count = 0;\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for _ in 0..n {\n        count += factorial_recur(n - 1);\n    }\n    count\n}\n
time_complexity.c
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint factorialRecur(int n) {\n    if (n == 0)\n        return 1;\n    int count = 0;\n    for (int i = 0; i < n; i++) {\n        count += factorialRecur(n - 1);\n    }\n    return count;\n}\n
time_complexity.zig
// \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\nfn factorialRecur(n: i32) i32 {\n    if (n == 0) return 1;\n    var count: i32 = 0;\n    var i: i32 = 0;\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    while (i < n) : (i += 1) {\n        count += factorialRecur(n - 1);\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

Figure 2-14 \u00a0 Factorial Order Time Complexity

Note that factorial order grows even faster than exponential order; it's unacceptable for larger \\(n\\) values.

"},{"location":"chapter_computational_complexity/time_complexity/#235-worst-best-and-average-time-complexities","title":"2.3.5 \u00a0 Worst, Best, and Average Time Complexities","text":"

The time efficiency of an algorithm is often not fixed but depends on the distribution of the input data. Assume we have an array nums of length \\(n\\), consisting of numbers from \\(1\\) to \\(n\\), each appearing only once, but in a randomly shuffled order. The task is to return the index of the element \\(1\\). We can draw the following conclusions:

  • When nums = [?, ?, ..., 1], that is, when the last element is \\(1\\), it requires a complete traversal of the array, achieving the worst-case time complexity of \\(O(n)\\).
  • When nums = [1, ?, ?, ...], that is, when the first element is \\(1\\), no matter the length of the array, no further traversal is needed, achieving the best-case time complexity of \\(\\Omega(1)\\).

The \"worst-case time complexity\" corresponds to the asymptotic upper bound, denoted by the big \\(O\\) notation. Correspondingly, the \"best-case time complexity\" corresponds to the asymptotic lower bound, denoted by \\(\\Omega\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig worst_best_time_complexity.py
def random_numbers(n: int) -> list[int]:\n    \"\"\"\u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a: 1, 2, ..., n \uff0c\u987a\u5e8f\u88ab\u6253\u4e71\"\"\"\n    # \u751f\u6210\u6570\u7ec4 nums =: 1, 2, 3, ..., n\n    nums = [i for i in range(1, n + 1)]\n    # \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    random.shuffle(nums)\n    return nums\n\ndef find_one(nums: list[int]) -> int:\n    \"\"\"\u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15\"\"\"\n    for i in range(len(nums)):\n        # \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        # \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if nums[i] == 1:\n            return i\n    return -1\n
worst_best_time_complexity.cpp
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nvector<int> randomNumbers(int n) {\n    vector<int> nums(n);\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for (int i = 0; i < n; i++) {\n        nums[i] = i + 1;\n    }\n    // \u4f7f\u7528\u7cfb\u7edf\u65f6\u95f4\u751f\u6210\u968f\u673a\u79cd\u5b50\n    unsigned seed = chrono::system_clock::now().time_since_epoch().count();\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    shuffle(nums.begin(), nums.end(), default_random_engine(seed));\n    return nums;\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nint findOne(vector<int> &nums) {\n    for (int i = 0; i < nums.size(); i++) {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if (nums[i] == 1)\n            return i;\n    }\n    return -1;\n}\n
worst_best_time_complexity.java
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nint[] randomNumbers(int n) {\n    Integer[] nums = new Integer[n];\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for (int i = 0; i < n; i++) {\n        nums[i] = i + 1;\n    }\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    Collections.shuffle(Arrays.asList(nums));\n    // Integer[] -> int[]\n    int[] res = new int[n];\n    for (int i = 0; i < n; i++) {\n        res[i] = nums[i];\n    }\n    return res;\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nint findOne(int[] nums) {\n    for (int i = 0; i < nums.length; i++) {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if (nums[i] == 1)\n            return i;\n    }\n    return -1;\n}\n
worst_best_time_complexity.cs
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nint[] RandomNumbers(int n) {\n    int[] nums = new int[n];\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for (int i = 0; i < n; i++) {\n        nums[i] = i + 1;\n    }\n\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    for (int i = 0; i < nums.Length; i++) {\n        int index = new Random().Next(i, nums.Length);\n        (nums[i], nums[index]) = (nums[index], nums[i]);\n    }\n    return nums;\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nint FindOne(int[] nums) {\n    for (int i = 0; i < nums.Length; i++) {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if (nums[i] == 1)\n            return i;\n    }\n    return -1;\n}\n
worst_best_time_complexity.go
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nfunc randomNumbers(n int) []int {\n    nums := make([]int, n)\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for i := 0; i < n; i++ {\n        nums[i] = i + 1\n    }\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    rand.Shuffle(len(nums), func(i, j int) {\n        nums[i], nums[j] = nums[j], nums[i]\n    })\n    return nums\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nfunc findOne(nums []int) int {\n    for i := 0; i < len(nums); i++ {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if nums[i] == 1 {\n            return i\n        }\n    }\n    return -1\n}\n
worst_best_time_complexity.swift
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nfunc randomNumbers(n: Int) -> [Int] {\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    var nums = Array(1 ... n)\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    nums.shuffle()\n    return nums\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nfunc findOne(nums: [Int]) -> Int {\n    for i in nums.indices {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if nums[i] == 1 {\n            return i\n        }\n    }\n    return -1\n}\n
worst_best_time_complexity.js
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nfunction randomNumbers(n) {\n    const nums = Array(n);\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for (let i = 0; i < n; i++) {\n        nums[i] = i + 1;\n    }\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    for (let i = 0; i < n; i++) {\n        const r = Math.floor(Math.random() * (i + 1));\n        const temp = nums[i];\n        nums[i] = nums[r];\n        nums[r] = temp;\n    }\n    return nums;\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nfunction findOne(nums) {\n    for (let i = 0; i < nums.length; i++) {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if (nums[i] === 1) {\n            return i;\n        }\n    }\n    return -1;\n}\n
worst_best_time_complexity.ts
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nfunction randomNumbers(n: number): number[] {\n    const nums = Array(n);\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for (let i = 0; i < n; i++) {\n        nums[i] = i + 1;\n    }\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    for (let i = 0; i < n; i++) {\n        const r = Math.floor(Math.random() * (i + 1));\n        const temp = nums[i];\n        nums[i] = nums[r];\n        nums[r] = temp;\n    }\n    return nums;\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nfunction findOne(nums: number[]): number {\n    for (let i = 0; i < nums.length; i++) {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if (nums[i] === 1) {\n            return i;\n        }\n    }\n    return -1;\n}\n
worst_best_time_complexity.dart
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nList<int> randomNumbers(int n) {\n  final nums = List.filled(n, 0);\n  // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n  for (var i = 0; i < n; i++) {\n    nums[i] = i + 1;\n  }\n  // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n  nums.shuffle();\n\n  return nums;\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nint findOne(List<int> nums) {\n  for (var i = 0; i < nums.length; i++) {\n    // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n    // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n    if (nums[i] == 1) return i;\n  }\n\n  return -1;\n}\n
worst_best_time_complexity.rs
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nfn random_numbers(n: i32) -> Vec<i32> {\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    let mut nums = (1..=n).collect::<Vec<i32>>();\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    nums.shuffle(&mut thread_rng());\n    nums\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nfn find_one(nums: &[i32]) -> Option<usize> {\n    for i in 0..nums.len() {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if nums[i] == 1 {\n            return Some(i);\n        }\n    }\n    None\n}\n
worst_best_time_complexity.c
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nint *randomNumbers(int n) {\n    // \u5206\u914d\u5806\u533a\u5185\u5b58\uff08\u521b\u5efa\u4e00\u7ef4\u53ef\u53d8\u957f\u6570\u7ec4\uff1a\u6570\u7ec4\u4e2d\u5143\u7d20\u6570\u91cf\u4e3a n \uff0c\u5143\u7d20\u7c7b\u578b\u4e3a int \uff09\n    int *nums = (int *)malloc(n * sizeof(int));\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for (int i = 0; i < n; i++) {\n        nums[i] = i + 1;\n    }\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    for (int i = n - 1; i > 0; i--) {\n        int j = rand() % (i + 1);\n        int temp = nums[i];\n        nums[i] = nums[j];\n        nums[j] = temp;\n    }\n    return nums;\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nint findOne(int *nums, int n) {\n    for (int i = 0; i < n; i++) {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if (nums[i] == 1)\n            return i;\n    }\n    return -1;\n}\n
worst_best_time_complexity.zig
// \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71\nfn randomNumbers(comptime n: usize) [n]i32 {\n    var nums: [n]i32 = undefined;\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for (&nums, 0..) |*num, i| {\n        num.* = @as(i32, @intCast(i)) + 1;\n    }\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    const rand = std.crypto.random;\n    rand.shuffle(i32, &nums);\n    return nums;\n}\n\n// \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15\nfn findOne(nums: []i32) i32 {\n    for (nums, 0..) |num, i| {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if (num == 1) return @intCast(i);\n    }\n    return -1;\n}\n
Visualizing Code

Full Screen >

It's important to note that the best-case time complexity is rarely used in practice, as it is usually only achievable under very low probabilities and might be misleading. The worst-case time complexity is more practical as it provides a safety value for efficiency, allowing us to confidently use the algorithm.

From the above example, it's clear that both the worst-case and best-case time complexities only occur under \"special data distributions,\" which may have a small probability of occurrence and may not accurately reflect the algorithm's run efficiency. In contrast, the average time complexity can reflect the algorithm's efficiency under random input data, denoted by the \\(\\Theta\\) notation.

For some algorithms, we can simply estimate the average case under a random data distribution. For example, in the aforementioned example, since the input array is shuffled, the probability of element \\(1\\) appearing at any index is equal. Therefore, the average number of loops for the algorithm is half the length of the array \\(n / 2\\), giving an average time complexity of \\(\\Theta(n / 2) = \\Theta(n)\\).

However, calculating the average time complexity for more complex algorithms can be quite difficult, as it's challenging to analyze the overall mathematical expectation under the data distribution. In such cases, we usually use the worst-case time complexity as the standard for judging the efficiency of the algorithm.

Why is the \\(\\Theta\\) symbol rarely seen?

Possibly because the \\(O\\) notation is more commonly spoken, it is often used to represent the average time complexity. However, strictly speaking, this practice is not accurate. In this book and other materials, if you encounter statements like \"average time complexity \\(O(n)\\)\", please understand it directly as \\(\\Theta(n)\\).

"},{"location":"chapter_data_structure/","title":"Chapter 3. \u00a0 Data Structures","text":"

Abstract

Data structures serve as a robust and diverse framework.

They offer a blueprint for the orderly organization of data, upon which algorithms come to life.

"},{"location":"chapter_data_structure/#chapter-contents","title":"Chapter Contents","text":"
  • 3.1 \u00a0 Classification of Data Structures
  • 3.2 \u00a0 Fundamental Data Types
  • 3.3 \u00a0 Number Encoding *
  • 3.4 \u00a0 Character Encoding *
  • 3.5 \u00a0 Summary
"},{"location":"chapter_data_structure/basic_data_types/","title":"3.2 \u00a0 Basic Data Types","text":"

When discussing data in computers, various forms like text, images, videos, voice and 3D models comes to mind. Despite their different organizational forms, they are all composed of various basic data types.

Basic data types are those that the CPU can directly operate on and are directly used in algorithms, mainly including the following.

  • Integer types: byte, short, int, long.
  • Floating-point types: float, double, used to represent decimals.
  • Character type: char, used to represent letters, punctuation, and even emojis in various languages.
  • Boolean type: bool, used to represent \"yes\" or \"no\" decisions.

Basic data types are stored in computers in binary form. One binary digit is 1 bit. In most modern operating systems, 1 byte consists of 8 bits.

The range of values for basic data types depends on the size of the space they occupy. Below, we take Java as an example.

  • The integer type byte occupies 1 byte = 8 bits and can represent \\(2^8\\) numbers.
  • The integer type int occupies 4 bytes = 32 bits and can represent \\(2^{32}\\) numbers.

The following table lists the space occupied, value range, and default values of various basic data types in Java. While memorizing this table isn't necessary, having a general understanding of it and referencing it when required is recommended.

Table 3-1 \u00a0 Space Occupied and Value Range of Basic Data Types

Type Symbol Space Occupied Minimum Value Maximum Value Default Value Integer byte 1 byte \\(-2^7\\) (\\(-128\\)) \\(2^7 - 1\\) (\\(127\\)) 0 short 2 bytes \\(-2^{15}\\) \\(2^{15} - 1\\) 0 int 4 bytes \\(-2^{31}\\) \\(2^{31} - 1\\) 0 long 8 bytes \\(-2^{63}\\) \\(2^{63} - 1\\) 0 Float float 4 bytes \\(1.175 \\times 10^{-38}\\) \\(3.403 \\times 10^{38}\\) \\(0.0\\text{f}\\) double 8 bytes \\(2.225 \\times 10^{-308}\\) \\(1.798 \\times 10^{308}\\) 0.0 Char char 2 bytes 0 \\(2^{16} - 1\\) 0 Boolean bool 1 byte \\(\\text{false}\\) \\(\\text{true}\\) \\(\\text{false}\\)

Please note that the above table is specific to Java's basic data types. Every programming language has its own data type definitions, which might differ in space occupied, value ranges, and default values.

  • In Python, the integer type int can be of any size, limited only by available memory; the floating-point float is double precision 64-bit; there is no char type, as a single character is actually a string str of length 1.
  • C and C++ do not specify the size of basic data types, it varies with implementation and platform. The above table follows the LP64 data model, used for Unix 64-bit operating systems including Linux and macOS.
  • The size of char in C and C++ is 1 byte, while in most programming languages, it depends on the specific character encoding method, as detailed in the \"Character Encoding\" chapter.
  • Even though representing a boolean only requires 1 bit (0 or 1), it is usually stored in memory as 1 byte. This is because modern computer CPUs typically use 1 byte as the smallest addressable memory unit.

So, what is the connection between basic data types and data structures? We know that data structures are ways to organize and store data in computers. The focus here is on \"structure\" rather than \"data\".

If we want to represent \"a row of numbers\", we naturally think of using an array. This is because the linear structure of an array can represent the adjacency and the ordering of the numbers, but whether the stored content is an integer int, a decimal float, or a character char, is irrelevant to the \"data structure\".

In other words, basic data types provide the \"content type\" of data, while data structures provide the \"way of organizing\" data. For example, in the following code, we use the same data structure (array) to store and represent different basic data types, including int, float, char, bool, etc.

PythonC++JavaC#GoSwiftJSTSDartRustCZig
# Using various basic data types to initialize arrays\nnumbers: list[int] = [0] * 5\ndecimals: list[float] = [0.0] * 5\n# Python's characters are actually strings of length 1\ncharacters: list[str] = ['0'] * 5\nbools: list[bool] = [False] * 5\n# Python's lists can freely store various basic data types and object references\ndata = [0, 0.0, 'a', False, ListNode(0)]\n
// Using various basic data types to initialize arrays\nint numbers[5];\nfloat decimals[5];\nchar characters[5];\nbool bools[5];\n
// Using various basic data types to initialize arrays\nint[] numbers = new int[5];\nfloat[] decimals = new float[5];\nchar[] characters = new char[5];\nboolean[] bools = new boolean[5];\n
// Using various basic data types to initialize arrays\nint[] numbers = new int[5];\nfloat[] decimals = new float[5];\nchar[] characters = new char[5];\nbool[] bools = new bool[5];\n
// Using various basic data types to initialize arrays\nvar numbers = [5]int{}\nvar decimals = [5]float64{}\nvar characters = [5]byte{}\nvar bools = [5]bool{}\n
// Using various basic data types to initialize arrays\nlet numbers = Array(repeating: Int(), count: 5)\nlet decimals = Array(repeating: Double(), count: 5)\nlet characters = Array(repeating: Character(\"a\"), count: 5)\nlet bools = Array(repeating: Bool(), count: 5)\n
// JavaScript's arrays can freely store various basic data types and objects\nconst array = [0, 0.0, 'a', false];\n
// Using various basic data types to initialize arrays\nconst numbers: number[] = [];\nconst characters: string[] = [];\nconst bools: boolean[] = [];\n
// Using various basic data types to initialize arrays\nList<int> numbers = List.filled(5, 0);\nList<double> decimals = List.filled(5, 0.0);\nList<String> characters = List.filled(5, 'a');\nList<bool> bools = List.filled(5, false);\n
// Using various basic data types to initialize arrays\nlet numbers: Vec<i32> = vec![0; 5];\nlet decimals: Vec<f32> = vec![0.0, 5];\nlet characters: Vec<char> = vec!['0'; 5];\nlet bools: Vec<bool> = vec![false; 5];\n
// Using various basic data types to initialize arrays\nint numbers[10];\nfloat decimals[10];\nchar characters[10];\nbool bools[10];\n
// Using various basic data types to initialize arrays\nvar numbers: [5]i32 = undefined;\nvar decimals: [5]f32 = undefined;\nvar characters: [5]u8 = undefined;\nvar bools: [5]bool = undefined;\n
"},{"location":"chapter_data_structure/character_encoding/","title":"3.4 \u00a0 Character Encoding *","text":"

In computers, all data is stored in binary form, and the character char is no exception. To represent characters, we need to establish a \"character set\" that defines a one-to-one correspondence between each character and binary numbers. With a character set, computers can convert binary numbers to characters by looking up a table.

"},{"location":"chapter_data_structure/character_encoding/#341-ascii-character-set","title":"3.4.1 \u00a0 ASCII Character Set","text":"

The \"ASCII code\" is one of the earliest character sets, officially known as the American Standard Code for Information Interchange. It uses 7 binary digits (the lower 7 bits of a byte) to represent a character, allowing for a maximum of 128 different characters. As shown in the Figure 3-6 , ASCII includes uppercase and lowercase English letters, numbers 0 ~ 9, some punctuation marks, and some control characters (such as newline and tab).

Figure 3-6 \u00a0 ASCII Code

However, ASCII can only represent English characters. With the globalization of computers, a character set called \"EASCII\" was developed to represent more languages. It expands on the 7-bit basis of ASCII to 8 bits, enabling the representation of 256 different characters.

Globally, a series of EASCII character sets for different regions emerged. The first 128 characters of these sets are uniformly ASCII, while the remaining 128 characters are defined differently to cater to various language requirements.

"},{"location":"chapter_data_structure/character_encoding/#342-gbk-character-set","title":"3.4.2 \u00a0 GBK Character Set","text":"

Later, it was found that EASCII still could not meet the character requirements of many languages. For instance, there are nearly a hundred thousand Chinese characters, with several thousand used in everyday life. In 1980, China's National Standards Bureau released the \"GB2312\" character set, which included 6763 Chinese characters, essentially meeting the computer processing needs for Chinese.

However, GB2312 could not handle some rare and traditional characters. The \"GBK\" character set, an expansion of GB2312, includes a total of 21886 Chinese characters. In the GBK encoding scheme, ASCII characters are represented with one byte, while Chinese characters use two bytes.

"},{"location":"chapter_data_structure/character_encoding/#343-unicode-character-set","title":"3.4.3 \u00a0 Unicode Character Set","text":"

With the rapid development of computer technology and a plethora of character sets and encoding standards, numerous problems arose. On one hand, these character sets generally only defined characters for specific languages and could not function properly in multilingual environments. On the other hand, the existence of multiple character set standards for the same language caused garbled text when information was exchanged between computers using different encoding standards.

Researchers of that era thought: What if we introduced a comprehensive character set that included all languages and symbols worldwide, wouldn't that solve the problems of cross-language environments and garbled text? Driven by this idea, the extensive character set, Unicode, was born.

The Chinese name for \"Unicode\" is \"\u7edf\u4e00\u7801\" (Unified Code), theoretically capable of accommodating over a million characters. It aims to incorporate characters from all over the world into a single set, providing a universal character set for processing and displaying various languages and reducing the issues of garbled text due to different encoding standards.

Since its release in 1991, Unicode has continually expanded to include new languages and characters. As of September 2022, Unicode contains 149,186 characters, including characters, symbols, and even emojis from various languages. In the vast Unicode character set, commonly used characters occupy 2 bytes, while some rare characters take up 3 or even 4 bytes.

Unicode is a universal character set that assigns a number (called a \"code point\") to each character, but it does not specify how these character code points should be stored in a computer. One might ask: When Unicode code points of varying lengths appear in a text, how does the system parse the characters? For example, given a 2-byte code, how does the system determine if it represents a single 2-byte character or two 1-byte characters?

A straightforward solution to this problem is to store all characters as equal-length encodings. As shown in the Figure 3-7 , each character in \"Hello\" occupies 1 byte, while each character in \"\u7b97\u6cd5\" (algorithm) occupies 2 bytes. We could encode all characters in \"Hello \u7b97\u6cd5\" as 2 bytes by padding the higher bits with zeros. This way, the system can parse a character every 2 bytes, recovering the content of the phrase.

Figure 3-7 \u00a0 Unicode Encoding Example

However, as ASCII has shown us, encoding English only requires 1 byte. Using the above approach would double the space occupied by English text compared to ASCII encoding, which is a waste of memory space. Therefore, a more efficient Unicode encoding method is needed.

"},{"location":"chapter_data_structure/character_encoding/#344-utf-8-encoding","title":"3.4.4 \u00a0 UTF-8 Encoding","text":"

Currently, UTF-8 has become the most widely used Unicode encoding method internationally. It is a variable-length encoding, using 1 to 4 bytes to represent a character, depending on the complexity of the character. ASCII characters need only 1 byte, Latin and Greek letters require 2 bytes, commonly used Chinese characters need 3 bytes, and some other rare characters need 4 bytes.

The encoding rules for UTF-8 are not complex and can be divided into two cases:

  • For 1-byte characters, set the highest bit to \\(0\\), and the remaining 7 bits to the Unicode code point. Notably, ASCII characters occupy the first 128 code points in the Unicode set. This means that UTF-8 encoding is backward compatible with ASCII. This implies that UTF-8 can be used to parse ancient ASCII text.
  • For characters of length \\(n\\) bytes (where \\(n > 1\\)), set the highest \\(n\\) bits of the first byte to \\(1\\), and the \\((n + 1)^{\\text{th}}\\) bit to \\(0\\); starting from the second byte, set the highest 2 bits of each byte to \\(10\\); the rest of the bits are used to fill the Unicode code point.

The Figure 3-8 shows the UTF-8 encoding for \"Hello\u7b97\u6cd5\". It can be observed that since the highest \\(n\\) bits are set to \\(1\\), the system can determine the length of the character as \\(n\\) by counting the number of highest bits set to \\(1\\).

But why set the highest 2 bits of the remaining bytes to \\(10\\)? Actually, this \\(10\\) serves as a kind of checksum. If the system starts parsing text from an incorrect byte, the \\(10\\) at the beginning of the byte can help the system quickly detect an anomaly.

The reason for using \\(10\\) as a checksum is that, under UTF-8 encoding rules, it's impossible for the highest two bits of a character to be \\(10\\). This can be proven by contradiction: If the highest two bits of a character are \\(10\\), it indicates that the character's length is \\(1\\), corresponding to ASCII. However, the highest bit of an ASCII character should be \\(0\\), contradicting the assumption.

Figure 3-8 \u00a0 UTF-8 Encoding Example

Apart from UTF-8, other common encoding methods include:

  • UTF-16 Encoding: Uses 2 or 4 bytes to represent a character. All ASCII characters and commonly used non-English characters are represented with 2 bytes; a few characters require 4 bytes. For 2-byte characters, the UTF-16 encoding is equal to the Unicode code point.
  • UTF-32 Encoding: Every character uses 4 bytes. This means UTF-32 occupies more space than UTF-8 and UTF-16, especially for texts with a high proportion of ASCII characters.

From the perspective of storage space, UTF-8 is highly efficient for representing English characters, requiring only 1 byte; UTF-16 might be more efficient for encoding some non-English characters (like Chinese), as it requires only 2 bytes, while UTF-8 might need 3 bytes.

From a compatibility standpoint, UTF-8 is the most versatile, with many tools and libraries supporting UTF-8 as a priority.

"},{"location":"chapter_data_structure/character_encoding/#345-character-encoding-in-programming-languages","title":"3.4.5 \u00a0 Character Encoding in Programming Languages","text":"

In many classic programming languages, strings during program execution are encoded using fixed-length encodings like UTF-16 or UTF-32. This allows strings to be treated as arrays, offering several advantages:

  • Random Access: Strings encoded in UTF-16 can be accessed randomly with ease. For UTF-8, which is a variable-length encoding, locating the \\(i^{th}\\) character requires traversing the string from the start to the \\(i^{th}\\) position, taking \\(O(n)\\) time.
  • Character Counting: Similar to random access, counting the number of characters in a UTF-16 encoded string is an \\(O(1)\\) operation. However, counting characters in a UTF-8 encoded string requires traversing the entire string.
  • String Operations: Many string operations like splitting, concatenating, inserting, and deleting are easier on UTF-16 encoded strings. These operations generally require additional computation on UTF-8 encoded strings to ensure the validity of the UTF-8 encoding.

The design of character encoding schemes in programming languages is an interesting topic involving various factors:

  • Java\u2019s String type uses UTF-16 encoding, with each character occupying 2 bytes. This was based on the initial belief that 16 bits were sufficient to represent all possible characters, a judgment later proven incorrect. As the Unicode standard expanded beyond 16 bits, characters in Java may now be represented by a pair of 16-bit values, known as \u201csurrogate pairs.\u201d
  • JavaScript and TypeScript use UTF-16 encoding for similar reasons as Java. When JavaScript was first introduced by Netscape in 1995, Unicode was still in its early stages, and 16-bit encoding was sufficient to represent all Unicode characters.
  • C# uses UTF-16 encoding, largely because the .NET platform, designed by Microsoft, and many Microsoft technologies, including the Windows operating system, extensively use UTF-16 encoding.

Due to the underestimation of character counts, these languages had to resort to using \"surrogate pairs\" to represent Unicode characters exceeding 16 bits. This approach has its drawbacks: strings containing surrogate pairs may have characters occupying 2 or 4 bytes, losing the advantage of fixed-length encoding, and handling surrogate pairs adds to the complexity and debugging difficulty of programming.

Owing to these reasons, some programming languages have adopted different encoding schemes:

  • Python\u2019s str type uses Unicode encoding with a flexible representation where the storage length of characters depends on the largest Unicode code point in the string. If all characters are ASCII, each character occupies 1 byte; if characters exceed ASCII but are within the Basic Multilingual Plane (BMP), each occupies 2 bytes; if characters exceed the BMP, each occupies 4 bytes.
  • Go\u2019s string type internally uses UTF-8 encoding. Go also provides the rune type for representing individual Unicode code points.
  • Rust\u2019s str and String types use UTF-8 encoding internally. Rust also offers the char type for individual Unicode code points.

It\u2019s important to note that the above discussion pertains to how strings are stored in programming languages, which is a different issue from how strings are stored in files or transmitted over networks. For file storage or network transmission, strings are usually encoded in UTF-8 format for optimal compatibility and space efficiency.

"},{"location":"chapter_data_structure/classification_of_data_structure/","title":"3.1 \u00a0 Classification of Data Structures","text":"

Common data structures include arrays, linked lists, stacks, queues, hash tables, trees, heaps, and graphs. They can be classified into \"logical structure\" and \"physical structure\".

"},{"location":"chapter_data_structure/classification_of_data_structure/#311-logical-structure-linear-and-non-linear","title":"3.1.1 \u00a0 Logical Structure: Linear and Non-Linear","text":"

The logical structures reveal the logical relationships between data elements. In arrays and linked lists, data are arranged in a specific sequence, demonstrating the linear relationship between data; while in trees, data are arranged hierarchically from the top down, showing the derived relationship between \"ancestors\" and \"descendants\"; and graphs are composed of nodes and edges, reflecting the intricate network relationship.

As shown in the Figure 3-1 , logical structures can be divided into two major categories: \"linear\" and \"non-linear\". Linear structures are more intuitive, indicating data is arranged linearly in logical relationships; non-linear structures, conversely, are arranged non-linearly.

  • Linear Data Structures: Arrays, Linked Lists, Stacks, Queues, Hash Tables.
  • Non-Linear Data Structures: Trees, Heaps, Graphs, Hash Tables.

Figure 3-1 \u00a0 Linear and Non-Linear Data Structures

Non-linear data structures can be further divided into tree structures and network structures.

  • Linear Structures: Arrays, linked lists, queues, stacks, and hash tables, where elements have a one-to-one sequential relationship.
  • Tree Structures: Trees, Heaps, Hash Tables, where elements have a one-to-many relationship.
  • Network Structures: Graphs, where elements have a many-to-many relationships.
"},{"location":"chapter_data_structure/classification_of_data_structure/#312-physical-structure-contiguous-and-dispersed","title":"3.1.2 \u00a0 Physical Structure: Contiguous and Dispersed","text":"

During the execution of an algorithm, the data being processed is stored in memory. The Figure 3-2 shows a computer memory stick where each black square is a physical memory space. We can think of memory as a vast Excel spreadsheet, with each cell capable of storing a certain amount of data.

The system accesses the data at the target location by means of a memory address. As shown in the Figure 3-2 , the computer assigns a unique identifier to each cell in the table according to specific rules, ensuring that each memory space has a unique memory address. With these addresses, the program can access the data stored in memory.

Figure 3-2 \u00a0 Memory Stick, Memory Spaces, Memory Addresses

Tip

It's worth noting that comparing memory to an Excel spreadsheet is a simplified analogy. The actual working mechanism of memory is more complex, involving concepts like address space, memory management, cache mechanisms, virtual memory, and physical memory.

Memory is a shared resource for all programs. When a block of memory is occupied by one program, it cannot be simultaneously used by other programs. Therefore, considering memory resources is crucial in designing data structures and algorithms. For instance, the algorithm's peak memory usage should not exceed the remaining free memory of the system; if there is a lack of contiguous memory blocks, then the data structure chosen must be able to be stored in non-contiguous memory blocks.

As illustrated in the Figure 3-3 , the physical structure reflects the way data is stored in computer memory and it can be divided into contiguous space storage (arrays) and non-contiguous space storage (linked lists). The two types of physical structures exhibit complementary characteristics in terms of time efficiency and space efficiency.

Figure 3-3 \u00a0 Contiguous Space Storage and Dispersed Space Storage

It is worth noting that all data structures are implemented based on arrays, linked lists, or a combination of both. For example, stacks and queues can be implemented using either arrays or linked lists; while implementations of hash tables may involve both arrays and linked lists. - Array-based implementations: Stacks, Queues, Hash Tables, Trees, Heaps, Graphs, Matrices, Tensors (arrays with dimensions \\(\\geq 3\\)). - Linked-list-based implementations: Stacks, Queues, Hash Tables, Trees, Heaps, Graphs, etc.

Data structures implemented based on arrays are also called \u201cStatic Data Structures,\u201d meaning their length cannot be changed after initialization. Conversely, those based on linked lists are called \u201cDynamic Data Structures,\u201d which can still adjust their size during program execution.

Tip

If you find it challenging to comprehend the physical structure, it is recommended that you read the next chapter, \"Arrays and Linked Lists,\" and revisit this section later.

"},{"location":"chapter_data_structure/number_encoding/","title":"3.3 \u00a0 Number Encoding *","text":"

Note

In this book, chapters marked with an asterisk '*' are optional readings. If you are short on time or find them challenging, you may skip these initially and return to them after completing the essential chapters.

"},{"location":"chapter_data_structure/number_encoding/#331-integer-encoding","title":"3.3.1 \u00a0 Integer Encoding","text":"

In the table from the previous section, we observed that all integer types can represent one more negative number than positive numbers, such as the byte range of \\([-128, 127]\\). This phenomenon seems counterintuitive, and its underlying reason involves knowledge of sign-magnitude, one's complement, and two's complement encoding.

Firstly, it's important to note that numbers are stored in computers using the two's complement form. Before analyzing why this is the case, let's define these three encoding methods:

  • Sign-magnitude: The highest bit of a binary representation of a number is considered the sign bit, where \\(0\\) represents a positive number and \\(1\\) represents a negative number. The remaining bits represent the value of the number.
  • One's complement: The one's complement of a positive number is the same as its sign-magnitude. For negative numbers, it's obtained by inverting all bits except the sign bit.
  • Two's complement: The two's complement of a positive number is the same as its sign-magnitude. For negative numbers, it's obtained by adding \\(1\\) to their one's complement.

The following diagram illustrates the conversions among sign-magnitude, one's complement, and two's complement:

Figure 3-4 \u00a0 Conversions between Sign-Magnitude, One's Complement, and Two's Complement

Although sign-magnitude is the most intuitive, it has limitations. For one, negative numbers in sign-magnitude cannot be directly used in calculations. For example, in sign-magnitude, calculating \\(1 + (-2)\\) results in \\(-3\\), which is incorrect.

\\[ \\begin{aligned} & 1 + (-2) \\newline & \\rightarrow 0000 \\; 0001 + 1000 \\; 0010 \\newline & = 1000 \\; 0011 \\newline & \\rightarrow -3 \\end{aligned} \\]

To address this, computers introduced the one's complement. If we convert to one's complement and calculate \\(1 + (-2)\\), then convert the result back to sign-magnitude, we get the correct result of \\(-1\\).

\\[ \\begin{aligned} & 1 + (-2) \\newline & \\rightarrow 0000 \\; 0001 \\; \\text{(Sign-magnitude)} + 1000 \\; 0010 \\; \\text{(Sign-magnitude)} \\newline & = 0000 \\; 0001 \\; \\text{(One's complement)} + 1111 \\; 1101 \\; \\text{(One's complement)} \\newline & = 1111 \\; 1110 \\; \\text{(One's complement)} \\newline & = 1000 \\; 0001 \\; \\text{(Sign-magnitude)} \\newline & \\rightarrow -1 \\end{aligned} \\]

Additionally, there are two representations of zero in sign-magnitude: \\(+0\\) and \\(-0\\). This means two different binary encodings for zero, which could lead to ambiguity. For example, in conditional checks, not differentiating between positive and negative zero might result in incorrect outcomes. Addressing this ambiguity would require additional checks, potentially reducing computational efficiency.

\\[ \\begin{aligned} +0 & \\rightarrow 0000 \\; 0000 \\newline -0 & \\rightarrow 1000 \\; 0000 \\end{aligned} \\]

Like sign-magnitude, one's complement also suffers from the positive and negative zero ambiguity. Therefore, computers further introduced the two's complement. Let's observe the conversion process for negative zero in sign-magnitude, one's complement, and two's complement:

\\[ \\begin{aligned} -0 \\rightarrow \\; & 1000 \\; 0000 \\; \\text{(Sign-magnitude)} \\newline = \\; & 1111 \\; 1111 \\; \\text{(One's complement)} \\newline = 1 \\; & 0000 \\; 0000 \\; \\text{(Two's complement)} \\newline \\end{aligned} \\]

Adding \\(1\\) to the one's complement of negative zero produces a carry, but with byte length being only 8 bits, the carried-over \\(1\\) to the 9th bit is discarded. Therefore, the two's complement of negative zero is \\(0000 \\; 0000\\), the same as positive zero, thus resolving the ambiguity.

One last puzzle is the \\([-128, 127]\\) range for byte, with an additional negative number, \\(-128\\). We observe that for the interval \\([-127, +127]\\), all integers have corresponding sign-magnitude, one's complement, and two's complement, allowing for mutual conversion between them.

However, the two's complement \\(1000 \\; 0000\\) is an exception without a corresponding sign-magnitude. According to the conversion method, its sign-magnitude would be \\(0000 \\; 0000\\), indicating zero. This presents a contradiction because its two's complement should represent itself. Computers designate this special two's complement \\(1000 \\; 0000\\) as representing \\(-128\\). In fact, the calculation of \\((-1) + (-127)\\) in two's complement results in \\(-128\\).

\\[ \\begin{aligned} & (-127) + (-1) \\newline & \\rightarrow 1111 \\; 1111 \\; \\text{(Sign-magnitude)} + 1000 \\; 0001 \\; \\text{(Sign-magnitude)} \\newline & = 1000 \\; 0000 \\; \\text{(One's complement)} + 1111 \\; 1110 \\; \\text{(One's complement)} \\newline & = 1000 \\; 0001 \\; \\text{(Two's complement)} + 1111 \\; 1111 \\; \\text{(Two's complement)} \\newline & = 1000 \\; 0000 \\; \\text{(Two's complement)} \\newline & \\rightarrow -128 \\end{aligned} \\]

As you might have noticed, all these calculations are additions, hinting at an important fact: computers' internal hardware circuits are primarily designed around addition operations. This is because addition is simpler to implement in hardware compared to other operations like multiplication, division, and subtraction, allowing for easier parallelization and faster computation.

It's important to note that this doesn't mean computers can only perform addition. By combining addition with basic logical operations, computers can execute a variety of other mathematical operations. For example, the subtraction \\(a - b\\) can be translated into \\(a + (-b)\\); multiplication and division can be translated into multiple additions or subtractions.

We can now summarize the reason for using two's complement in computers: with two's complement representation, computers can use the same circuits and operations to handle both positive and negative number addition, eliminating the need for special hardware circuits for subtraction and avoiding the ambiguity of positive and negative zero. This greatly simplifies hardware design and enhances computational efficiency.

The design of two's complement is quite ingenious, and due to space constraints, we'll stop here. Interested readers are encouraged to explore further.

"},{"location":"chapter_data_structure/number_encoding/#332-floating-point-number-encoding","title":"3.3.2 \u00a0 Floating-Point Number Encoding","text":"

You might have noticed something intriguing: despite having the same length of 4 bytes, why does a float have a much larger range of values compared to an int? This seems counterintuitive, as one would expect the range to shrink for float since it needs to represent fractions.

In fact, this is due to the different representation method used by floating-point numbers (float). Let's consider a 32-bit binary number as:

\\[ b_{31} b_{30} b_{29} \\ldots b_2 b_1 b_0 \\]

According to the IEEE 754 standard, a 32-bit float consists of the following three parts:

  • Sign bit \\(\\mathrm{S}\\): Occupies 1 bit, corresponding to \\(b_{31}\\).
  • Exponent bit \\(\\mathrm{E}\\): Occupies 8 bits, corresponding to \\(b_{30} b_{29} \\ldots b_{23}\\).
  • Fraction bit \\(\\mathrm{N}\\): Occupies 23 bits, corresponding to \\(b_{22} b_{21} \\ldots b_0\\).

The value of a binary float number is calculated as:

\\[ \\text{val} = (-1)^{b_{31}} \\times 2^{\\left(b_{30} b_{29} \\ldots b_{23}\\right)_2 - 127} \\times \\left(1 . b_{22} b_{21} \\ldots b_0\\right)_2 \\]

Converted to a decimal formula, this becomes:

\\[ \\text{val} = (-1)^{\\mathrm{S}} \\times 2^{\\mathrm{E} - 127} \\times (1 + \\mathrm{N}) \\]

The range of each component is:

\\[ \\begin{aligned} \\mathrm{S} \\in & \\{ 0, 1\\}, \\quad \\mathrm{E} \\in \\{ 1, 2, \\dots, 254 \\} \\newline (1 + \\mathrm{N}) = & (1 + \\sum_{i=1}^{23} b_{23-i} \\times 2^{-i}) \\subset [1, 2 - 2^{-23}] \\end{aligned} \\]

Figure 3-5 \u00a0 Example Calculation of a float in IEEE 754 Standard

Observing the diagram, given an example data \\(\\mathrm{S} = 0\\), \\(\\mathrm{E} = 124\\), \\(\\mathrm{N} = 2^{-2} + 2^{-3} = 0.375\\), we have:

\\[ \\text{val} = (-1)^0 \\times 2^{124 - 127} \\times (1 + 0.375) = 0.171875 \\]

Now we can answer the initial question: The representation of float includes an exponent bit, leading to a much larger range than int. Based on the above calculation, the maximum positive number representable by float is approximately \\(2^{254 - 127} \\times (2 - 2^{-23}) \\approx 3.4 \\times 10^{38}\\), and the minimum negative number is obtained by switching the sign bit.

However, the trade-off for float's expanded range is a sacrifice in precision. The integer type int uses all 32 bits to represent the number, with values evenly distributed; but due to the exponent bit, the larger the value of a float, the greater the difference between adjacent numbers.

As shown in the Table 3-2 , exponent bits \\(E = 0\\) and \\(E = 255\\) have special meanings, used to represent zero, infinity, \\(\\mathrm{NaN}\\), etc.

Table 3-2 \u00a0 Meaning of Exponent Bits

Exponent Bit E Fraction Bit \\(\\mathrm{N} = 0\\) Fraction Bit \\(\\mathrm{N} \\ne 0\\) Calculation Formula \\(0\\) \\(\\pm 0\\) Subnormal Numbers \\((-1)^{\\mathrm{S}} \\times 2^{-126} \\times (0.\\mathrm{N})\\) \\(1, 2, \\dots, 254\\) Normal Numbers Normal Numbers \\((-1)^{\\mathrm{S}} \\times 2^{(\\mathrm{E} -127)} \\times (1.\\mathrm{N})\\) \\(255\\) \\(\\pm \\infty\\) \\(\\mathrm{NaN}\\)

It's worth noting that subnormal numbers significantly improve the precision of floating-point numbers. The smallest positive normal number is \\(2^{-126}\\), and the smallest positive subnormal number is \\(2^{-126} \\times 2^{-23}\\).

Double-precision double also uses a similar representation method to float, which is not elaborated here for brevity.

"},{"location":"chapter_data_structure/summary/","title":"3.5 \u00a0 Summary","text":""},{"location":"chapter_data_structure/summary/#1-key-review","title":"1. \u00a0 Key Review","text":"
  • Data structures can be categorized from two perspectives: logical structure and physical structure. Logical structure describes the logical relationships between data elements, while physical structure describes how data is stored in computer memory.
  • Common logical structures include linear, tree-like, and network structures. We generally classify data structures into linear (arrays, linked lists, stacks, queues) and non-linear (trees, graphs, heaps) based on their logical structure. The implementation of hash tables may involve both linear and non-linear data structures.
  • When a program runs, data is stored in computer memory. Each memory space has a corresponding memory address, and the program accesses data through these addresses.
  • Physical structures are primarily divided into contiguous space storage (arrays) and dispersed space storage (linked lists). All data structures are implemented using arrays, linked lists, or a combination of both.
  • Basic data types in computers include integers (byte, short, int, long), floating-point numbers (float, double), characters (char), and booleans (boolean). Their range depends on the size of the space occupied and the representation method.
  • Original code, complement code, and two's complement code are three methods of encoding numbers in computers, and they can be converted into each other. The highest bit of the original code of an integer is the sign bit, and the remaining bits represent the value of the number.
  • Integers are stored in computers in the form of two's complement. In this representation, the computer can treat the addition of positive and negative numbers uniformly, without the need for special hardware circuits for subtraction, and there is no ambiguity of positive and negative zero.
  • The encoding of floating-point numbers consists of 1 sign bit, 8 exponent bits, and 23 fraction bits. Due to the presence of the exponent bit, the range of floating-point numbers is much greater than that of integers, but at the cost of sacrificing precision.
  • ASCII is the earliest English character set, 1 byte in length, and includes 127 characters. The GBK character set is a commonly used Chinese character set, including more than 20,000 Chinese characters. Unicode strives to provide a complete character set standard, including characters from various languages worldwide, thus solving the problem of garbled characters caused by inconsistent character encoding methods.
  • UTF-8 is the most popular Unicode encoding method, with excellent universality. It is a variable-length encoding method with good scalability and effectively improves the efficiency of space usage. UTF-16 and UTF-32 are fixed-length encoding methods. When encoding Chinese characters, UTF-16 occupies less space than UTF-8. Programming languages like Java and C# use UTF-16 encoding by default.
"},{"location":"chapter_data_structure/summary/#2-q-a","title":"2. \u00a0 Q & A","text":"

Q: Why does a hash table contain both linear and non-linear data structures?

The underlying structure of a hash table is an array. To resolve hash collisions, we may use \"chaining\": each bucket in the array points to a linked list, which, when exceeding a certain threshold, might be transformed into a tree (usually a red-black tree). From a storage perspective, the foundation of a hash table is an array, where each bucket slot might contain a value, a linked list, or a tree. Therefore, hash tables may contain both linear data structures (arrays, linked lists) and non-linear data structures (trees).

Q: Is the length of the char type 1 byte?

The length of the char type is determined by the encoding method used by the programming language. For example, Java, JavaScript, TypeScript, and C# all use UTF-16 encoding (to save Unicode code points), so the length of the char type is 2 bytes.

Q: Is there ambiguity in calling data structures based on arrays \"static data structures\"? Because operations like push and pop on stacks are \"dynamic\".

While stacks indeed allow for dynamic data operations, the data structure itself remains \"static\" (with unchangeable length). Even though data structures based on arrays can dynamically add or remove elements, their capacity is fixed. If the data volume exceeds the pre-allocated size, a new, larger array needs to be created, and the contents of the old array copied into it.

Q: When building stacks (queues) without specifying their size, why are they considered \"static data structures\"?

In high-level programming languages, we don't need to manually specify the initial capacity of stacks (queues); this task is automatically handled internally by the class. For example, the initial capacity of Java's ArrayList is usually 10. Furthermore, the expansion operation is also implemented automatically. See the subsequent \"List\" chapter for details.

"},{"location":"chapter_introduction/","title":"Chapter 1. \u00a0 Introduction to Algorithms","text":"

Abstract

A graceful maiden dances, intertwined with the data, her skirt swaying to the melody of algorithms.

She invites you to a dance, follow her steps, and enter the world of algorithms full of logic and beauty.

"},{"location":"chapter_introduction/#chapter-contents","title":"Chapter Contents","text":"
  • 1.1 \u00a0 Algorithms are Everywhere
  • 1.2 \u00a0 What is an Algorithm
  • 1.3 \u00a0 Summary
"},{"location":"chapter_introduction/algorithms_are_everywhere/","title":"1.1 \u00a0 Algorithms are Everywhere","text":"

When we hear the word \"algorithm,\" we naturally think of mathematics. However, many algorithms do not involve complex mathematics but rely more on basic logic, which can be seen everywhere in our daily lives.

Before formally discussing algorithms, there's an interesting fact worth sharing: you have already unconsciously learned many algorithms and have become accustomed to applying them in your daily life. Here, I will give a few specific examples to prove this point.

Example 1: Looking Up a Dictionary. In an English dictionary, words are listed alphabetically. Suppose we're searching for a word that starts with the letter \\(r\\). This is typically done in the following way:

  1. Open the dictionary to about halfway and check the first letter on the page, let's say the letter is \\(m\\).
  2. Since \\(r\\) comes after \\(m\\) in the alphabet, we can ignore the first half of the dictionary and focus on the latter half.
  3. Repeat steps 1. and 2. until you find the page where the word starts with \\(r\\).
<1><2><3><4><5>

Figure 1-1 \u00a0 Process of Looking Up a Dictionary

This essential skill for elementary students, looking up a dictionary, is actually the famous \"Binary Search\" algorithm. From a data structure perspective, we can consider the dictionary as a sorted \"array\"; from an algorithmic perspective, the series of actions taken to look up a word in the dictionary can be viewed as \"Binary Search.\"

Example 2: Organizing Playing Cards. When playing cards, we need to arrange the cards in our hand in ascending order, as shown in the following process.

  1. Divide the playing cards into \"ordered\" and \"unordered\" sections, assuming initially the leftmost card is already in order.
  2. Take out a card from the unordered section and insert it into the correct position in the ordered section; after this, the leftmost two cards are in order.
  3. Continue to repeat step 2. until all cards are in order.

Figure 1-2 \u00a0 Playing Cards Sorting Process

The above method of organizing playing cards is essentially the \"Insertion Sort\" algorithm, which is very efficient for small datasets. Many programming languages' sorting functions include the insertion sort.

Example 3: Making Change. Suppose we buy goods worth \\(69\\) yuan at a supermarket and give the cashier \\(100\\) yuan, then the cashier needs to give us \\(31\\) yuan in change. They would naturally complete the thought process as shown below.

  1. The options are currencies smaller than \\(31\\), including \\(1\\), \\(5\\), \\(10\\), and \\(20\\).
  2. Take out the largest \\(20\\) from the options, leaving \\(31 - 20 = 11\\).
  3. Take out the largest \\(10\\) from the remaining options, leaving \\(11 - 10 = 1\\).
  4. Take out the largest \\(1\\) from the remaining options, leaving \\(1 - 1 = 0\\).
  5. Complete the change-making, with the solution being \\(20 + 10 + 1 = 31\\).

Figure 1-3 \u00a0 Change making process

In the above steps, we make the best choice at each step (using the largest denomination possible), ultimately resulting in a feasible change-making plan. From the perspective of data structures and algorithms, this method is essentially a \"Greedy\" algorithm.

From cooking a meal to interstellar travel, almost all problem-solving involves algorithms. The advent of computers allows us to store data structures in memory and write code to call the CPU and GPU to execute algorithms. In this way, we can transfer real-life problems to computers, solving various complex issues more efficiently.

Tip

If concepts such as data structures, algorithms, arrays, and binary search still seem somewhat obsecure, I encourage you to continue reading. This book will gently guide you into the realm of understanding data structures and algorithms.

"},{"location":"chapter_introduction/summary/","title":"1.3 \u00a0 Summary","text":"
  • Algorithms are ubiquitous in daily life and are not as inaccessible and complex as they might seem. In fact, we have already unconsciously learned many algorithms to solve various problems in life.
  • The principle of looking up a word in a dictionary is consistent with the binary search algorithm. The binary search algorithm embodies the important algorithmic concept of divide and conquer.
  • The process of organizing playing cards is very similar to the insertion sort algorithm. The insertion sort algorithm is suitable for sorting small datasets.
  • The steps of making change in currency essentially follow the greedy algorithm, where each step involves making the best possible choice at the moment.
  • An algorithm is a set of instructions or steps used to solve a specific problem within a finite amount of time, while a data structure is the way data is organized and stored in a computer.
  • Data structures and algorithms are closely linked. Data structures are the foundation of algorithms, and algorithms are the stage to utilize the functions of data structures.
  • We can liken data structures and algorithms to building blocks. The blocks represent data, the shape and connection method of the blocks represent data structures, and the steps of assembling the blocks correspond to algorithms.
"},{"location":"chapter_introduction/what_is_dsa/","title":"1.2 \u00a0 What is an Algorithm","text":""},{"location":"chapter_introduction/what_is_dsa/#121-definition-of-an-algorithm","title":"1.2.1 \u00a0 Definition of an Algorithm","text":"

An \"algorithm\" is a set of instructions or steps to solve a specific problem within a finite amount of time. It has the following characteristics:

  • The problem is clearly defined, including unambiguous definitions of input and output.
  • The algorithm is feasible, meaning it can be completed within a finite number of steps, time, and memory space.
  • Each step has a definitive meaning. The output is consistently the same under the same inputs and conditions.
"},{"location":"chapter_introduction/what_is_dsa/#122-definition-of-a-data-structure","title":"1.2.2 \u00a0 Definition of a Data Structure","text":"

A \"data structure\" is a way of organizing and storing data in a computer, with the following design goals:

  • Minimize space occupancy to save computer memory.
  • Make data operations as fast as possible, covering data access, addition, deletion, updating, etc.
  • Provide concise data representation and logical information to enable efficient algorithm execution.

Designing data structures is a balancing act, often requiring trade-offs. If you want to improve in one aspect, you often need to compromise in another. Here are two examples:

  • Compared to arrays, linked lists offer more convenience in data addition and deletion but sacrifice data access speed.
  • Graphs, compared to linked lists, provide richer logical information but require more memory space.
"},{"location":"chapter_introduction/what_is_dsa/#123-relationship-between-data-structures-and-algorithms","title":"1.2.3 \u00a0 Relationship Between Data Structures and Algorithms","text":"

As shown in the Figure 1-4 , data structures and algorithms are highly related and closely integrated, specifically in the following three aspects:

  • Data structures are the foundation of algorithms. They provide structured data storage and methods for manipulating data for algorithms.
  • Algorithms are the stage where data structures come into play. The data structure alone only stores data information; it is through the application of algorithms that specific problems can be solved.
  • Algorithms can often be implemented based on different data structures, but their execution efficiency can vary greatly. Choosing the right data structure is key.

Figure 1-4 \u00a0 Relationship between data structures and algorithms

Data structures and algorithms can be likened to a set of building blocks, as illustrated in the Figure 1-5 . A building block set includes numerous pieces, accompanied by detailed assembly instructions. Following these instructions step by step allows us to construct an intricate block model.

Figure 1-5 \u00a0 Assembling blocks

The detailed correspondence between the two is shown in the Table 1-1 .

Table 1-1 \u00a0 Comparing Data Structures and Algorithms to Building Blocks

Data Structures and Algorithms Building Blocks Input data Unassembled blocks Data structure Organization of blocks, including shape, size, connections, etc Algorithm A series of steps to assemble the blocks into the desired shape Output data Completed Block model

It's worth noting that data structures and algorithms are independent of programming languages. For this reason, this book is able to provide implementations in multiple programming languages.

Conventional Abbreviation

In real-life discussions, we often refer to \"Data Structures and Algorithms\" simply as \"Algorithms\". For example, the well-known LeetCode algorithm problems actually test both data structure and algorithm knowledge.

"},{"location":"chapter_preface/","title":"Chapter 0. \u00a0 Preface","text":"

Abstract

Algorithms are like a beautiful symphony, with each line of code flowing like a rhythm.

May this book ring softly in your mind, leaving a unique and profound melody.

"},{"location":"chapter_preface/#chapter-contents","title":"Chapter Contents","text":"
  • 0.1 \u00a0 About This Book
  • 0.2 \u00a0 How to Read
  • 0.3 \u00a0 Summary
"},{"location":"chapter_preface/about_the_book/","title":"0.1 \u00a0 About This Book","text":"

This open-source project aims to create a free, and beginner-friendly crash course on data structures and algorithms.

  • Using animated illustrations, it delivers structured insights into data structures and algorithmic concepts, ensuring comprehensibility and a smooth learning curve.
  • Run code with just one click, supporting Java, C++, Python, Go, JS, TS, C#, Swift, Rust, Dart, Zig and other languages.
  • Readers are encouraged to engage with each other in the discussion area for each section, questions and comments are usually answered within two days.
"},{"location":"chapter_preface/about_the_book/#011-target-audience","title":"0.1.1 \u00a0 Target Audience","text":"

If you are new to algorithms with limited exposure, or you have accumulated some experience in algorithms, but you only have a vague understanding of data structures and algorithms, and you are constantly jumping between \"yep\" and \"hmm\", then this book is for you!

If you have already accumulated a certain amount of problem-solving experience, and are familiar with most types of problems, then this book can help you review and organize your algorithm knowledge system. The repository's source code can be used as a \"problem-solving toolkit\" or an \"algorithm cheat sheet\".

If you are an algorithm expert, we look forward to receiving your valuable suggestions, or join us and collaborate.

Prerequisites

You should know how to write and read simple code in at least one programming language.

"},{"location":"chapter_preface/about_the_book/#012-content-structure","title":"0.1.2 \u00a0 Content Structure","text":"

The main content of the book is shown in the following figure.

  • Complexity Analysis: explores aspects and methods for evaluating data structures and algorithms. Covers methods of deriving time complexity and space complexity, along with common types and examples.
  • Data Structures: focuses on fundamental data types, classification methods, definitions, pros and cons, common operations, types, applications, and implementation methods of data structures such as array, linked list, stack, queue, hash table, tree, heap, graph, etc.
  • Algorithms: defines algorithms, discusses their pros and cons, efficiency, application scenarios, problem-solving steps, and includes sample questions for various algorithms such as search, sorting, divide and conquer, backtracking, dynamic programming, greedy algorithms, and more.

Figure 0-1 \u00a0 Main Content of the Book

"},{"location":"chapter_preface/about_the_book/#013-acknowledgements","title":"0.1.3 \u00a0 Acknowledgements","text":"

This book is continuously improved with the joint efforts of many contributors from the open-source community. Thanks to each writer who invested their time and energy, listed in the order generated by GitHub: krahets, codingonion, nuomi1, Gonglja, Reanon, justin-tse, danielsss, hpstory, S-N-O-R-L-A-X, night-cruise, msk397, gvenusleo, RiverTwilight, gyt95, zhuoqinyue, Zuoxun, Xia-Sang, mingXta, FangYuan33, GN-Yu, IsChristina, xBLACKICEx, guowei-gong, Cathay-Chen, mgisr, JoseHung, qualifier1024, pengchzn, Guanngxu, longsizhuo, L-Super, what-is-me, yuan0221, lhxsm, Slone123c, WSL0809, longranger2, theNefelibatas, xiongsp, JeffersonHuang, hongyun-robot, K3v123, yuelinxin, a16su, gaofer, malone6, Wonderdch, xjr7670, DullSword, Horbin-Magician, NI-SW, reeswell, XC-Zero, XiaChuerwu, yd-j, iron-irax, huawuque404, MolDuM, Nigh, KorsChen, foursevenlove, 52coder, bubble9um, youshaoXG, curly210102, gltianwen, fanchenggang, Transmigration-zhou, FloranceYeh, FreddieLi, ShiMaRing, lipusheng, Javesun99, JackYang-hellobobo, shanghai-Jerry, 0130w, Keynman, psychelzh, logan-qiu, ZnYang2018, MwumLi, 1ch0, Phoenix0415, qingpeng9802, Richard-Zhang1019, QiLOL, Suremotoo, Turing-1024-Lee, Evilrabbit520, GaochaoZhu, ZJKung, linzeyan, hezhizhen, ZongYangL, beintentional, czruby, coderlef, dshlstarr, szu17dmy, fbigm, gledfish, hts0000, boloboloda, iStig, jiaxianhua, wenjianmin, keshida, kilikilikid, lclc6, lwbaptx, liuxjerry, lucaswangdev, lyl625760, chadyi, noobcodemaker, selear, siqyka, syd168, 4yDX3906, tao363, wangwang105, weibk, yabo083, yi427, yishangzhang, zhouLion, baagod, ElaBosak233, xb534, luluxia, yanedie, thomasq0, YangXuanyi and th1nk3r-ing.

The code review work for this book was completed by codingonion, Gonglja, gvenusleo, hpstory, justin\u2010tse, krahets, night-cruise, nuomi1, and Reanon (listed in alphabetical order). Thanks to them for their time and effort, ensuring the standardization and uniformity of the code in various languages.

Throughout the creation of this book, numerous individuals provided invaluable assistance, including but not limited to:

  • Thanks to my mentor at the company, Dr. Xi Li, who encouraged me in a conversation to \"get moving fast,\" which solidified my determination to write this book;
  • Thanks to my girlfriend Bubble, as the first reader of this book, for offering many valuable suggestions from the perspective of a beginner in algorithms, making this book more suitable for newbies;
  • Thanks to Tengbao, Qibao, and Feibao for coming up with a creative name for this book, evoking everyone's fond memories of writing their first line of code \"Hello World!\";
  • Thanks to Xiaoquan for providing professional help in intellectual property, which has played a significant role in the development of this open-source book;
  • Thanks to Sutong for designing a beautiful cover and logo for this book, and for patiently making multiple revisions under my insistence;
  • Thanks to @squidfunk for providing writing and typesetting suggestions, as well as his developed open-source documentation theme Material-for-MkDocs.

Throughout the writing journey, I delved into numerous textbooks and articles on data structures and algorithms. These works served as exemplary models, ensuring the accuracy and quality of this book's content. I extend my gratitude to all who preceded me for their invaluable contributions!

This book advocates a combination of hands-on and minds-on learning, inspired in this regard by \"Dive into Deep Learning\". I highly recommend this excellent book to all readers.

Heartfelt thanks to my parents, whose ongoing support and encouragement have allowed me to do this interesting work.

"},{"location":"chapter_preface/suggestions/","title":"0.2 \u00a0 How to Read","text":"

Tip

For the best reading experience, it is recommended that you read through this section.

"},{"location":"chapter_preface/suggestions/#021-writing-conventions","title":"0.2.1 \u00a0 Writing Conventions","text":"
  • Chapters marked with '*' after the title are optional and contain relatively challenging content. If you are short on time, it is advisable to skip them.
  • Key technical terms and their English equivalents are enclosed in Bold + italics brackets, for example, array. It's advisable to familiarize yourself with these for better comprehension of technical texts.
  • Proprietary terms and words with specific meanings are indicated with \u201cquotation marks\u201d to avoid ambiguity.
  • Bolded text indicates key content or summary statements, which deserve special attention.
  • When it comes to terms that are inconsistent between programming languages, this book follows Python, for example using \\(\\text{None}\\) to mean \"null\".
  • This book partially ignores the comment conventions for programming languages in exchange for a more compact layout of the content. The comments primarily consist of three types: title comments, content comments, and multi-line comments.
PythonC++JavaC#GoSwiftJSTSDartRustCZig
\"\"\"Header comments for labeling functions, classes, test samples, etc\"\"\"\"\n\n# Comments for explaining details\n\n\"\"\"\nMultiline\ncomments\n\"\"\"\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
// Header comments for labeling functions, classes, test samples, etc\n\n// Comments for explaining details.\n\n// Multiline\n// comments\n
"},{"location":"chapter_preface/suggestions/#022-efficient-learning-via-animated-illustrations","title":"0.2.2 \u00a0 Efficient Learning via Animated Illustrations","text":"

Compared with text, videos and pictures have a higher density of information and are more structured, making them easier to understand. In this book, key and difficult concepts are mainly presented through animations and illustrations, with text serving as explanations and supplements.

When encountering content with animations or illustrations as shown in the Figure 0-2 , prioritize understanding the figure, with text as supplementary, integrating both for a comprehensive understanding.

Figure 0-2 \u00a0 Animated Illustration Example

"},{"location":"chapter_preface/suggestions/#023-deepen-understanding-through-coding-practice","title":"0.2.3 \u00a0 Deepen Understanding through Coding Practice","text":"

The source code of this book is hosted on the GitHub Repository. As shown in the Figure 0-3 , the source code comes with test examples and can be executed with just a single click.

If time permits, it's recommended to type out the code yourself. If pressed for time, at least read and run all the codes.

Compared to just reading code, writing code often yields more learning. Learning by doing is the real way to learn.

Figure 0-3 \u00a0 Running Code Example

Setting up to run the code involves three main steps.

Step 1: Install a local programming environment. Follow the tutorial in the appendix for installation, or skip this step if already installed.

Step 2: Clone or download the code repository. Visit the GitHub Repository.

If Git is installed, use the following command to clone the repository:

git clone https://github.com/krahets/hello-algo.git\n

Alternatively, you can also click the \"Download ZIP\" button at the location shown in the Figure 0-4 to directly download the code as a compressed ZIP file. Then, you can simply extract it locally.

Figure 0-4 \u00a0 Cloning Repository and Downloading Code

Step 3: Run the source code. As shown in the Figure 0-5 , for the code block labeled with the file name at the top, we can find the corresponding source code file in the codes folder of the repository. These files can be executed with a single click, which will help you save unnecessary debugging time and allow you to focus on learning.

Figure 0-5 \u00a0 Code Block and Corresponding Source Code File

"},{"location":"chapter_preface/suggestions/#024-learning-together-in-discussion","title":"0.2.4 \u00a0 Learning Together in Discussion","text":"

While reading this book, please don't skip over the points that you didn't learn. Feel free to post your questions in the comment section. We will be happy to answer them and can usually respond within two days.

As illustrated in the Figure 0-6 , each chapter features a comment section at the bottom. I encourage you to pay attention to these comments. They not only expose you to others' encountered problems, aiding in identifying knowledge gaps and sparking deeper contemplation, but also invite you to generously contribute by answering fellow readers' inquiries, sharing insights, and fostering mutual improvement.

Figure 0-6 \u00a0 Comment Section Example

"},{"location":"chapter_preface/suggestions/#025-algorithm-learning-path","title":"0.2.5 \u00a0 Algorithm Learning Path","text":"

Overall, the journey of mastering data structures and algorithms can be divided into three stages:

  1. Stage 1: Introduction to algorithms. We need to familiarize ourselves with the characteristics and usage of various data structures and learn about the principles, processes, uses, and efficiency of different algorithms.
  2. Stage 2: Practicing algorithm problems. It is recommended to start from popular problems, such as Sword for Offer and LeetCode Hot 100, and accumulate at least 100 questions to familiarize yourself with mainstream algorithmic problems. Forgetfulness can be a challenge when you start practicing, but rest assured that this is normal. We can follow the \"Ebbinghaus Forgetting Curve\" to review the questions, and usually after 3~5 rounds of repetitions, we will be able to memorize them.
  3. Stage 3: Building the knowledge system. In terms of learning, we can read algorithm column articles, solution frameworks, and algorithm textbooks to continuously enrich the knowledge system. In terms of practicing, we can try advanced strategies, such as categorizing by topic, multiple solutions for a single problem, and one solution for multiple problems, etc. Insights on these strategies can be found in various communities.

As shown in the Figure 0-7 , this book mainly covers \u201cStage 1,\u201d aiming to help you more efficiently embark on Stages 2 and 3.

Figure 0-7 \u00a0 Algorithm Learning Path

"},{"location":"chapter_preface/summary/","title":"0.3 \u00a0 Summary","text":"
  • The main audience of this book is beginners in algorithm. If you already have some basic knowledge, this book can help you systematically review your algorithm knowledge, and the source code in this book can also be used as a \"Coding Toolkit\".
  • The book consists of three main sections, Complexity Analysis, Data Structures, and Algorithms, covering most of the topics in the field.
  • For newcomers to algorithms, it is crucial to read an introductory book in the beginning stages to avoid many detours or common pitfalls.
  • Animations and figures within the book are usually used to introduce key points and difficult knowledge. These should be given more attention when reading the book.
  • Practice is the best way to learn programming. It is highly recommended that you run the source code and type in the code yourself.
  • Each chapter in the web version of this book features a discussion section, and you are welcome to share your questions and insights at any time.
"},{"location":"chapter_stack_and_queue/","title":"Chapter 5. \u00a0 Stack and Queue","text":"

Abstract

Stacks are like stacking cats, while queues are like cats lining up.

They respectively represent the logical relationships of Last-In-First-Out (LIFO) and First-In-First-Out (FIFO).

"},{"location":"chapter_stack_and_queue/#chapter-contents","title":"Chapter Contents","text":"
  • 5.1 \u00a0 Stack
  • 5.2 \u00a0 Queue
  • 5.3 \u00a0 Double-ended Queue
  • 5.4 \u00a0 Summary
"},{"location":"chapter_stack_and_queue/deque/","title":"5.3 \u00a0 Double-Ended Queue","text":"

In a regular queue, we can only delete elements from the head or add elements to the tail. As shown in the Figure 5-7 , a \"double-ended queue (deque)\" offers more flexibility, allowing the addition or removal of elements at both the head and the tail.

Figure 5-7 \u00a0 Operations in Double-Ended Queue

"},{"location":"chapter_stack_and_queue/deque/#531-common-operations-in-double-ended-queue","title":"5.3.1 \u00a0 Common Operations in Double-Ended Queue","text":"

The common operations in a double-ended queue are listed below, and the specific method names depend on the programming language used.

Table 5-3 \u00a0 Efficiency of Double-Ended Queue Operations

Method Name Description Time Complexity pushFirst() Add an element to the front \\(O(1)\\) pushLast() Add an element to the rear \\(O(1)\\) popFirst() Remove the front element \\(O(1)\\) popLast() Remove the rear element \\(O(1)\\) peekFirst() Access the front element \\(O(1)\\) peekLast() Access the rear element \\(O(1)\\)

Similarly, we can directly use the double-ended queue classes implemented in programming languages:

PythonC++JavaC#GoSwiftJSTSDartRustCZig deque.py
from collections import deque\n\n# Initialize the deque\ndeque: deque[int] = deque()\n\n# Enqueue elements\ndeque.append(2)      # Add to the rear\ndeque.append(5)\ndeque.append(4)\ndeque.appendleft(3)  # Add to the front\ndeque.appendleft(1)\n\n# Access elements\nfront: int = deque[0]  # Front element\nrear: int = deque[-1]  # Rear element\n\n# Dequeue elements\npop_front: int = deque.popleft()  # Front element dequeued\npop_rear: int = deque.pop()       # Rear element dequeued\n\n# Get the length of the deque\nsize: int = len(deque)\n\n# Check if the deque is empty\nis_empty: bool = len(deque) == 0\n
deque.cpp
/* Initialize the deque */\ndeque<int> deque;\n\n/* Enqueue elements */\ndeque.push_back(2);   // Add to the rear\ndeque.push_back(5);\ndeque.push_back(4);\ndeque.push_front(3);  // Add to the front\ndeque.push_front(1);\n\n/* Access elements */\nint front = deque.front(); // Front element\nint back = deque.back();   // Rear element\n\n/* Dequeue elements */\ndeque.pop_front();  // Front element dequeued\ndeque.pop_back();   // Rear element dequeued\n\n/* Get the length of the deque */\nint size = deque.size();\n\n/* Check if the deque is empty */\nbool empty = deque.empty();\n
deque.java
/* Initialize the deque */\nDeque<Integer> deque = new LinkedList<>();\n\n/* Enqueue elements */\ndeque.offerLast(2);   // Add to the rear\ndeque.offerLast(5);\ndeque.offerLast(4);\ndeque.offerFirst(3);  // Add to the front\ndeque.offerFirst(1);\n\n/* Access elements */\nint peekFirst = deque.peekFirst();  // Front element\nint peekLast = deque.peekLast();    // Rear element\n\n/* Dequeue elements */\nint popFirst = deque.pollFirst();  // Front element dequeued\nint popLast = deque.pollLast();    // Rear element dequeued\n\n/* Get the length of the deque */\nint size = deque.size();\n\n/* Check if the deque is empty */\nboolean isEmpty = deque.isEmpty();\n
deque.cs
/* Initialize the deque */\n// In C#, LinkedList is used as a deque\nLinkedList<int> deque = new();\n\n/* Enqueue elements */\ndeque.AddLast(2);   // Add to the rear\ndeque.AddLast(5);\ndeque.AddLast(4);\ndeque.AddFirst(3);  // Add to the front\ndeque.AddFirst(1);\n\n/* Access elements */\nint peekFirst = deque.First.Value;  // Front element\nint peekLast = deque.Last.Value;    // Rear element\n\n/* Dequeue elements */\ndeque.RemoveFirst();  // Front element dequeued\ndeque.RemoveLast();   // Rear element dequeued\n\n/* Get the length of the deque */\nint size = deque.Count;\n\n/* Check if the deque is empty */\nbool isEmpty = deque.Count == 0;\n
deque_test.go
/* Initialize the deque */\n// In Go, use list as a deque\ndeque := list.New()\n\n/* Enqueue elements */\ndeque.PushBack(2)      // Add to the rear\ndeque.PushBack(5)\ndeque.PushBack(4)\ndeque.PushFront(3)     // Add to the front\ndeque.PushFront(1)\n\n/* Access elements */\nfront := deque.Front() // Front element\nrear := deque.Back()   // Rear element\n\n/* Dequeue elements */\ndeque.Remove(front)    // Front element dequeued\ndeque.Remove(rear)     // Rear element dequeued\n\n/* Get the length of the deque */\nsize := deque.Len()\n\n/* Check if the deque is empty */\nisEmpty := deque.Len() == 0\n
deque.swift
/* Initialize the deque */\n// Swift does not have a built-in deque class, so Array can be used as a deque\nvar deque: [Int] = []\n\n/* Enqueue elements */\ndeque.append(2) // Add to the rear\ndeque.append(5)\ndeque.append(4)\ndeque.insert(3, at: 0) // Add to the front\ndeque.insert(1, at: 0)\n\n/* Access elements */\nlet peekFirst = deque.first! // Front element\nlet peekLast = deque.last!   // Rear element\n\n/* Dequeue elements */\n// Using Array, popFirst has a complexity of O(n)\nlet popFirst = deque.removeFirst() // Front element dequeued\nlet popLast = deque.removeLast()   // Rear element dequeued\n\n/* Get the length of the deque */\nlet size = deque.count\n\n/* Check if the deque is empty */\nlet isEmpty = deque.isEmpty\n
deque.js
/* Initialize the deque */\n// JavaScript does not have a built-in deque, so Array is used as a deque\nconst deque = [];\n\n/* Enqueue elements */\ndeque.push(2);\ndeque.push(5);\ndeque.push(4);\n// Note that unshift() has a time complexity of O(n) as it's an array\ndeque.unshift(3);\ndeque.unshift(1);\n\n/* Access elements */\nconst peekFirst = deque[0]; // Front element\nconst peekLast = deque[deque.length - 1]; // Rear element\n\n/* Dequeue elements */\n// Note that shift() has a time complexity of O(n) as it's an array\nconst popFront = deque.shift(); // Front element dequeued\nconst popBack = deque.pop();    // Rear element dequeued\n\n/* Get the length of the deque */\nconst size = deque.length;\n\n/* Check if the deque is empty */\nconst isEmpty = size === 0;\n
deque.ts
/* Initialize the deque */\n// TypeScript does not have a built-in deque, so Array is used as a deque\nconst deque: number[] = [];\n\n/* Enqueue elements */\ndeque.push(2);\ndeque.push(5);\ndeque.push(4);\n// Note that unshift() has a time complexity of O(n) as it's an array\ndeque.unshift(3);\ndeque.unshift(1);\n\n/* Access elements */\nconst peekFirst: number = deque[0]; // Front element\nconst peekLast: number = deque[deque.length - 1]; // Rear element\n\n/* Dequeue elements */\n// Note that shift() has a time complexity of O(n) as it's an array\nconst popFront: number = deque.shift() as number; // Front element dequeued\nconst popBack: number = deque.pop() as number;    // Rear element dequeued\n\n/* Get the length of the deque */\nconst size: number = deque.length;\n\n/* Check if the deque is empty */\nconst isEmpty: boolean = size === 0;\n
deque.dart
/* Initialize the deque */\n// In Dart, Queue is defined as a deque\nQueue<int> deque = Queue<int>();\n\n/* Enqueue elements */\ndeque.addLast(2);  // Add to the rear\ndeque.addLast(5);\ndeque.addLast(4);\ndeque.addFirst(3); // Add to the front\ndeque.addFirst(1);\n\n/* Access elements */\nint peekFirst = deque.first; // Front element\nint peekLast = deque.last;   // Rear element\n\n/* Dequeue elements */\nint popFirst = deque.removeFirst(); // Front element dequeued\nint popLast = deque.removeLast();   // Rear element dequeued\n\n/* Get the length of the deque */\nint size = deque.length;\n\n/* Check if the deque is empty */\nbool isEmpty = deque.isEmpty;\n
deque.rs
/* Initialize the deque */\nlet mut deque: VecDeque<u32> = VecDeque::new();\n\n/* Enqueue elements */\ndeque.push_back(2);  // Add to the rear\ndeque.push_back(5);\ndeque.push_back(4);\ndeque.push_front(3); // Add to the front\ndeque.push_front(1);\n\n/* Access elements */\nif let Some(front) = deque.front() { // Front element\n}\nif let Some(rear) = deque.back() {   // Rear element\n}\n\n/* Dequeue elements */\nif let Some(pop_front) = deque.pop_front() { // Front element dequeued\n}\nif let Some(pop_rear) = deque.pop_back() {   // Rear element dequeued\n}\n\n/* Get the length of the deque */\nlet size = deque.len();\n\n/* Check if the deque is empty */\nlet is_empty = deque.is_empty();\n
deque.c
// C does not provide a built-in deque\n
deque.zig
\n
Visualizing Code

Full Screen >

"},{"location":"chapter_stack_and_queue/deque/#532-implementing-a-double-ended-queue","title":"5.3.2 \u00a0 Implementing a Double-Ended Queue *","text":"

The implementation of a double-ended queue is similar to that of a regular queue, with the choice of either linked lists or arrays as the underlying data structure.

"},{"location":"chapter_stack_and_queue/deque/#1-implementation-based-on-doubly-linked-list","title":"1. \u00a0 Implementation Based on Doubly Linked List","text":"

Recall from the previous section that we used a regular singly linked list to implement a queue, as it conveniently allows for deleting the head node (corresponding to dequeue operation) and adding new nodes after the tail node (corresponding to enqueue operation).

For a double-ended queue, both the head and the tail can perform enqueue and dequeue operations. In other words, a double-ended queue needs to implement another symmetric direction of operations. For this, we use a \"doubly linked list\" as the underlying data structure of the double-ended queue.

As shown in the Figure 5-8 , we treat the head and tail nodes of the doubly linked list as the front and rear of the double-ended queue, respectively, and implement the functionality to add and remove nodes at both ends.

LinkedListDequepushLast()pushFirst()popLast()popFirst()

Figure 5-8 \u00a0 Implementing Double-Ended Queue with Doubly Linked List for Enqueue and Dequeue Operations

The implementation code is as follows:

PythonC++JavaC#GoSwiftJSTSDartRustCZig linkedlist_deque.py
class ListNode:\n    \"\"\"\u53cc\u5411\u94fe\u8868\u8282\u70b9\"\"\"\n\n    def __init__(self, val: int):\n        \"\"\"\u6784\u9020\u65b9\u6cd5\"\"\"\n        self.val: int = val\n        self.next: ListNode | None = None  # \u540e\u7ee7\u8282\u70b9\u5f15\u7528\n        self.prev: ListNode | None = None  # \u524d\u9a71\u8282\u70b9\u5f15\u7528\n\nclass LinkedListDeque:\n    \"\"\"\u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217\"\"\"\n\n    def __init__(self):\n        \"\"\"\u6784\u9020\u65b9\u6cd5\"\"\"\n        self._front: ListNode | None = None  # \u5934\u8282\u70b9 front\n        self._rear: ListNode | None = None  # \u5c3e\u8282\u70b9 rear\n        self._size: int = 0  # \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n    def size(self) -> int:\n        \"\"\"\u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\"\"\"\n        return self._size\n\n    def is_empty(self) -> bool:\n        \"\"\"\u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a\"\"\"\n        return self.size() == 0\n\n    def push(self, num: int, is_front: bool):\n        \"\"\"\u5165\u961f\u64cd\u4f5c\"\"\"\n        node = ListNode(num)\n        # \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if self.is_empty():\n            self._front = self._rear = node\n        # \u961f\u9996\u5165\u961f\u64cd\u4f5c\n        elif is_front:\n            # \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n            self._front.prev = node\n            node.next = self._front\n            self._front = node  # \u66f4\u65b0\u5934\u8282\u70b9\n        # \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n        else:\n            # \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n            self._rear.next = node\n            node.prev = self._rear\n            self._rear = node  # \u66f4\u65b0\u5c3e\u8282\u70b9\n        self._size += 1  # \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n\n    def push_first(self, num: int):\n        \"\"\"\u961f\u9996\u5165\u961f\"\"\"\n        self.push(num, True)\n\n    def push_last(self, num: int):\n        \"\"\"\u961f\u5c3e\u5165\u961f\"\"\"\n        self.push(num, False)\n\n    def pop(self, is_front: bool) -> int:\n        \"\"\"\u51fa\u961f\u64cd\u4f5c\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\")\n        # \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n        if is_front:\n            val: int = self._front.val  # \u6682\u5b58\u5934\u8282\u70b9\u503c\n            # \u5220\u9664\u5934\u8282\u70b9\n            fnext: ListNode | None = self._front.next\n            if fnext != None:\n                fnext.prev = None\n                self._front.next = None\n            self._front = fnext  # \u66f4\u65b0\u5934\u8282\u70b9\n        # \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n        else:\n            val: int = self._rear.val  # \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n            # \u5220\u9664\u5c3e\u8282\u70b9\n            rprev: ListNode | None = self._rear.prev\n            if rprev != None:\n                rprev.next = None\n                self._rear.prev = None\n            self._rear = rprev  # \u66f4\u65b0\u5c3e\u8282\u70b9\n        self._size -= 1  # \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n        return val\n\n    def pop_first(self) -> int:\n        \"\"\"\u961f\u9996\u51fa\u961f\"\"\"\n        return self.pop(True)\n\n    def pop_last(self) -> int:\n        \"\"\"\u961f\u5c3e\u51fa\u961f\"\"\"\n        return self.pop(False)\n\n    def peek_first(self) -> int:\n        \"\"\"\u8bbf\u95ee\u961f\u9996\u5143\u7d20\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\")\n        return self._front.val\n\n    def peek_last(self) -> int:\n        \"\"\"\u8bbf\u95ee\u961f\u5c3e\u5143\u7d20\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\")\n        return self._rear.val\n\n    def to_array(self) -> list[int]:\n        \"\"\"\u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370\"\"\"\n        node = self._front\n        res = [0] * self.size()\n        for i in range(self.size()):\n            res[i] = node.val\n            node = node.next\n        return res\n
linkedlist_deque.cpp
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\nstruct DoublyListNode {\n    int val;              // \u8282\u70b9\u503c\n    DoublyListNode *next; // \u540e\u7ee7\u8282\u70b9\u6307\u9488\n    DoublyListNode *prev; // \u524d\u9a71\u8282\u70b9\u6307\u9488\n    DoublyListNode(int val) : val(val), prev(nullptr), next(nullptr) {\n    }\n};\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\nclass LinkedListDeque {\n  private:\n    DoublyListNode *front, *rear; // \u5934\u8282\u70b9 front \uff0c\u5c3e\u8282\u70b9 rear\n    int queSize = 0;              // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n  public:\n    /* \u6784\u9020\u65b9\u6cd5 */\n    LinkedListDeque() : front(nullptr), rear(nullptr) {\n    }\n\n    /* \u6790\u6784\u65b9\u6cd5 */\n    ~LinkedListDeque() {\n        // \u904d\u5386\u94fe\u8868\u5220\u9664\u8282\u70b9\uff0c\u91ca\u653e\u5185\u5b58\n        DoublyListNode *pre, *cur = front;\n        while (cur != nullptr) {\n            pre = cur;\n            cur = cur->next;\n            delete pre;\n        }\n    }\n\n    /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6 */\n    int size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    bool isEmpty() {\n        return size() == 0;\n    }\n\n    /* \u5165\u961f\u64cd\u4f5c */\n    void push(int num, bool isFront) {\n        DoublyListNode *node = new DoublyListNode(num);\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if (isEmpty())\n            front = rear = node;\n        // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n        else if (isFront) {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n            front->prev = node;\n            node->next = front;\n            front = node; // \u66f4\u65b0\u5934\u8282\u70b9\n        // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n        } else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n            rear->next = node;\n            node->prev = rear;\n            rear = node; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        queSize++; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n    }\n\n    /* \u961f\u9996\u5165\u961f */\n    void pushFirst(int num) {\n        push(num, true);\n    }\n\n    /* \u961f\u5c3e\u5165\u961f */\n    void pushLast(int num) {\n        push(num, false);\n    }\n\n    /* \u51fa\u961f\u64cd\u4f5c */\n    int pop(bool isFront) {\n        if (isEmpty())\n            throw out_of_range(\"\u961f\u5217\u4e3a\u7a7a\");\n        int val;\n        // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n        if (isFront) {\n            val = front->val; // \u6682\u5b58\u5934\u8282\u70b9\u503c\n            // \u5220\u9664\u5934\u8282\u70b9\n            DoublyListNode *fNext = front->next;\n            if (fNext != nullptr) {\n                fNext->prev = nullptr;\n                front->next = nullptr;\n                delete front;\n            }\n            front = fNext; // \u66f4\u65b0\u5934\u8282\u70b9\n        // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n        } else {\n            val = rear->val; // \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n            // \u5220\u9664\u5c3e\u8282\u70b9\n            DoublyListNode *rPrev = rear->prev;\n            if (rPrev != nullptr) {\n                rPrev->next = nullptr;\n                rear->prev = nullptr;\n                delete rear;\n            }\n            rear = rPrev; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        queSize--; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n        return val;\n    }\n\n    /* \u961f\u9996\u51fa\u961f */\n    int popFirst() {\n        return pop(true);\n    }\n\n    /* \u961f\u5c3e\u51fa\u961f */\n    int popLast() {\n        return pop(false);\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    int peekFirst() {\n        if (isEmpty())\n            throw out_of_range(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\");\n        return front->val;\n    }\n\n    /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n    int peekLast() {\n        if (isEmpty())\n            throw out_of_range(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\");\n        return rear->val;\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370 */\n    vector<int> toVector() {\n        DoublyListNode *node = front;\n        vector<int> res(size());\n        for (int i = 0; i < res.size(); i++) {\n            res[i] = node->val;\n            node = node->next;\n        }\n        return res;\n    }\n};\n
linkedlist_deque.java
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\nclass ListNode {\n    int val; // \u8282\u70b9\u503c\n    ListNode next; // \u540e\u7ee7\u8282\u70b9\u5f15\u7528\n    ListNode prev; // \u524d\u9a71\u8282\u70b9\u5f15\u7528\n\n    ListNode(int val) {\n        this.val = val;\n        prev = next = null;\n    }\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\nclass LinkedListDeque {\n    private ListNode front, rear; // \u5934\u8282\u70b9 front \uff0c\u5c3e\u8282\u70b9 rear\n    private int queSize = 0; // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n    public LinkedListDeque() {\n        front = rear = null;\n    }\n\n    /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6 */\n    public int size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /* \u5165\u961f\u64cd\u4f5c */\n    private void push(int num, boolean isFront) {\n        ListNode node = new ListNode(num);\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if (isEmpty())\n            front = rear = node;\n        // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n        else if (isFront) {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n            front.prev = node;\n            node.next = front;\n            front = node; // \u66f4\u65b0\u5934\u8282\u70b9\n        // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n        } else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n            rear.next = node;\n            node.prev = rear;\n            rear = node; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        queSize++; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n    }\n\n    /* \u961f\u9996\u5165\u961f */\n    public void pushFirst(int num) {\n        push(num, true);\n    }\n\n    /* \u961f\u5c3e\u5165\u961f */\n    public void pushLast(int num) {\n        push(num, false);\n    }\n\n    /* \u51fa\u961f\u64cd\u4f5c */\n    private int pop(boolean isFront) {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        int val;\n        // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n        if (isFront) {\n            val = front.val; // \u6682\u5b58\u5934\u8282\u70b9\u503c\n            // \u5220\u9664\u5934\u8282\u70b9\n            ListNode fNext = front.next;\n            if (fNext != null) {\n                fNext.prev = null;\n                front.next = null;\n            }\n            front = fNext; // \u66f4\u65b0\u5934\u8282\u70b9\n        // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n        } else {\n            val = rear.val; // \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n            // \u5220\u9664\u5c3e\u8282\u70b9\n            ListNode rPrev = rear.prev;\n            if (rPrev != null) {\n                rPrev.next = null;\n                rear.prev = null;\n            }\n            rear = rPrev; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        queSize--; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n        return val;\n    }\n\n    /* \u961f\u9996\u51fa\u961f */\n    public int popFirst() {\n        return pop(true);\n    }\n\n    /* \u961f\u5c3e\u51fa\u961f */\n    public int popLast() {\n        return pop(false);\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    public int peekFirst() {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        return front.val;\n    }\n\n    /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n    public int peekLast() {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        return rear.val;\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370 */\n    public int[] toArray() {\n        ListNode node = front;\n        int[] res = new int[size()];\n        for (int i = 0; i < res.length; i++) {\n            res[i] = node.val;\n            node = node.next;\n        }\n        return res;\n    }\n}\n
linkedlist_deque.cs
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\nclass ListNode(int val) {\n    public int val = val;       // \u8282\u70b9\u503c\n    public ListNode? next = null; // \u540e\u7ee7\u8282\u70b9\u5f15\u7528\n    public ListNode? prev = null; // \u524d\u9a71\u8282\u70b9\u5f15\u7528\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\nclass LinkedListDeque {\n    ListNode? front, rear; // \u5934\u8282\u70b9 front, \u5c3e\u8282\u70b9 rear\n    int queSize = 0;      // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n    public LinkedListDeque() {\n        front = null;\n        rear = null;\n    }\n\n    /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6 */\n    public int Size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    public bool IsEmpty() {\n        return Size() == 0;\n    }\n\n    /* \u5165\u961f\u64cd\u4f5c */\n    void Push(int num, bool isFront) {\n        ListNode node = new(num);\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if (IsEmpty()) {\n            front = node;\n            rear = node;\n        }\n        // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n        else if (isFront) {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n            front!.prev = node;\n            node.next = front;\n            front = node; // \u66f4\u65b0\u5934\u8282\u70b9                           \n        }\n        // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n        else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n            rear!.next = node;\n            node.prev = rear;\n            rear = node;  // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n\n        queSize++; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n    }\n\n    /* \u961f\u9996\u5165\u961f */\n    public void PushFirst(int num) {\n        Push(num, true);\n    }\n\n    /* \u961f\u5c3e\u5165\u961f */\n    public void PushLast(int num) {\n        Push(num, false);\n    }\n\n    /* \u51fa\u961f\u64cd\u4f5c */\n    int? Pop(bool isFront) {\n        if (IsEmpty())\n            throw new Exception();\n        int? val;\n        // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n        if (isFront) {\n            val = front?.val; // \u6682\u5b58\u5934\u8282\u70b9\u503c\n            // \u5220\u9664\u5934\u8282\u70b9\n            ListNode? fNext = front?.next;\n            if (fNext != null) {\n                fNext.prev = null;\n                front!.next = null;\n            }\n            front = fNext;   // \u66f4\u65b0\u5934\u8282\u70b9\n        }\n        // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n        else {\n            val = rear?.val;  // \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n            // \u5220\u9664\u5c3e\u8282\u70b9\n            ListNode? rPrev = rear?.prev;\n            if (rPrev != null) {\n                rPrev.next = null;\n                rear!.prev = null;\n            }\n            rear = rPrev;    // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n\n        queSize--; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n        return val;\n    }\n\n    /* \u961f\u9996\u51fa\u961f */\n    public int? PopFirst() {\n        return Pop(true);\n    }\n\n    /* \u961f\u5c3e\u51fa\u961f */\n    public int? PopLast() {\n        return Pop(false);\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    public int? PeekFirst() {\n        if (IsEmpty())\n            throw new Exception();\n        return front?.val;\n    }\n\n    /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n    public int? PeekLast() {\n        if (IsEmpty())\n            throw new Exception();\n        return rear?.val;\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370 */\n    public int?[] ToArray() {\n        ListNode? node = front;\n        int?[] res = new int?[Size()];\n        for (int i = 0; i < res.Length; i++) {\n            res[i] = node?.val;\n            node = node?.next;\n        }\n\n        return res;\n    }\n}\n
linkedlist_deque.go
/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\ntype linkedListDeque struct {\n    // \u4f7f\u7528\u5185\u7f6e\u5305 list\n    data *list.List\n}\n\n/* \u521d\u59cb\u5316\u53cc\u7aef\u961f\u5217 */\nfunc newLinkedListDeque() *linkedListDeque {\n    return &linkedListDeque{\n        data: list.New(),\n    }\n}\n\n/* \u961f\u9996\u5143\u7d20\u5165\u961f */\nfunc (s *linkedListDeque) pushFirst(value any) {\n    s.data.PushFront(value)\n}\n\n/* \u961f\u5c3e\u5143\u7d20\u5165\u961f */\nfunc (s *linkedListDeque) pushLast(value any) {\n    s.data.PushBack(value)\n}\n\n/* \u961f\u9996\u5143\u7d20\u51fa\u961f */\nfunc (s *linkedListDeque) popFirst() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Front()\n    s.data.Remove(e)\n    return e.Value\n}\n\n/* \u961f\u5c3e\u5143\u7d20\u51fa\u961f */\nfunc (s *linkedListDeque) popLast() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Back()\n    s.data.Remove(e)\n    return e.Value\n}\n\n/* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\nfunc (s *linkedListDeque) peekFirst() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Front()\n    return e.Value\n}\n\n/* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\nfunc (s *linkedListDeque) peekLast() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Back()\n    return e.Value\n}\n\n/* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\nfunc (s *linkedListDeque) size() int {\n    return s.data.Len()\n}\n\n/* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\nfunc (s *linkedListDeque) isEmpty() bool {\n    return s.data.Len() == 0\n}\n\n/* \u83b7\u53d6 List \u7528\u4e8e\u6253\u5370 */\nfunc (s *linkedListDeque) toList() *list.List {\n    return s.data\n}\n
linkedlist_deque.swift
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\nclass ListNode {\n    var val: Int // \u8282\u70b9\u503c\n    var next: ListNode? // \u540e\u7ee7\u8282\u70b9\u5f15\u7528\n    weak var prev: ListNode? // \u524d\u9a71\u8282\u70b9\u5f15\u7528\n\n    init(val: Int) {\n        self.val = val\n    }\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\nclass LinkedListDeque {\n    private var front: ListNode? // \u5934\u8282\u70b9 front\n    private var rear: ListNode? // \u5c3e\u8282\u70b9 rear\n    private var queSize: Int // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n    init() {\n        queSize = 0\n    }\n\n    /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6 */\n    func size() -> Int {\n        queSize\n    }\n\n    /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    func isEmpty() -> Bool {\n        size() == 0\n    }\n\n    /* \u5165\u961f\u64cd\u4f5c */\n    private func push(num: Int, isFront: Bool) {\n        let node = ListNode(val: num)\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if isEmpty() {\n            front = node\n            rear = node\n        }\n        // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n        else if isFront {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n            front?.prev = node\n            node.next = front\n            front = node // \u66f4\u65b0\u5934\u8282\u70b9\n        }\n        // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n        else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n            rear?.next = node\n            node.prev = rear\n            rear = node // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        queSize += 1 // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n    }\n\n    /* \u961f\u9996\u5165\u961f */\n    func pushFirst(num: Int) {\n        push(num: num, isFront: true)\n    }\n\n    /* \u961f\u5c3e\u5165\u961f */\n    func pushLast(num: Int) {\n        push(num: num, isFront: false)\n    }\n\n    /* \u51fa\u961f\u64cd\u4f5c */\n    private func pop(isFront: Bool) -> Int {\n        if isEmpty() {\n            fatalError(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\")\n        }\n        let val: Int\n        // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n        if isFront {\n            val = front!.val // \u6682\u5b58\u5934\u8282\u70b9\u503c\n            // \u5220\u9664\u5934\u8282\u70b9\n            let fNext = front?.next\n            if fNext != nil {\n                fNext?.prev = nil\n                front?.next = nil\n            }\n            front = fNext // \u66f4\u65b0\u5934\u8282\u70b9\n        }\n        // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n        else {\n            val = rear!.val // \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n            // \u5220\u9664\u5c3e\u8282\u70b9\n            let rPrev = rear?.prev\n            if rPrev != nil {\n                rPrev?.next = nil\n                rear?.prev = nil\n            }\n            rear = rPrev // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        queSize -= 1 // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n        return val\n    }\n\n    /* \u961f\u9996\u51fa\u961f */\n    func popFirst() -> Int {\n        pop(isFront: true)\n    }\n\n    /* \u961f\u5c3e\u51fa\u961f */\n    func popLast() -> Int {\n        pop(isFront: false)\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    func peekFirst() -> Int? {\n        isEmpty() ? nil : front?.val\n    }\n\n    /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n    func peekLast() -> Int? {\n        isEmpty() ? nil : rear?.val\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370 */\n    func toArray() -> [Int] {\n        var node = front\n        var res = Array(repeating: 0, count: size())\n        for i in res.indices {\n            res[i] = node!.val\n            node = node?.next\n        }\n        return res\n    }\n}\n
linkedlist_deque.js
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\nclass ListNode {\n    prev; // \u524d\u9a71\u8282\u70b9\u5f15\u7528 (\u6307\u9488)\n    next; // \u540e\u7ee7\u8282\u70b9\u5f15\u7528 (\u6307\u9488)\n    val; // \u8282\u70b9\u503c\n\n    constructor(val) {\n        this.val = val;\n        this.next = null;\n        this.prev = null;\n    }\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\nclass LinkedListDeque {\n    #front; // \u5934\u8282\u70b9 front\n    #rear; // \u5c3e\u8282\u70b9 rear\n    #queSize; // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n    constructor() {\n        this.#front = null;\n        this.#rear = null;\n        this.#queSize = 0;\n    }\n\n    /* \u961f\u5c3e\u5165\u961f\u64cd\u4f5c */\n    pushLast(val) {\n        const node = new ListNode(val);\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if (this.#queSize === 0) {\n            this.#front = node;\n            this.#rear = node;\n        } else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n            this.#rear.next = node;\n            node.prev = this.#rear;\n            this.#rear = node; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        this.#queSize++;\n    }\n\n    /* \u961f\u9996\u5165\u961f\u64cd\u4f5c */\n    pushFirst(val) {\n        const node = new ListNode(val);\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if (this.#queSize === 0) {\n            this.#front = node;\n            this.#rear = node;\n        } else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n            this.#front.prev = node;\n            node.next = this.#front;\n            this.#front = node; // \u66f4\u65b0\u5934\u8282\u70b9\n        }\n        this.#queSize++;\n    }\n\n    /* \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c */\n    popLast() {\n        if (this.#queSize === 0) {\n            return null;\n        }\n        const value = this.#rear.val; // \u5b58\u50a8\u5c3e\u8282\u70b9\u503c\n        // \u5220\u9664\u5c3e\u8282\u70b9\n        let temp = this.#rear.prev;\n        if (temp !== null) {\n            temp.next = null;\n            this.#rear.prev = null;\n        }\n        this.#rear = temp; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        this.#queSize--;\n        return value;\n    }\n\n    /* \u961f\u9996\u51fa\u961f\u64cd\u4f5c */\n    popFirst() {\n        if (this.#queSize === 0) {\n            return null;\n        }\n        const value = this.#front.val; // \u5b58\u50a8\u5c3e\u8282\u70b9\u503c\n        // \u5220\u9664\u5934\u8282\u70b9\n        let temp = this.#front.next;\n        if (temp !== null) {\n            temp.prev = null;\n            this.#front.next = null;\n        }\n        this.#front = temp; // \u66f4\u65b0\u5934\u8282\u70b9\n        this.#queSize--;\n        return value;\n    }\n\n    /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n    peekLast() {\n        return this.#queSize === 0 ? null : this.#rear.val;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    peekFirst() {\n        return this.#queSize === 0 ? null : this.#front.val;\n    }\n\n    /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6 */\n    size() {\n        return this.#queSize;\n    }\n\n    /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    isEmpty() {\n        return this.#queSize === 0;\n    }\n\n    /* \u6253\u5370\u53cc\u5411\u961f\u5217 */\n    print() {\n        const arr = [];\n        let temp = this.#front;\n        while (temp !== null) {\n            arr.push(temp.val);\n            temp = temp.next;\n        }\n        console.log('[' + arr.join(', ') + ']');\n    }\n}\n
linkedlist_deque.ts
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\nclass ListNode {\n    prev: ListNode; // \u524d\u9a71\u8282\u70b9\u5f15\u7528 (\u6307\u9488)\n    next: ListNode; // \u540e\u7ee7\u8282\u70b9\u5f15\u7528 (\u6307\u9488)\n    val: number; // \u8282\u70b9\u503c\n\n    constructor(val: number) {\n        this.val = val;\n        this.next = null;\n        this.prev = null;\n    }\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\nclass LinkedListDeque {\n    private front: ListNode; // \u5934\u8282\u70b9 front\n    private rear: ListNode; // \u5c3e\u8282\u70b9 rear\n    private queSize: number; // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n    constructor() {\n        this.front = null;\n        this.rear = null;\n        this.queSize = 0;\n    }\n\n    /* \u961f\u5c3e\u5165\u961f\u64cd\u4f5c */\n    pushLast(val: number): void {\n        const node: ListNode = new ListNode(val);\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if (this.queSize === 0) {\n            this.front = node;\n            this.rear = node;\n        } else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n            this.rear.next = node;\n            node.prev = this.rear;\n            this.rear = node; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        this.queSize++;\n    }\n\n    /* \u961f\u9996\u5165\u961f\u64cd\u4f5c */\n    pushFirst(val: number): void {\n        const node: ListNode = new ListNode(val);\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if (this.queSize === 0) {\n            this.front = node;\n            this.rear = node;\n        } else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n            this.front.prev = node;\n            node.next = this.front;\n            this.front = node; // \u66f4\u65b0\u5934\u8282\u70b9\n        }\n        this.queSize++;\n    }\n\n    /* \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c */\n    popLast(): number {\n        if (this.queSize === 0) {\n            return null;\n        }\n        const value: number = this.rear.val; // \u5b58\u50a8\u5c3e\u8282\u70b9\u503c\n        // \u5220\u9664\u5c3e\u8282\u70b9\n        let temp: ListNode = this.rear.prev;\n        if (temp !== null) {\n            temp.next = null;\n            this.rear.prev = null;\n        }\n        this.rear = temp; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        this.queSize--;\n        return value;\n    }\n\n    /* \u961f\u9996\u51fa\u961f\u64cd\u4f5c */\n    popFirst(): number {\n        if (this.queSize === 0) {\n            return null;\n        }\n        const value: number = this.front.val; // \u5b58\u50a8\u5c3e\u8282\u70b9\u503c\n        // \u5220\u9664\u5934\u8282\u70b9\n        let temp: ListNode = this.front.next;\n        if (temp !== null) {\n            temp.prev = null;\n            this.front.next = null;\n        }\n        this.front = temp; // \u66f4\u65b0\u5934\u8282\u70b9\n        this.queSize--;\n        return value;\n    }\n\n    /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n    peekLast(): number {\n        return this.queSize === 0 ? null : this.rear.val;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    peekFirst(): number {\n        return this.queSize === 0 ? null : this.front.val;\n    }\n\n    /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6 */\n    size(): number {\n        return this.queSize;\n    }\n\n    /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    isEmpty(): boolean {\n        return this.queSize === 0;\n    }\n\n    /* \u6253\u5370\u53cc\u5411\u961f\u5217 */\n    print(): void {\n        const arr: number[] = [];\n        let temp: ListNode = this.front;\n        while (temp !== null) {\n            arr.push(temp.val);\n            temp = temp.next;\n        }\n        console.log('[' + arr.join(', ') + ']');\n    }\n}\n
linkedlist_deque.dart
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\nclass ListNode {\n  int val; // \u8282\u70b9\u503c\n  ListNode? next; // \u540e\u7ee7\u8282\u70b9\u5f15\u7528\n  ListNode? prev; // \u524d\u9a71\u8282\u70b9\u5f15\u7528\n\n  ListNode(this.val, {this.next, this.prev});\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u5bf9\u5217 */\nclass LinkedListDeque {\n  late ListNode? _front; // \u5934\u8282\u70b9 _front\n  late ListNode? _rear; // \u5c3e\u8282\u70b9 _rear\n  int _queSize = 0; // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n  LinkedListDeque() {\n    this._front = null;\n    this._rear = null;\n  }\n\n  /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u957f\u5ea6 */\n  int size() {\n    return this._queSize;\n  }\n\n  /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n  bool isEmpty() {\n    return size() == 0;\n  }\n\n  /* \u5165\u961f\u64cd\u4f5c */\n  void push(int _num, bool isFront) {\n    final ListNode node = ListNode(_num);\n    if (isEmpty()) {\n      // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 _front \u548c _rear \u90fd\u6307\u5411 node\n      _front = _rear = node;\n    } else if (isFront) {\n      // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n      // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n      _front!.prev = node;\n      node.next = _front;\n      _front = node; // \u66f4\u65b0\u5934\u8282\u70b9\n    } else {\n      // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n      // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n      _rear!.next = node;\n      node.prev = _rear;\n      _rear = node; // \u66f4\u65b0\u5c3e\u8282\u70b9\n    }\n    _queSize++; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n  }\n\n  /* \u961f\u9996\u5165\u961f */\n  void pushFirst(int _num) {\n    push(_num, true);\n  }\n\n  /* \u961f\u5c3e\u5165\u961f */\n  void pushLast(int _num) {\n    push(_num, false);\n  }\n\n  /* \u51fa\u961f\u64cd\u4f5c */\n  int? pop(bool isFront) {\n    // \u82e5\u961f\u5217\u4e3a\u7a7a\uff0c\u76f4\u63a5\u8fd4\u56de null\n    if (isEmpty()) {\n      return null;\n    }\n    final int val;\n    if (isFront) {\n      // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n      val = _front!.val; // \u6682\u5b58\u5934\u8282\u70b9\u503c\n      // \u5220\u9664\u5934\u8282\u70b9\n      ListNode? fNext = _front!.next;\n      if (fNext != null) {\n        fNext.prev = null;\n        _front!.next = null;\n      }\n      _front = fNext; // \u66f4\u65b0\u5934\u8282\u70b9\n    } else {\n      // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n      val = _rear!.val; // \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n      // \u5220\u9664\u5c3e\u8282\u70b9\n      ListNode? rPrev = _rear!.prev;\n      if (rPrev != null) {\n        rPrev.next = null;\n        _rear!.prev = null;\n      }\n      _rear = rPrev; // \u66f4\u65b0\u5c3e\u8282\u70b9\n    }\n    _queSize--; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n    return val;\n  }\n\n  /* \u961f\u9996\u51fa\u961f */\n  int? popFirst() {\n    return pop(true);\n  }\n\n  /* \u961f\u5c3e\u51fa\u961f */\n  int? popLast() {\n    return pop(false);\n  }\n\n  /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n  int? peekFirst() {\n    return _front?.val;\n  }\n\n  /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n  int? peekLast() {\n    return _rear?.val;\n  }\n\n  /* \u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370 */\n  List<int> toArray() {\n    ListNode? node = _front;\n    final List<int> res = [];\n    for (int i = 0; i < _queSize; i++) {\n      res.add(node!.val);\n      node = node.next;\n    }\n    return res;\n  }\n}\n
linkedlist_deque.rs
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\npub struct ListNode<T> {\n    pub val: T,                                 // \u8282\u70b9\u503c\n    pub next: Option<Rc<RefCell<ListNode<T>>>>, // \u540e\u7ee7\u8282\u70b9\u6307\u9488\n    pub prev: Option<Rc<RefCell<ListNode<T>>>>, // \u524d\u9a71\u8282\u70b9\u6307\u9488\n}\n\nimpl<T> ListNode<T> {\n    pub fn new(val: T) -> Rc<RefCell<ListNode<T>>> {\n        Rc::new(RefCell::new(ListNode {\n            val,\n            next: None,\n            prev: None,\n        }))\n    }\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\n#[allow(dead_code)]\npub struct LinkedListDeque<T> {\n    front: Option<Rc<RefCell<ListNode<T>>>>,    // \u5934\u8282\u70b9 front\n    rear: Option<Rc<RefCell<ListNode<T>>>>,     // \u5c3e\u8282\u70b9 rear \n    que_size: usize,                            // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n}\n\nimpl<T: Copy> LinkedListDeque<T> {\n    pub fn new() -> Self {\n        Self {\n            front: None,\n            rear: None,\n            que_size: 0, \n        }\n    }\n\n    /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6 */\n    pub fn size(&self) -> usize {\n        return self.que_size;\n    }\n\n    /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    pub fn is_empty(&self) -> bool {\n        return self.size() == 0;\n    }\n\n    /* \u5165\u961f\u64cd\u4f5c */\n    pub fn push(&mut self, num: T, is_front: bool) {\n        let node = ListNode::new(num);\n        // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n        if is_front {\n            match self.front.take() {\n                // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n                None => {\n                    self.rear = Some(node.clone());\n                    self.front = Some(node);\n                }\n                // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n                Some(old_front) => {\n                    old_front.borrow_mut().prev = Some(node.clone());\n                    node.borrow_mut().next = Some(old_front);\n                    self.front = Some(node); // \u66f4\u65b0\u5934\u8282\u70b9\n                }\n            }\n        } \n        // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n        else {\n            match self.rear.take() {\n                // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n                None => {\n                    self.front = Some(node.clone());\n                    self.rear = Some(node);\n                }\n                // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n                Some(old_rear) => {\n                    old_rear.borrow_mut().next = Some(node.clone());\n                    node.borrow_mut().prev = Some(old_rear);\n                    self.rear = Some(node); // \u66f4\u65b0\u5c3e\u8282\u70b9\n                }\n            }\n        }\n        self.que_size += 1; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n    }\n\n    /* \u961f\u9996\u5165\u961f */\n    pub fn push_first(&mut self, num: T) {\n        self.push(num, true);\n    }\n\n    /* \u961f\u5c3e\u5165\u961f */\n    pub fn push_last(&mut self, num: T) {\n        self.push(num, false);\n    }\n\n    /* \u51fa\u961f\u64cd\u4f5c */\n    pub fn pop(&mut self, is_front: bool) -> Option<T> {\n        // \u82e5\u961f\u5217\u4e3a\u7a7a\uff0c\u76f4\u63a5\u8fd4\u56de None\n        if self.is_empty() { \n            return None \n        };\n        // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n        if is_front {\n            self.front.take().map(|old_front| {\n                match old_front.borrow_mut().next.take() {\n                    Some(new_front) => {\n                        new_front.borrow_mut().prev.take();\n                        self.front = Some(new_front);   // \u66f4\u65b0\u5934\u8282\u70b9\n                    }\n                    None => {\n                        self.rear.take();\n                    }\n                }\n                self.que_size -= 1; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n                Rc::try_unwrap(old_front).ok().unwrap().into_inner().val\n            })\n\n        } \n        // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n        else {\n            self.rear.take().map(|old_rear| {\n                match old_rear.borrow_mut().prev.take() {\n                    Some(new_rear) => {\n                        new_rear.borrow_mut().next.take();\n                        self.rear = Some(new_rear);     // \u66f4\u65b0\u5c3e\u8282\u70b9\n                    }\n                    None => {\n                        self.front.take();\n                    }\n                }\n                self.que_size -= 1; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n                Rc::try_unwrap(old_rear).ok().unwrap().into_inner().val\n            })\n        }\n    }\n\n    /* \u961f\u9996\u51fa\u961f */\n    pub fn pop_first(&mut self) -> Option<T> {\n        return self.pop(true);\n    }\n\n    /* \u961f\u5c3e\u51fa\u961f */\n    pub fn pop_last(&mut self) -> Option<T> {\n        return self.pop(false);\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    pub fn peek_first(&self) -> Option<&Rc<RefCell<ListNode<T>>>> {\n        self.front.as_ref()\n    }\n\n    /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n    pub fn peek_last(&self) -> Option<&Rc<RefCell<ListNode<T>>>> {\n        self.rear.as_ref()\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370 */\n    pub fn to_array(&self, head: Option<&Rc<RefCell<ListNode<T>>>>) -> Vec<T> {\n        if let Some(node) = head {\n            let mut nums = self.to_array(node.borrow().next.as_ref());\n            nums.insert(0, node.borrow().val);\n            return nums;\n        }\n        return Vec::new();\n    }\n}\n
linkedlist_deque.c
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\ntypedef struct DoublyListNode {\n    int val;                     // \u8282\u70b9\u503c\n    struct DoublyListNode *next; // \u540e\u7ee7\u8282\u70b9\n    struct DoublyListNode *prev; // \u524d\u9a71\u8282\u70b9\n} DoublyListNode;\n\n/* \u6784\u9020\u51fd\u6570 */\nDoublyListNode *newDoublyListNode(int num) {\n    DoublyListNode *new = (DoublyListNode *)malloc(sizeof(DoublyListNode));\n    new->val = num;\n    new->next = NULL;\n    new->prev = NULL;\n    return new;\n}\n\n/* \u6790\u6784\u51fd\u6570 */\nvoid delDoublyListNode(DoublyListNode *node) {\n    free(node);\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\ntypedef struct {\n    DoublyListNode *front, *rear; // \u5934\u8282\u70b9 front \uff0c\u5c3e\u8282\u70b9 rear\n    int queSize;                  // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n} LinkedListDeque;\n\n/* \u6784\u9020\u51fd\u6570 */\nLinkedListDeque *newLinkedListDeque() {\n    LinkedListDeque *deque = (LinkedListDeque *)malloc(sizeof(LinkedListDeque));\n    deque->front = NULL;\n    deque->rear = NULL;\n    deque->queSize = 0;\n    return deque;\n}\n\n/* \u6790\u6784\u51fd\u6570 */\nvoid delLinkedListdeque(LinkedListDeque *deque) {\n    // \u91ca\u653e\u6240\u6709\u8282\u70b9\n    for (int i = 0; i < deque->queSize && deque->front != NULL; i++) {\n        DoublyListNode *tmp = deque->front;\n        deque->front = deque->front->next;\n        free(tmp);\n    }\n    // \u91ca\u653e deque \u7ed3\u6784\u4f53\n    free(deque);\n}\n\n/* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\nint size(LinkedListDeque *deque) {\n    return deque->queSize;\n}\n\n/* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\nbool empty(LinkedListDeque *deque) {\n    return (size(deque) == 0);\n}\n\n/* \u5165\u961f */\nvoid push(LinkedListDeque *deque, int num, bool isFront) {\n    DoublyListNode *node = newDoublyListNode(num);\n    // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411node\n    if (empty(deque)) {\n        deque->front = deque->rear = node;\n    }\n    // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n    else if (isFront) {\n        // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n        deque->front->prev = node;\n        node->next = deque->front;\n        deque->front = node; // \u66f4\u65b0\u5934\u8282\u70b9\n    }\n    // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n    else {\n        // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n        deque->rear->next = node;\n        node->prev = deque->rear;\n        deque->rear = node;\n    }\n    deque->queSize++; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n}\n\n/* \u961f\u9996\u5165\u961f */\nvoid pushFirst(LinkedListDeque *deque, int num) {\n    push(deque, num, true);\n}\n\n/* \u961f\u5c3e\u5165\u961f */\nvoid pushLast(LinkedListDeque *deque, int num) {\n    push(deque, num, false);\n}\n\n/* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\nint peekFirst(LinkedListDeque *deque) {\n    assert(size(deque) && deque->front);\n    return deque->front->val;\n}\n\n/* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\nint peekLast(LinkedListDeque *deque) {\n    assert(size(deque) && deque->rear);\n    return deque->rear->val;\n}\n\n/* \u51fa\u961f */\nint pop(LinkedListDeque *deque, bool isFront) {\n    if (empty(deque))\n        return -1;\n    int val;\n    // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n    if (isFront) {\n        val = peekFirst(deque); // \u6682\u5b58\u5934\u8282\u70b9\u503c\n        DoublyListNode *fNext = deque->front->next;\n        if (fNext) {\n            fNext->prev = NULL;\n            deque->front->next = NULL;\n            delDoublyListNode(deque->front);\n        }\n        deque->front = fNext; // \u66f4\u65b0\u5934\u8282\u70b9\n    }\n    // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n    else {\n        val = peekLast(deque); // \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n        DoublyListNode *rPrev = deque->rear->prev;\n        if (rPrev) {\n            rPrev->next = NULL;\n            deque->rear->prev = NULL;\n            delDoublyListNode(deque->rear);\n        }\n        deque->rear = rPrev; // \u66f4\u65b0\u5c3e\u8282\u70b9\n    }\n    deque->queSize--; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n    return val;\n}\n\n/* \u961f\u9996\u51fa\u961f */\nint popFirst(LinkedListDeque *deque) {\n    return pop(deque, true);\n}\n\n/* \u961f\u5c3e\u51fa\u961f */\nint popLast(LinkedListDeque *deque) {\n    return pop(deque, false);\n}\n\n/* \u6253\u5370\u961f\u5217 */\nvoid printLinkedListDeque(LinkedListDeque *deque) {\n    int *arr = malloc(sizeof(int) * deque->queSize);\n    // \u62f7\u8d1d\u94fe\u8868\u4e2d\u7684\u6570\u636e\u5230\u6570\u7ec4\n    int i;\n    DoublyListNode *node;\n    for (i = 0, node = deque->front; i < deque->queSize; i++) {\n        arr[i] = node->val;\n        node = node->next;\n    }\n    printArray(arr, deque->queSize);\n    free(arr);\n}\n
linkedlist_deque.zig
// \u53cc\u5411\u94fe\u8868\u8282\u70b9\nfn ListNode(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        val: T = undefined,     // \u8282\u70b9\u503c\n        next: ?*Self = null,    // \u540e\u7ee7\u8282\u70b9\u6307\u9488\n        prev: ?*Self = null,    // \u524d\u9a71\u8282\u70b9\u6307\u9488\n\n        // Initialize a list node with specific value\n        pub fn init(self: *Self, x: i32) void {\n            self.val = x;\n            self.next = null;\n            self.prev = null;\n        }\n    };\n}\n\n// \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217\nfn LinkedListDeque(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        front: ?*ListNode(T) = null,                    // \u5934\u8282\u70b9 front\n        rear: ?*ListNode(T) = null,                     // \u5c3e\u8282\u70b9 rear\n        que_size: usize = 0,                             // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n        mem_arena: ?std.heap.ArenaAllocator = null,\n        mem_allocator: std.mem.Allocator = undefined,   // \u5185\u5b58\u5206\u914d\u5668\n\n        // \u6784\u9020\u51fd\u6570\uff08\u5206\u914d\u5185\u5b58+\u521d\u59cb\u5316\u961f\u5217\uff09\n        pub fn init(self: *Self, allocator: std.mem.Allocator) !void {\n            if (self.mem_arena == null) {\n                self.mem_arena = std.heap.ArenaAllocator.init(allocator);\n                self.mem_allocator = self.mem_arena.?.allocator();\n            }\n            self.front = null;\n            self.rear = null;\n            self.que_size = 0;\n        }\n\n        // \u6790\u6784\u51fd\u6570\uff08\u91ca\u653e\u5185\u5b58\uff09\n        pub fn deinit(self: *Self) void {\n            if (self.mem_arena == null) return;\n            self.mem_arena.?.deinit();\n        }\n\n        // \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n        pub fn size(self: *Self) usize {\n            return self.que_size;\n        }\n\n        // \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a\n        pub fn isEmpty(self: *Self) bool {\n            return self.size() == 0;\n        }\n\n        // \u5165\u961f\u64cd\u4f5c\n        pub fn push(self: *Self, num: T, is_front: bool) !void {\n            var node = try self.mem_allocator.create(ListNode(T));\n            node.init(num);\n            // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n            if (self.isEmpty()) {\n                self.front = node;\n                self.rear = node;\n            // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n            } else if (is_front) {\n                // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n                self.front.?.prev = node;\n                node.next = self.front;\n                self.front = node;  // \u66f4\u65b0\u5934\u8282\u70b9\n            // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n            } else {\n                // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n                self.rear.?.next = node;\n                node.prev = self.rear;\n                self.rear = node;   // \u66f4\u65b0\u5c3e\u8282\u70b9\n            }\n            self.que_size += 1;      // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n        } \n\n        // \u961f\u9996\u5165\u961f\n        pub fn pushFirst(self: *Self, num: T) !void {\n            try self.push(num, true);\n        } \n\n        // \u961f\u5c3e\u5165\u961f\n        pub fn pushLast(self: *Self, num: T) !void {\n            try self.push(num, false);\n        } \n\n        // \u51fa\u961f\u64cd\u4f5c\n        pub fn pop(self: *Self, is_front: bool) T {\n            if (self.isEmpty()) @panic(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\");\n            var val: T = undefined;\n            // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n            if (is_front) {\n                val = self.front.?.val;     // \u6682\u5b58\u5934\u8282\u70b9\u503c\n                // \u5220\u9664\u5934\u8282\u70b9\n                var fNext = self.front.?.next;\n                if (fNext != null) {\n                    fNext.?.prev = null;\n                    self.front.?.next = null;\n                }\n                self.front = fNext;         // \u66f4\u65b0\u5934\u8282\u70b9\n            // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n            } else {\n                val = self.rear.?.val;      // \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n                // \u5220\u9664\u5c3e\u8282\u70b9\n                var rPrev = self.rear.?.prev;\n                if (rPrev != null) {\n                    rPrev.?.next = null;\n                    self.rear.?.prev = null;\n                }\n                self.rear = rPrev;          // \u66f4\u65b0\u5c3e\u8282\u70b9\n            }\n            self.que_size -= 1;              // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n            return val;\n        } \n\n        // \u961f\u9996\u51fa\u961f\n        pub fn popFirst(self: *Self) T {\n            return self.pop(true);\n        } \n\n        // \u961f\u5c3e\u51fa\u961f\n        pub fn popLast(self: *Self) T {\n            return self.pop(false);\n        } \n\n        // \u8bbf\u95ee\u961f\u9996\u5143\u7d20\n        pub fn peekFirst(self: *Self) T {\n            if (self.isEmpty()) @panic(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\");\n            return self.front.?.val;\n        }  \n\n        // \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20\n        pub fn peekLast(self: *Self) T {\n            if (self.isEmpty()) @panic(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\");\n            return self.rear.?.val;\n        }\n\n        // \u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370\n        pub fn toArray(self: *Self) ![]T {\n            var node = self.front;\n            var res = try self.mem_allocator.alloc(T, self.size());\n            @memset(res, @as(T, 0));\n            var i: usize = 0;\n            while (i < res.len) : (i += 1) {\n                res[i] = node.?.val;\n                node = node.?.next;\n            }\n            return res;\n        }\n    };\n}\n
"},{"location":"chapter_stack_and_queue/deque/#2-implementation-based-on-array","title":"2. \u00a0 Implementation Based on Array","text":"

As shown in the Figure 5-9 , similar to implementing a queue with an array, we can also use a circular array to implement a double-ended queue.

ArrayDequepushLast()pushFirst()popLast()popFirst()

Figure 5-9 \u00a0 Implementing Double-Ended Queue with Array for Enqueue and Dequeue Operations

The implementation only needs to add methods for \"front enqueue\" and \"rear dequeue\":

[file]{array_deque}-[func]{}\n
"},{"location":"chapter_stack_and_queue/deque/#533-applications-of-double-ended-queue","title":"5.3.3 \u00a0 Applications of Double-Ended Queue","text":"

The double-ended queue combines the logic of both stacks and queues, thus it can implement all the application scenarios of these two, while offering greater flexibility.

We know that the \"undo\" feature in software is typically implemented using a stack: the system pushes each change operation onto the stack, and then pops to implement undoing. However, considering the limitations of system resources, software often restricts the number of undo steps (for example, only allowing the last 50 steps). When the length of the stack exceeds 50, the software needs to perform a deletion operation at the bottom of the stack (the front of the queue). But a regular stack cannot perform this function, which is where a double-ended queue becomes necessary. Note that the core logic of \"undo\" still follows the Last-In-First-Out principle of a stack, but a double-ended queue can more flexibly implement some additional logic.

"},{"location":"chapter_stack_and_queue/queue/","title":"5.2 \u00a0 Queue","text":"

\"Queue\" is a linear data structure that follows the First-In-First-Out (FIFO) rule. As the name suggests, a queue simulates the phenomenon of lining up, where newcomers join the back of the queue, and people at the front of the queue leave one by one.

As shown in the Figure 5-4 , we call the front of the queue the \"head\" and the back the \"tail.\" The operation of adding elements to the tail of the queue is termed \"enqueue,\" and the operation of removing elements from the head is termed \"dequeue.\"

Figure 5-4 \u00a0 Queue's First-In-First-Out Rule

"},{"location":"chapter_stack_and_queue/queue/#521-common-operations-on-queue","title":"5.2.1 \u00a0 Common Operations on Queue","text":"

The common operations on a queue are shown in the Table 5-2 . Note that method names may vary across different programming languages. Here, we adopt the same naming convention as used for stacks.

Table 5-2 \u00a0 Efficiency of Queue Operations

Method Name Description Time Complexity push() Enqueue an element, add it to the tail \\(O(1)\\) pop() Dequeue the head element \\(O(1)\\) peek() Access the head element \\(O(1)\\)

We can directly use the ready-made queue classes in programming languages:

PythonC++JavaC#GoSwiftJSTSDartRustCZig queue.py
from collections import deque\n\n# Initialize the queue\n# In Python, we generally use the deque class as a queue\n# Although queue.Queue() is a pure queue class, it's not very user-friendly, so it's not recommended\nque: deque[int] = deque()\n\n# Enqueue elements\nque.append(1)\nque.append(3)\nque.append(2)\nque.append(5)\nque.append(4)\n\n# Access the front element\nfront: int = que[0]\n\n# Dequeue an element\npop: int = que.popleft()\n\n# Get the length of the queue\nsize: int = len(que)\n\n# Check if the queue is empty\nis_empty: bool = len(que) == 0\n
queue.cpp
/* Initialize the queue */\nqueue<int> queue;\n\n/* Enqueue elements */\nqueue.push(1);\nqueue.push(3);\nqueue.push(2);\nqueue.push(5);\nqueue.push(4);\n\n/* Access the front element */\nint front = queue.front();\n\n/* Dequeue an element */\nqueue.pop();\n\n/* Get the length of the queue */\nint size = queue.size();\n\n/* Check if the queue is empty */\nbool empty = queue.empty();\n
queue.java
/* Initialize the queue */\nQueue<Integer> queue = new LinkedList<>();\n\n/* Enqueue elements */\nqueue.offer(1);\nqueue.offer(3);\nqueue.offer(2);\nqueue.offer(5);\nqueue.offer(4);\n\n/* Access the front element */\nint peek = queue.peek();\n\n/* Dequeue an element */\nint pop = queue.poll();\n\n/* Get the length of the queue */\nint size = queue.size();\n\n/* Check if the queue is empty */\nboolean isEmpty = queue.isEmpty();\n
queue.cs
/* Initialize the queue */\nQueue<int> queue = new();\n\n/* Enqueue elements */\nqueue.Enqueue(1);\nqueue.Enqueue(3);\nqueue.Enqueue(2);\nqueue.Enqueue(5);\nqueue.Enqueue(4);\n\n/* Access the front element */\nint peek = queue.Peek();\n\n/* Dequeue an element */\nint pop = queue.Dequeue();\n\n/* Get the length of the queue */\nint size = queue.Count;\n\n/* Check if the queue is empty */\nbool isEmpty = queue.Count == 0;\n
queue_test.go
/* Initialize the queue */\n// In Go, use list as a queue\nqueue := list.New()\n\n/* Enqueue elements */\nqueue.PushBack(1)\nqueue.PushBack(3)\nqueue.PushBack(2)\nqueue.PushBack(5)\nqueue.PushBack(4)\n\n/* Access the front element */\npeek := queue.Front()\n\n/* Dequeue an element */\npop := queue.Front()\nqueue.Remove(pop)\n\n/* Get the length of the queue */\nsize := queue.Len()\n\n/* Check if the queue is empty */\nisEmpty := queue.Len() == 0\n
queue.swift
/* Initialize the queue */\n// Swift does not have a built-in queue class, so Array can be used as a queue\nvar queue: [Int] = []\n\n/* Enqueue elements */\nqueue.append(1)\nqueue.append(3)\nqueue.append(2)\nqueue.append(5)\nqueue.append(4)\n\n/* Access the front element */\nlet peek = queue.first!\n\n/* Dequeue an element */\n// Since it's an array, removeFirst has a complexity of O(n)\nlet pool = queue.removeFirst()\n\n/* Get the length of the queue */\nlet size = queue.count\n\n/* Check if the queue is empty */\nlet isEmpty = queue.isEmpty\n
queue.js
/* Initialize the queue */\n// JavaScript does not have a built-in queue, so Array can be used as a queue\nconst queue = [];\n\n/* Enqueue elements */\nqueue.push(1);\nqueue.push(3);\nqueue.push(2);\nqueue.push(5);\nqueue.push(4);\n\n/* Access the front element */\nconst peek = queue[0];\n\n/* Dequeue an element */\n// Since the underlying structure is an array, shift() method has a time complexity of O(n)\nconst pop = queue.shift();\n\n/* Get the length of the queue */\nconst size = queue.length;\n\n/* Check if the queue is empty */\nconst empty = queue.length === 0;\n
queue.ts
/* Initialize the queue */\n// TypeScript does not have a built-in queue, so Array can be used as a queue \nconst queue: number[] = [];\n\n/* Enqueue elements */\nqueue.push(1);\nqueue.push(3);\nqueue.push(2);\nqueue.push(5);\nqueue.push(4);\n\n/* Access the front element */\nconst peek = queue[0];\n\n/* Dequeue an element */\n// Since the underlying structure is an array, shift() method has a time complexity of O(n)\nconst pop = queue.shift();\n\n/* Get the length of the queue */\nconst size = queue.length;\n\n/* Check if the queue is empty */\nconst empty = queue.length === 0;\n
queue.dart
/* Initialize the queue */\n// In Dart, the Queue class is a double-ended queue but can be used as a queue\nQueue<int> queue = Queue();\n\n/* Enqueue elements */\nqueue.add(1);\nqueue.add(3);\nqueue.add(2);\nqueue.add(5);\nqueue.add(4);\n\n/* Access the front element */\nint peek = queue.first;\n\n/* Dequeue an element */\nint pop = queue.removeFirst();\n\n/* Get the length of the queue */\nint size = queue.length;\n\n/* Check if the queue is empty */\nbool isEmpty = queue.isEmpty;\n
queue.rs
/* Initialize the double-ended queue */\n// In Rust, use a double-ended queue as a regular queue\nlet mut deque: VecDeque<u32> = VecDeque::new();\n\n/* Enqueue elements */\ndeque.push_back(1);\ndeque.push_back(3);\ndeque.push_back(2);\ndeque.push_back(5);\ndeque.push_back(4);\n\n/* Access the front element */\nif let Some(front) = deque.front() {\n}\n\n/* Dequeue an element */\nif let Some(pop) = deque.pop_front() {\n}\n\n/* Get the length of the queue */\nlet size = deque.len();\n\n/* Check if the queue is empty */\nlet is_empty = deque.is_empty();\n
queue.c
// C does not provide a built-in queue\n
queue.zig
\n
Visualizing Code

Full Screen >

"},{"location":"chapter_stack_and_queue/queue/#522-implementing-a-queue","title":"5.2.2 \u00a0 Implementing a Queue","text":"

To implement a queue, we need a data structure that allows adding elements at one end and removing them at the other. Both linked lists and arrays meet this requirement.

"},{"location":"chapter_stack_and_queue/queue/#1-implementation-based-on-linked-list","title":"1. \u00a0 Implementation Based on Linked List","text":"

As shown in the Figure 5-5 , we can consider the \"head node\" and \"tail node\" of a linked list as the \"head\" and \"tail\" of the queue, respectively. We restrict the operations so that nodes can only be added at the tail and removed at the head.

LinkedListQueuepush()pop()

Figure 5-5 \u00a0 Implementing Queue with Linked List for Enqueue and Dequeue Operations

Below is the code for implementing a queue using a linked list:

PythonC++JavaC#GoSwiftJSTSDartRustCZig linkedlist_queue.py
class LinkedListQueue:\n    \"\"\"\u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217\"\"\"\n\n    def __init__(self):\n        \"\"\"\u6784\u9020\u65b9\u6cd5\"\"\"\n        self._front: ListNode | None = None  # \u5934\u8282\u70b9 front\n        self._rear: ListNode | None = None  # \u5c3e\u8282\u70b9 rear\n        self._size: int = 0\n\n    def size(self) -> int:\n        \"\"\"\u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6\"\"\"\n        return self._size\n\n    def is_empty(self) -> bool:\n        \"\"\"\u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a\"\"\"\n        return not self._front\n\n    def push(self, num: int):\n        \"\"\"\u5165\u961f\"\"\"\n        # \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        node = ListNode(num)\n        # \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n        if self._front is None:\n            self._front = node\n            self._rear = node\n        # \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n        else:\n            self._rear.next = node\n            self._rear = node\n        self._size += 1\n\n    def pop(self) -> int:\n        \"\"\"\u51fa\u961f\"\"\"\n        num = self.peek()\n        # \u5220\u9664\u5934\u8282\u70b9\n        self._front = self._front.next\n        self._size -= 1\n        return num\n\n    def peek(self) -> int:\n        \"\"\"\u8bbf\u95ee\u961f\u9996\u5143\u7d20\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u961f\u5217\u4e3a\u7a7a\")\n        return self._front.val\n\n    def to_list(self) -> list[int]:\n        \"\"\"\u8f6c\u5316\u4e3a\u5217\u8868\u7528\u4e8e\u6253\u5370\"\"\"\n        queue = []\n        temp = self._front\n        while temp:\n            queue.append(temp.val)\n            temp = temp.next\n        return queue\n
linkedlist_queue.cpp
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\nclass LinkedListQueue {\n  private:\n    ListNode *front, *rear; // \u5934\u8282\u70b9 front \uff0c\u5c3e\u8282\u70b9 rear\n    int queSize;\n\n  public:\n    LinkedListQueue() {\n        front = nullptr;\n        rear = nullptr;\n        queSize = 0;\n    }\n\n    ~LinkedListQueue() {\n        // \u904d\u5386\u94fe\u8868\u5220\u9664\u8282\u70b9\uff0c\u91ca\u653e\u5185\u5b58\n        freeMemoryLinkedList(front);\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    int size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    bool isEmpty() {\n        return queSize == 0;\n    }\n\n    /* \u5165\u961f */\n    void push(int num) {\n        // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        ListNode *node = new ListNode(num);\n        // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n        if (front == nullptr) {\n            front = node;\n            rear = node;\n        }\n        // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n        else {\n            rear->next = node;\n            rear = node;\n        }\n        queSize++;\n    }\n\n    /* \u51fa\u961f */\n    int pop() {\n        int num = peek();\n        // \u5220\u9664\u5934\u8282\u70b9\n        ListNode *tmp = front;\n        front = front->next;\n        // \u91ca\u653e\u5185\u5b58\n        delete tmp;\n        queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    int peek() {\n        if (size() == 0)\n            throw out_of_range(\"\u961f\u5217\u4e3a\u7a7a\");\n        return front->val;\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Vector \u5e76\u8fd4\u56de */\n    vector<int> toVector() {\n        ListNode *node = front;\n        vector<int> res(size());\n        for (int i = 0; i < res.size(); i++) {\n            res[i] = node->val;\n            node = node->next;\n        }\n        return res;\n    }\n};\n
linkedlist_queue.java
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\nclass LinkedListQueue {\n    private ListNode front, rear; // \u5934\u8282\u70b9 front \uff0c\u5c3e\u8282\u70b9 rear\n    private int queSize = 0;\n\n    public LinkedListQueue() {\n        front = null;\n        rear = null;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    public int size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /* \u5165\u961f */\n    public void push(int num) {\n        // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        ListNode node = new ListNode(num);\n        // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n        if (front == null) {\n            front = node;\n            rear = node;\n        // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n        } else {\n            rear.next = node;\n            rear = node;\n        }\n        queSize++;\n    }\n\n    /* \u51fa\u961f */\n    public int pop() {\n        int num = peek();\n        // \u5220\u9664\u5934\u8282\u70b9\n        front = front.next;\n        queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    public int peek() {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        return front.val;\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    public int[] toArray() {\n        ListNode node = front;\n        int[] res = new int[size()];\n        for (int i = 0; i < res.length; i++) {\n            res[i] = node.val;\n            node = node.next;\n        }\n        return res;\n    }\n}\n
linkedlist_queue.cs
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\nclass LinkedListQueue {\n    ListNode? front, rear;  // \u5934\u8282\u70b9 front \uff0c\u5c3e\u8282\u70b9 rear \n    int queSize = 0;\n\n    public LinkedListQueue() {\n        front = null;\n        rear = null;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    public int Size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    public bool IsEmpty() {\n        return Size() == 0;\n    }\n\n    /* \u5165\u961f */\n    public void Push(int num) {\n        // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        ListNode node = new(num);\n        // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n        if (front == null) {\n            front = node;\n            rear = node;\n            // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n        } else if (rear != null) {\n            rear.next = node;\n            rear = node;\n        }\n        queSize++;\n    }\n\n    /* \u51fa\u961f */\n    public int Pop() {\n        int num = Peek();\n        // \u5220\u9664\u5934\u8282\u70b9\n        front = front?.next;\n        queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    public int Peek() {\n        if (IsEmpty())\n            throw new Exception();\n        return front!.val;\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    public int[] ToArray() {\n        if (front == null)\n            return [];\n\n        ListNode? node = front;\n        int[] res = new int[Size()];\n        for (int i = 0; i < res.Length; i++) {\n            res[i] = node!.val;\n            node = node.next;\n        }\n        return res;\n    }\n}\n
linkedlist_queue.go
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\ntype linkedListQueue struct {\n    // \u4f7f\u7528\u5185\u7f6e\u5305 list \u6765\u5b9e\u73b0\u961f\u5217\n    data *list.List\n}\n\n/* \u521d\u59cb\u5316\u961f\u5217 */\nfunc newLinkedListQueue() *linkedListQueue {\n    return &linkedListQueue{\n        data: list.New(),\n    }\n}\n\n/* \u5165\u961f */\nfunc (s *linkedListQueue) push(value any) {\n    s.data.PushBack(value)\n}\n\n/* \u51fa\u961f */\nfunc (s *linkedListQueue) pop() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Front()\n    s.data.Remove(e)\n    return e.Value\n}\n\n/* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\nfunc (s *linkedListQueue) peek() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Front()\n    return e.Value\n}\n\n/* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\nfunc (s *linkedListQueue) size() int {\n    return s.data.Len()\n}\n\n/* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\nfunc (s *linkedListQueue) isEmpty() bool {\n    return s.data.Len() == 0\n}\n\n/* \u83b7\u53d6 List \u7528\u4e8e\u6253\u5370 */\nfunc (s *linkedListQueue) toList() *list.List {\n    return s.data\n}\n
linkedlist_queue.swift
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\nclass LinkedListQueue {\n    private var front: ListNode? // \u5934\u8282\u70b9\n    private var rear: ListNode? // \u5c3e\u8282\u70b9\n    private var _size = 0\n\n    init() {}\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    func size() -> Int {\n        _size\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    func isEmpty() -> Bool {\n        size() == 0\n    }\n\n    /* \u5165\u961f */\n    func push(num: Int) {\n        // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        let node = ListNode(x: num)\n        // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n        if front == nil {\n            front = node\n            rear = node\n        }\n        // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n        else {\n            rear?.next = node\n            rear = node\n        }\n        _size += 1\n    }\n\n    /* \u51fa\u961f */\n    @discardableResult\n    func pop() -> Int {\n        let num = peek()\n        // \u5220\u9664\u5934\u8282\u70b9\n        front = front?.next\n        _size -= 1\n        return num\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    func peek() -> Int {\n        if isEmpty() {\n            fatalError(\"\u961f\u5217\u4e3a\u7a7a\")\n        }\n        return front!.val\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    func toArray() -> [Int] {\n        var node = front\n        var res = Array(repeating: 0, count: size())\n        for i in res.indices {\n            res[i] = node!.val\n            node = node?.next\n        }\n        return res\n    }\n}\n
linkedlist_queue.js
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\nclass LinkedListQueue {\n    #front; // \u5934\u8282\u70b9 #front\n    #rear; // \u5c3e\u8282\u70b9 #rear\n    #queSize = 0;\n\n    constructor() {\n        this.#front = null;\n        this.#rear = null;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    get size() {\n        return this.#queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    isEmpty() {\n        return this.size === 0;\n    }\n\n    /* \u5165\u961f */\n    push(num) {\n        // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        const node = new ListNode(num);\n        // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n        if (!this.#front) {\n            this.#front = node;\n            this.#rear = node;\n            // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n        } else {\n            this.#rear.next = node;\n            this.#rear = node;\n        }\n        this.#queSize++;\n    }\n\n    /* \u51fa\u961f */\n    pop() {\n        const num = this.peek();\n        // \u5220\u9664\u5934\u8282\u70b9\n        this.#front = this.#front.next;\n        this.#queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    peek() {\n        if (this.size === 0) throw new Error('\u961f\u5217\u4e3a\u7a7a');\n        return this.#front.val;\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    toArray() {\n        let node = this.#front;\n        const res = new Array(this.size);\n        for (let i = 0; i < res.length; i++) {\n            res[i] = node.val;\n            node = node.next;\n        }\n        return res;\n    }\n}\n
linkedlist_queue.ts
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\nclass LinkedListQueue {\n    private front: ListNode | null; // \u5934\u8282\u70b9 front\n    private rear: ListNode | null; // \u5c3e\u8282\u70b9 rear\n    private queSize: number = 0;\n\n    constructor() {\n        this.front = null;\n        this.rear = null;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    get size(): number {\n        return this.queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    isEmpty(): boolean {\n        return this.size === 0;\n    }\n\n    /* \u5165\u961f */\n    push(num: number): void {\n        // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        const node = new ListNode(num);\n        // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n        if (!this.front) {\n            this.front = node;\n            this.rear = node;\n            // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n        } else {\n            this.rear!.next = node;\n            this.rear = node;\n        }\n        this.queSize++;\n    }\n\n    /* \u51fa\u961f */\n    pop(): number {\n        const num = this.peek();\n        if (!this.front) throw new Error('\u961f\u5217\u4e3a\u7a7a');\n        // \u5220\u9664\u5934\u8282\u70b9\n        this.front = this.front.next;\n        this.queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    peek(): number {\n        if (this.size === 0) throw new Error('\u961f\u5217\u4e3a\u7a7a');\n        return this.front!.val;\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    toArray(): number[] {\n        let node = this.front;\n        const res = new Array<number>(this.size);\n        for (let i = 0; i < res.length; i++) {\n            res[i] = node!.val;\n            node = node!.next;\n        }\n        return res;\n    }\n}\n
linkedlist_queue.dart
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\nclass LinkedListQueue {\n  ListNode? _front; // \u5934\u8282\u70b9 _front\n  ListNode? _rear; // \u5c3e\u8282\u70b9 _rear\n  int _queSize = 0; // \u961f\u5217\u957f\u5ea6\n\n  LinkedListQueue() {\n    _front = null;\n    _rear = null;\n  }\n\n  /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n  int size() {\n    return _queSize;\n  }\n\n  /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n  bool isEmpty() {\n    return _queSize == 0;\n  }\n\n  /* \u5165\u961f */\n  void push(int _num) {\n    // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 _num\n    final node = ListNode(_num);\n    // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n    if (_front == null) {\n      _front = node;\n      _rear = node;\n    } else {\n      // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n      _rear!.next = node;\n      _rear = node;\n    }\n    _queSize++;\n  }\n\n  /* \u51fa\u961f */\n  int pop() {\n    final int _num = peek();\n    // \u5220\u9664\u5934\u8282\u70b9\n    _front = _front!.next;\n    _queSize--;\n    return _num;\n  }\n\n  /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n  int peek() {\n    if (_queSize == 0) {\n      throw Exception('\u961f\u5217\u4e3a\u7a7a');\n    }\n    return _front!.val;\n  }\n\n  /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n  List<int> toArray() {\n    ListNode? node = _front;\n    final List<int> queue = [];\n    while (node != null) {\n      queue.add(node.val);\n      node = node.next;\n    }\n    return queue;\n  }\n}\n
linkedlist_queue.rs
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\n#[allow(dead_code)]\npub struct LinkedListQueue<T> {\n    front: Option<Rc<RefCell<ListNode<T>>>>,    // \u5934\u8282\u70b9 front\n    rear: Option<Rc<RefCell<ListNode<T>>>>,     // \u5c3e\u8282\u70b9 rear \n    que_size: usize,                            // \u961f\u5217\u7684\u957f\u5ea6\n}\n\nimpl<T: Copy> LinkedListQueue<T> {\n    pub fn new() -> Self {\n        Self {\n            front: None,\n            rear: None,\n            que_size: 0, \n        }\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    pub fn size(&self) -> usize {\n        return self.que_size;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    pub fn is_empty(&self) -> bool {\n        return self.size() == 0;\n    }\n\n    /* \u5165\u961f */\n    pub fn push(&mut self, num: T) {\n        // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        let new_rear = ListNode::new(num);\n        match self.rear.take() {\n            // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n            Some(old_rear) => {\n                old_rear.borrow_mut().next = Some(new_rear.clone());\n                self.rear = Some(new_rear);\n            }\n            // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n            None => {\n                self.front = Some(new_rear.clone());\n                self.rear = Some(new_rear);\n            }\n        }\n        self.que_size += 1;\n    }\n\n    /* \u51fa\u961f */\n    pub fn pop(&mut self) -> Option<T> {\n        self.front.take().map(|old_front| {\n            match old_front.borrow_mut().next.take() {\n                Some(new_front) => {\n                    self.front = Some(new_front);\n                }\n                None => {\n                    self.rear.take();\n                }\n            }\n            self.que_size -= 1;\n            Rc::try_unwrap(old_front).ok().unwrap().into_inner().val\n        })\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    pub fn peek(&self) -> Option<&Rc<RefCell<ListNode<T>>>> {\n        self.front.as_ref()\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    pub fn to_array(&self, head: Option<&Rc<RefCell<ListNode<T>>>>) -> Vec<T> {\n        if let Some(node) = head {\n            let mut nums = self.to_array(node.borrow().next.as_ref());\n            nums.insert(0, node.borrow().val);\n            return nums;\n        }\n        return Vec::new();\n    }\n}\n
linkedlist_queue.c
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\ntypedef struct {\n    ListNode *front, *rear;\n    int queSize;\n} LinkedListQueue;\n\n/* \u6784\u9020\u51fd\u6570 */\nLinkedListQueue *newLinkedListQueue() {\n    LinkedListQueue *queue = (LinkedListQueue *)malloc(sizeof(LinkedListQueue));\n    queue->front = NULL;\n    queue->rear = NULL;\n    queue->queSize = 0;\n    return queue;\n}\n\n/* \u6790\u6784\u51fd\u6570 */\nvoid delLinkedListQueue(LinkedListQueue *queue) {\n    // \u91ca\u653e\u6240\u6709\u8282\u70b9\n    for (int i = 0; i < queue->queSize && queue->front != NULL; i++) {\n        ListNode *tmp = queue->front;\n        queue->front = queue->front->next;\n        free(tmp);\n    }\n    // \u91ca\u653e queue \u7ed3\u6784\u4f53\n    free(queue);\n}\n\n/* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\nint size(LinkedListQueue *queue) {\n    return queue->queSize;\n}\n\n/* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\nbool empty(LinkedListQueue *queue) {\n    return (size(queue) == 0);\n}\n\n/* \u5165\u961f */\nvoid push(LinkedListQueue *queue, int num) {\n    // \u5c3e\u8282\u70b9\u5904\u6dfb\u52a0 node\n    ListNode *node = newListNode(num);\n    // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n    if (queue->front == NULL) {\n        queue->front = node;\n        queue->rear = node;\n    }\n    // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n    else {\n        queue->rear->next = node;\n        queue->rear = node;\n    }\n    queue->queSize++;\n}\n\n/* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\nint peek(LinkedListQueue *queue) {\n    assert(size(queue) && queue->front);\n    return queue->front->val;\n}\n\n/* \u51fa\u961f */\nint pop(LinkedListQueue *queue) {\n    int num = peek(queue);\n    ListNode *tmp = queue->front;\n    queue->front = queue->front->next;\n    free(tmp);\n    queue->queSize--;\n    return num;\n}\n\n/* \u6253\u5370\u961f\u5217 */\nvoid printLinkedListQueue(LinkedListQueue *queue) {\n    int *arr = malloc(sizeof(int) * queue->queSize);\n    // \u62f7\u8d1d\u94fe\u8868\u4e2d\u7684\u6570\u636e\u5230\u6570\u7ec4\n    int i;\n    ListNode *node;\n    for (i = 0, node = queue->front; i < queue->queSize; i++) {\n        arr[i] = node->val;\n        node = node->next;\n    }\n    printArray(arr, queue->queSize);\n    free(arr);\n}\n
linkedlist_queue.zig
// \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217\nfn LinkedListQueue(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        front: ?*inc.ListNode(T) = null,                // \u5934\u8282\u70b9 front\n        rear: ?*inc.ListNode(T) = null,                 // \u5c3e\u8282\u70b9 rear\n        que_size: usize = 0,                            // \u961f\u5217\u7684\u957f\u5ea6\n        mem_arena: ?std.heap.ArenaAllocator = null,\n        mem_allocator: std.mem.Allocator = undefined,   // \u5185\u5b58\u5206\u914d\u5668\n\n        // \u6784\u9020\u51fd\u6570\uff08\u5206\u914d\u5185\u5b58+\u521d\u59cb\u5316\u961f\u5217\uff09\n        pub fn init(self: *Self, allocator: std.mem.Allocator) !void {\n            if (self.mem_arena == null) {\n                self.mem_arena = std.heap.ArenaAllocator.init(allocator);\n                self.mem_allocator = self.mem_arena.?.allocator();\n            }\n            self.front = null;\n            self.rear = null;\n            self.que_size = 0;\n        }\n\n        // \u6790\u6784\u51fd\u6570\uff08\u91ca\u653e\u5185\u5b58\uff09\n        pub fn deinit(self: *Self) void {\n            if (self.mem_arena == null) return;\n            self.mem_arena.?.deinit();\n        }\n\n        // \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6\n        pub fn size(self: *Self) usize {\n            return self.que_size;\n        }\n\n        // \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a\n        pub fn isEmpty(self: *Self) bool {\n            return self.size() == 0;\n        }\n\n        // \u8bbf\u95ee\u961f\u9996\u5143\u7d20\n        pub fn peek(self: *Self) T {\n            if (self.size() == 0) @panic(\"\u961f\u5217\u4e3a\u7a7a\");\n            return self.front.?.val;\n        }  \n\n        // \u5165\u961f\n        pub fn push(self: *Self, num: T) !void {\n            // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n            var node = try self.mem_allocator.create(inc.ListNode(T));\n            node.init(num);\n            // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n            if (self.front == null) {\n                self.front = node;\n                self.rear = node;\n            // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n            } else {\n                self.rear.?.next = node;\n                self.rear = node;\n            }\n            self.que_size += 1;\n        } \n\n        // \u51fa\u961f\n        pub fn pop(self: *Self) T {\n            var num = self.peek();\n            // \u5220\u9664\u5934\u8282\u70b9\n            self.front = self.front.?.next;\n            self.que_size -= 1;\n            return num;\n        } \n\n        // \u5c06\u94fe\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4\n        pub fn toArray(self: *Self) ![]T {\n            var node = self.front;\n            var res = try self.mem_allocator.alloc(T, self.size());\n            @memset(res, @as(T, 0));\n            var i: usize = 0;\n            while (i < res.len) : (i += 1) {\n                res[i] = node.?.val;\n                node = node.?.next;\n            }\n            return res;\n        }\n    };\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_stack_and_queue/queue/#2-implementation-based-on-array","title":"2. \u00a0 Implementation Based on Array","text":"

Deleting the first element in an array has a time complexity of \\(O(n)\\), which would make the dequeue operation inefficient. However, this problem can be cleverly avoided as follows.

We can use a variable front to point to the index of the head element and maintain a size variable to record the length of the queue. Define rear = front + size, which points to the position right after the tail element.

With this design, the effective interval of elements in the array is [front, rear - 1]. The implementation methods for various operations are shown in the Figure 5-6 .

  • Enqueue operation: Assign the input element to the rear index and increase size by 1.
  • Dequeue operation: Simply increase front by 1 and decrease size by 1.

Both enqueue and dequeue operations only require a single operation, each with a time complexity of \\(O(1)\\).

ArrayQueuepush()pop()

Figure 5-6 \u00a0 Implementing Queue with Array for Enqueue and Dequeue Operations

You might notice a problem: as enqueue and dequeue operations are continuously performed, both front and rear move to the right and will eventually reach the end of the array and can't move further. To resolve this issue, we can treat the array as a \"circular array.\"

For a circular array, front or rear needs to loop back to the start of the array upon reaching the end. This cyclical pattern can be achieved with a \"modulo operation,\" as shown in the code below:

PythonC++JavaC#GoSwiftJSTSDartRustCZig array_queue.py
class ArrayQueue:\n    \"\"\"\u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217\"\"\"\n\n    def __init__(self, size: int):\n        \"\"\"\u6784\u9020\u65b9\u6cd5\"\"\"\n        self._nums: list[int] = [0] * size  # \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n        self._front: int = 0  # \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n        self._size: int = 0  # \u961f\u5217\u957f\u5ea6\n\n    def capacity(self) -> int:\n        \"\"\"\u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf\"\"\"\n        return len(self._nums)\n\n    def size(self) -> int:\n        \"\"\"\u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6\"\"\"\n        return self._size\n\n    def is_empty(self) -> bool:\n        \"\"\"\u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a\"\"\"\n        return self._size == 0\n\n    def push(self, num: int):\n        \"\"\"\u5165\u961f\"\"\"\n        if self._size == self.capacity():\n            raise IndexError(\"\u961f\u5217\u5df2\u6ee1\")\n        # \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        # \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        rear: int = (self._front + self._size) % self.capacity()\n        # \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        self._nums[rear] = num\n        self._size += 1\n\n    def pop(self) -> int:\n        \"\"\"\u51fa\u961f\"\"\"\n        num: int = self.peek()\n        # \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        self._front = (self._front + 1) % self.capacity()\n        self._size -= 1\n        return num\n\n    def peek(self) -> int:\n        \"\"\"\u8bbf\u95ee\u961f\u9996\u5143\u7d20\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u961f\u5217\u4e3a\u7a7a\")\n        return self._nums[self._front]\n\n    def to_list(self) -> list[int]:\n        \"\"\"\u8fd4\u56de\u5217\u8868\u7528\u4e8e\u6253\u5370\"\"\"\n        res = [0] * self.size()\n        j: int = self._front\n        for i in range(self.size()):\n            res[i] = self._nums[(j % self.capacity())]\n            j += 1\n        return res\n
array_queue.cpp
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nclass ArrayQueue {\n  private:\n    int *nums;       // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    int front;       // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    int queSize;     // \u961f\u5217\u957f\u5ea6\n    int queCapacity; // \u961f\u5217\u5bb9\u91cf\n\n  public:\n    ArrayQueue(int capacity) {\n        // \u521d\u59cb\u5316\u6570\u7ec4\n        nums = new int[capacity];\n        queCapacity = capacity;\n        front = queSize = 0;\n    }\n\n    ~ArrayQueue() {\n        delete[] nums;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n    int capacity() {\n        return queCapacity;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    int size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    bool isEmpty() {\n        return size() == 0;\n    }\n\n    /* \u5165\u961f */\n    void push(int num) {\n        if (queSize == queCapacity) {\n            cout << \"\u961f\u5217\u5df2\u6ee1\" << endl;\n            return;\n        }\n        // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        int rear = (front + queSize) % queCapacity;\n        // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        nums[rear] = num;\n        queSize++;\n    }\n\n    /* \u51fa\u961f */\n    int pop() {\n        int num = peek();\n        // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        front = (front + 1) % queCapacity;\n        queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    int peek() {\n        if (isEmpty())\n            throw out_of_range(\"\u961f\u5217\u4e3a\u7a7a\");\n        return nums[front];\n    }\n\n    /* \u5c06\u6570\u7ec4\u8f6c\u5316\u4e3a Vector \u5e76\u8fd4\u56de */\n    vector<int> toVector() {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        vector<int> arr(queSize);\n        for (int i = 0, j = front; i < queSize; i++, j++) {\n            arr[i] = nums[j % queCapacity];\n        }\n        return arr;\n    }\n};\n
array_queue.java
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nclass ArrayQueue {\n    private int[] nums; // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    private int front; // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    private int queSize; // \u961f\u5217\u957f\u5ea6\n\n    public ArrayQueue(int capacity) {\n        nums = new int[capacity];\n        front = queSize = 0;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n    public int capacity() {\n        return nums.length;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    public int size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    public boolean isEmpty() {\n        return queSize == 0;\n    }\n\n    /* \u5165\u961f */\n    public void push(int num) {\n        if (queSize == capacity()) {\n            System.out.println(\"\u961f\u5217\u5df2\u6ee1\");\n            return;\n        }\n        // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        int rear = (front + queSize) % capacity();\n        // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        nums[rear] = num;\n        queSize++;\n    }\n\n    /* \u51fa\u961f */\n    public int pop() {\n        int num = peek();\n        // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        front = (front + 1) % capacity();\n        queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    public int peek() {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        return nums[front];\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4 */\n    public int[] toArray() {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        int[] res = new int[queSize];\n        for (int i = 0, j = front; i < queSize; i++, j++) {\n            res[i] = nums[j % capacity()];\n        }\n        return res;\n    }\n}\n
array_queue.cs
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nclass ArrayQueue {\n    int[] nums;  // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    int front;   // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    int queSize; // \u961f\u5217\u957f\u5ea6\n\n    public ArrayQueue(int capacity) {\n        nums = new int[capacity];\n        front = queSize = 0;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n    int Capacity() {\n        return nums.Length;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    public int Size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    public bool IsEmpty() {\n        return queSize == 0;\n    }\n\n    /* \u5165\u961f */\n    public void Push(int num) {\n        if (queSize == Capacity()) {\n            Console.WriteLine(\"\u961f\u5217\u5df2\u6ee1\");\n            return;\n        }\n        // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        int rear = (front + queSize) % Capacity();\n        // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        nums[rear] = num;\n        queSize++;\n    }\n\n    /* \u51fa\u961f */\n    public int Pop() {\n        int num = Peek();\n        // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        front = (front + 1) % Capacity();\n        queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    public int Peek() {\n        if (IsEmpty())\n            throw new Exception();\n        return nums[front];\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4 */\n    public int[] ToArray() {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        int[] res = new int[queSize];\n        for (int i = 0, j = front; i < queSize; i++, j++) {\n            res[i] = nums[j % this.Capacity()];\n        }\n        return res;\n    }\n}\n
array_queue.go
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\ntype arrayQueue struct {\n    nums        []int // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    front       int   // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    queSize     int   // \u961f\u5217\u957f\u5ea6\n    queCapacity int   // \u961f\u5217\u5bb9\u91cf\uff08\u5373\u6700\u5927\u5bb9\u7eb3\u5143\u7d20\u6570\u91cf\uff09\n}\n\n/* \u521d\u59cb\u5316\u961f\u5217 */\nfunc newArrayQueue(queCapacity int) *arrayQueue {\n    return &arrayQueue{\n        nums:        make([]int, queCapacity),\n        queCapacity: queCapacity,\n        front:       0,\n        queSize:     0,\n    }\n}\n\n/* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\nfunc (q *arrayQueue) size() int {\n    return q.queSize\n}\n\n/* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\nfunc (q *arrayQueue) isEmpty() bool {\n    return q.queSize == 0\n}\n\n/* \u5165\u961f */\nfunc (q *arrayQueue) push(num int) {\n    // \u5f53 rear == queCapacity \u8868\u793a\u961f\u5217\u5df2\u6ee1\n    if q.queSize == q.queCapacity {\n        return\n    }\n    // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n    // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n    rear := (q.front + q.queSize) % q.queCapacity\n    // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n    q.nums[rear] = num\n    q.queSize++\n}\n\n/* \u51fa\u961f */\nfunc (q *arrayQueue) pop() any {\n    num := q.peek()\n    // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n    q.front = (q.front + 1) % q.queCapacity\n    q.queSize--\n    return num\n}\n\n/* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\nfunc (q *arrayQueue) peek() any {\n    if q.isEmpty() {\n        return nil\n    }\n    return q.nums[q.front]\n}\n\n/* \u83b7\u53d6 Slice \u7528\u4e8e\u6253\u5370 */\nfunc (q *arrayQueue) toSlice() []int {\n    rear := (q.front + q.queSize)\n    if rear >= q.queCapacity {\n        rear %= q.queCapacity\n        return append(q.nums[q.front:], q.nums[:rear]...)\n    }\n    return q.nums[q.front:rear]\n}\n
array_queue.swift
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nclass ArrayQueue {\n    private var nums: [Int] // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    private var front = 0 // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    private var queSize = 0 // \u961f\u5217\u957f\u5ea6\n\n    init(capacity: Int) {\n        // \u521d\u59cb\u5316\u6570\u7ec4\n        nums = Array(repeating: 0, count: capacity)\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n    func capacity() -> Int {\n        nums.count\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    func size() -> Int {\n        queSize\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    func isEmpty() -> Bool {\n        queSize == 0\n    }\n\n    /* \u5165\u961f */\n    func push(num: Int) {\n        if size() == capacity() {\n            print(\"\u961f\u5217\u5df2\u6ee1\")\n            return\n        }\n        // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        let rear = (front + queSize) % capacity()\n        // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        nums[rear] = num\n        queSize += 1\n    }\n\n    /* \u51fa\u961f */\n    @discardableResult\n    func pop() -> Int {\n        let num = peek()\n        // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        front = (front + 1) % capacity()\n        queSize -= 1\n        return num\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    func peek() -> Int {\n        if isEmpty() {\n            fatalError(\"\u961f\u5217\u4e3a\u7a7a\")\n        }\n        return nums[front]\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4 */\n    func toArray() -> [Int] {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        var res = Array(repeating: 0, count: queSize)\n        for (i, j) in sequence(first: (0, front), next: { $0 < self.queSize - 1 ? ($0 + 1, $1 + 1) : nil }) {\n            res[i] = nums[j % capacity()]\n        }\n        return res\n    }\n}\n
array_queue.js
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nclass ArrayQueue {\n    #nums; // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    #front = 0; // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    #queSize = 0; // \u961f\u5217\u957f\u5ea6\n\n    constructor(capacity) {\n        this.#nums = new Array(capacity);\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n    get capacity() {\n        return this.#nums.length;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    get size() {\n        return this.#queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    isEmpty() {\n        return this.#queSize === 0;\n    }\n\n    /* \u5165\u961f */\n    push(num) {\n        if (this.size === this.capacity) {\n            console.log('\u961f\u5217\u5df2\u6ee1');\n            return;\n        }\n        // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        const rear = (this.#front + this.size) % this.capacity;\n        // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        this.#nums[rear] = num;\n        this.#queSize++;\n    }\n\n    /* \u51fa\u961f */\n    pop() {\n        const num = this.peek();\n        // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        this.#front = (this.#front + 1) % this.capacity;\n        this.#queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    peek() {\n        if (this.isEmpty()) throw new Error('\u961f\u5217\u4e3a\u7a7a');\n        return this.#nums[this.#front];\n    }\n\n    /* \u8fd4\u56de Array */\n    toArray() {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        const arr = new Array(this.size);\n        for (let i = 0, j = this.#front; i < this.size; i++, j++) {\n            arr[i] = this.#nums[j % this.capacity];\n        }\n        return arr;\n    }\n}\n
array_queue.ts
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nclass ArrayQueue {\n    private nums: number[]; // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    private front: number; // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    private queSize: number; // \u961f\u5217\u957f\u5ea6\n\n    constructor(capacity: number) {\n        this.nums = new Array(capacity);\n        this.front = this.queSize = 0;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n    get capacity(): number {\n        return this.nums.length;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    get size(): number {\n        return this.queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    isEmpty(): boolean {\n        return this.queSize === 0;\n    }\n\n    /* \u5165\u961f */\n    push(num: number): void {\n        if (this.size === this.capacity) {\n            console.log('\u961f\u5217\u5df2\u6ee1');\n            return;\n        }\n        // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        const rear = (this.front + this.queSize) % this.capacity;\n        // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        this.nums[rear] = num;\n        this.queSize++;\n    }\n\n    /* \u51fa\u961f */\n    pop(): number {\n        const num = this.peek();\n        // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        this.front = (this.front + 1) % this.capacity;\n        this.queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    peek(): number {\n        if (this.isEmpty()) throw new Error('\u961f\u5217\u4e3a\u7a7a');\n        return this.nums[this.front];\n    }\n\n    /* \u8fd4\u56de Array */\n    toArray(): number[] {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        const arr = new Array(this.size);\n        for (let i = 0, j = this.front; i < this.size; i++, j++) {\n            arr[i] = this.nums[j % this.capacity];\n        }\n        return arr;\n    }\n}\n
array_queue.dart
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nclass ArrayQueue {\n  late List<int> _nums; // \u7528\u4e8e\u50a8\u5b58\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n  late int _front; // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n  late int _queSize; // \u961f\u5217\u957f\u5ea6\n\n  ArrayQueue(int capacity) {\n    _nums = List.filled(capacity, 0);\n    _front = _queSize = 0;\n  }\n\n  /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n  int capaCity() {\n    return _nums.length;\n  }\n\n  /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n  int size() {\n    return _queSize;\n  }\n\n  /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n  bool isEmpty() {\n    return _queSize == 0;\n  }\n\n  /* \u5165\u961f */\n  void push(int _num) {\n    if (_queSize == capaCity()) {\n      throw Exception(\"\u961f\u5217\u5df2\u6ee1\");\n    }\n    // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n    // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n    int rear = (_front + _queSize) % capaCity();\n    // \u5c06 _num \u6dfb\u52a0\u81f3\u961f\u5c3e\n    _nums[rear] = _num;\n    _queSize++;\n  }\n\n  /* \u51fa\u961f */\n  int pop() {\n    int _num = peek();\n    // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n    _front = (_front + 1) % capaCity();\n    _queSize--;\n    return _num;\n  }\n\n  /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n  int peek() {\n    if (isEmpty()) {\n      throw Exception(\"\u961f\u5217\u4e3a\u7a7a\");\n    }\n    return _nums[_front];\n  }\n\n  /* \u8fd4\u56de Array */\n  List<int> toArray() {\n    // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n    final List<int> res = List.filled(_queSize, 0);\n    for (int i = 0, j = _front; i < _queSize; i++, j++) {\n      res[i] = _nums[j % capaCity()];\n    }\n    return res;\n  }\n}\n
array_queue.rs
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nstruct ArrayQueue {\n    nums: Vec<i32>,     // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    front: i32,         // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    que_size: i32,      // \u961f\u5217\u957f\u5ea6\n    que_capacity: i32,  // \u961f\u5217\u5bb9\u91cf\n}\n\nimpl ArrayQueue {\n    /* \u6784\u9020\u65b9\u6cd5 */\n    fn new(capacity: i32) -> ArrayQueue {\n        ArrayQueue {\n            nums: vec![0; capacity as usize],\n            front: 0,\n            que_size: 0,\n            que_capacity: capacity,\n        }\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n    fn capacity(&self) -> i32 {\n        self.que_capacity\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    fn size(&self) -> i32 {\n        self.que_size\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    fn is_empty(&self) -> bool {\n        self.que_size == 0\n    }\n\n    /* \u5165\u961f */\n    fn push(&mut self, num: i32) {\n        if self.que_size == self.capacity() {\n            println!(\"\u961f\u5217\u5df2\u6ee1\");\n            return;\n        }\n        // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        let rear = (self.front + self.que_size) % self.que_capacity;\n        // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        self.nums[rear as usize] = num;\n        self.que_size += 1;\n    }\n\n    /* \u51fa\u961f */\n    fn pop(&mut self) -> i32 {\n        let num = self.peek();\n        // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        self.front = (self.front + 1) % self.que_capacity;\n        self.que_size -= 1;\n        num\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    fn peek(&self) -> i32 {\n        if self.is_empty() {\n            panic!(\"index out of bounds\");\n        }\n        self.nums[self.front as usize]\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4 */\n    fn to_vector(&self) -> Vec<i32> {\n        let cap = self.que_capacity;\n        let mut j = self.front;\n        let mut arr = vec![0; self.que_size as usize];\n        for i in 0..self.que_size {\n            arr[i as usize] = self.nums[(j % cap) as usize];\n            j += 1;\n        }\n        arr\n    }\n}\n
array_queue.c
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\ntypedef struct {\n    int *nums;       // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    int front;       // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    int queSize;     // \u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e + 1\n    int queCapacity; // \u961f\u5217\u5bb9\u91cf\n} ArrayQueue;\n\n/* \u6784\u9020\u51fd\u6570 */\nArrayQueue *newArrayQueue(int capacity) {\n    ArrayQueue *queue = (ArrayQueue *)malloc(sizeof(ArrayQueue));\n    // \u521d\u59cb\u5316\u6570\u7ec4\n    queue->queCapacity = capacity;\n    queue->nums = (int *)malloc(sizeof(int) * queue->queCapacity);\n    queue->front = queue->queSize = 0;\n    return queue;\n}\n\n/* \u6790\u6784\u51fd\u6570 */\nvoid delArrayQueue(ArrayQueue *queue) {\n    free(queue->nums);\n    free(queue);\n}\n\n/* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\nint capacity(ArrayQueue *queue) {\n    return queue->queCapacity;\n}\n\n/* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\nint size(ArrayQueue *queue) {\n    return queue->queSize;\n}\n\n/* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\nbool empty(ArrayQueue *queue) {\n    return queue->queSize == 0;\n}\n\n/* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\nint peek(ArrayQueue *queue) {\n    assert(size(queue) != 0);\n    return queue->nums[queue->front];\n}\n\n/* \u5165\u961f */\nvoid push(ArrayQueue *queue, int num) {\n    if (size(queue) == capacity(queue)) {\n        printf(\"\u961f\u5217\u5df2\u6ee1\\r\\n\");\n        return;\n    }\n    // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n    // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n    int rear = (queue->front + queue->queSize) % queue->queCapacity;\n    // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n    queue->nums[rear] = num;\n    queue->queSize++;\n}\n\n/* \u51fa\u961f */\nint pop(ArrayQueue *queue) {\n    int num = peek(queue);\n    // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n    queue->front = (queue->front + 1) % queue->queCapacity;\n    queue->queSize--;\n    return num;\n}\n
array_queue.zig
// \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217\nfn ArrayQueue(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        nums: []T = undefined,                          // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4     \n        cap: usize = 0,                                 // \u961f\u5217\u5bb9\u91cf\n        front: usize = 0,                               // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n        queSize: usize = 0,                             // \u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e + 1\n        mem_arena: ?std.heap.ArenaAllocator = null,\n        mem_allocator: std.mem.Allocator = undefined,   // \u5185\u5b58\u5206\u914d\u5668\n\n        // \u6784\u9020\u51fd\u6570\uff08\u5206\u914d\u5185\u5b58+\u521d\u59cb\u5316\u6570\u7ec4\uff09\n        pub fn init(self: *Self, allocator: std.mem.Allocator, cap: usize) !void {\n            if (self.mem_arena == null) {\n                self.mem_arena = std.heap.ArenaAllocator.init(allocator);\n                self.mem_allocator = self.mem_arena.?.allocator();\n            }\n            self.cap = cap;\n            self.nums = try self.mem_allocator.alloc(T, self.cap);\n            @memset(self.nums, @as(T, 0));\n        }\n\n        // \u6790\u6784\u51fd\u6570\uff08\u91ca\u653e\u5185\u5b58\uff09\n        pub fn deinit(self: *Self) void {\n            if (self.mem_arena == null) return;\n            self.mem_arena.?.deinit();\n        }\n\n        // \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf\n        pub fn capacity(self: *Self) usize {\n            return self.cap;\n        }\n\n        // \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6\n        pub fn size(self: *Self) usize {\n            return self.queSize;\n        }\n\n        // \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a\n        pub fn isEmpty(self: *Self) bool {\n            return self.queSize == 0;\n        }\n\n        // \u5165\u961f\n        pub fn push(self: *Self, num: T) !void {\n            if (self.size() == self.capacity()) {\n                std.debug.print(\"\u961f\u5217\u5df2\u6ee1\\n\", .{});\n                return;\n            }\n            // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n            // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n            var rear = (self.front + self.queSize) % self.capacity();\n            // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n            self.nums[rear] = num;\n            self.queSize += 1;\n        } \n\n        // \u51fa\u961f\n        pub fn pop(self: *Self) T {\n            var num = self.peek();\n            // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n            self.front = (self.front + 1) % self.capacity();\n            self.queSize -= 1;\n            return num;\n        } \n\n        // \u8bbf\u95ee\u961f\u9996\u5143\u7d20\n        pub fn peek(self: *Self) T {\n            if (self.isEmpty()) @panic(\"\u961f\u5217\u4e3a\u7a7a\");\n            return self.nums[self.front];\n        } \n\n        // \u8fd4\u56de\u6570\u7ec4\n        pub fn toArray(self: *Self) ![]T {\n            // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n            var res = try self.mem_allocator.alloc(T, self.size());\n            @memset(res, @as(T, 0));\n            var i: usize = 0;\n            var j: usize = self.front;\n            while (i < self.size()) : ({ i += 1; j += 1; }) {\n                res[i] = self.nums[j % self.capacity()];\n            }\n            return res;\n        }\n    };\n}\n
Visualizing Code

Full Screen >

The above implementation of the queue still has limitations: its length is fixed. However, this issue is not difficult to resolve. We can replace the array with a dynamic array to introduce an expansion mechanism. Interested readers can try to implement this themselves.

The comparison of the two implementations is consistent with that of the stack and is not repeated here.

"},{"location":"chapter_stack_and_queue/queue/#523-typical-applications-of-queue","title":"5.2.3 \u00a0 Typical Applications of Queue","text":"
  • Amazon Orders. After shoppers place orders, these orders join a queue, and the system processes them in order. During events like Singles' Day, a massive number of orders are generated in a short time, making high concurrency a key challenge for engineers.
  • Various To-Do Lists. Any scenario requiring a \"first-come, first-served\" functionality, such as a printer's task queue or a restaurant's food delivery queue, can effectively maintain the order of processing with a queue.
"},{"location":"chapter_stack_and_queue/stack/","title":"5.1 \u00a0 Stack","text":"

\"Stack\" is a linear data structure that follows the principle of Last-In-First-Out (LIFO).

We can compare a stack to a pile of plates on a table. To access the bottom plate, one must remove the plates on top. If we replace the plates with various types of elements (such as integers, characters, objects, etc.), we obtain the data structure known as a stack.

As shown in the following figure, we refer to the top of the pile of elements as the \"top of the stack\" and the bottom as the \"bottom of the stack.\" The operation of adding elements to the top of the stack is called \"push,\" and the operation of removing the top element is called \"pop.\"

Figure 5-1 \u00a0 Stack's Last-In-First-Out Rule

"},{"location":"chapter_stack_and_queue/stack/#511-common-operations-on-stack","title":"5.1.1 \u00a0 Common Operations on Stack","text":"

The common operations on a stack are shown in the Table 5-1 . The specific method names depend on the programming language used. Here, we use push(), pop(), and peek() as examples.

Table 5-1 \u00a0 Efficiency of Stack Operations

Method Description Time Complexity push() Push an element onto the stack (add to the top) \\(O(1)\\) pop() Pop the top element from the stack \\(O(1)\\) peek() Access the top element of the stack \\(O(1)\\)

Typically, we can directly use the stack class built into the programming language. However, some languages may not specifically provide a stack class. In these cases, we can use the language's \"array\" or \"linked list\" as a stack and ignore operations that are not related to stack logic in the program.

PythonC++JavaC#GoSwiftJSTSDartRustCZig stack.py
# Initialize the stack\n# Python does not have a built-in stack class, so a list can be used as a stack\nstack: list[int] = []\n\n# Push elements onto the stack\nstack.append(1)\nstack.append(3)\nstack.append(2)\nstack.append(5)\nstack.append(4)\n\n# Access the top element of the stack\npeek: int = stack[-1]\n\n# Pop an element from the stack\npop: int = stack.pop()\n\n# Get the length of the stack\nsize: int = len(stack)\n\n# Check if the stack is empty\nis_empty: bool = len(stack) == 0\n
stack.cpp
/* Initialize the stack */\nstack<int> stack;\n\n/* Push elements onto the stack */\nstack.push(1);\nstack.push(3);\nstack.push(2);\nstack.push(5);\nstack.push(4);\n\n/* Access the top element of the stack */\nint top = stack.top();\n\n/* Pop an element from the stack */\nstack.pop(); // No return value\n\n/* Get the length of the stack */\nint size = stack.size();\n\n/* Check if the stack is empty */\nbool empty = stack.empty();\n
stack.java
/* Initialize the stack */\nStack<Integer> stack = new Stack<>();\n\n/* Push elements onto the stack */\nstack.push(1);\nstack.push(3);\nstack.push(2);\nstack.push(5);\nstack.push(4);\n\n/* Access the top element of the stack */\nint peek = stack.peek();\n\n/* Pop an element from the stack */\nint pop = stack.pop();\n\n/* Get the length of the stack */\nint size = stack.size();\n\n/* Check if the stack is empty */\nboolean isEmpty = stack.isEmpty();\n
stack.cs
/* Initialize the stack */\nStack<int> stack = new();\n\n/* Push elements onto the stack */\nstack.Push(1);\nstack.Push(3);\nstack.Push(2);\nstack.Push(5);\nstack.Push(4);\n\n/* Access the top element of the stack */\nint peek = stack.Peek();\n\n/* Pop an element from the stack */\nint pop = stack.Pop();\n\n/* Get the length of the stack */\nint size = stack.Count;\n\n/* Check if the stack is empty */\nbool isEmpty = stack.Count == 0;\n
stack_test.go
/* Initialize the stack */\n// In Go, it is recommended to use a Slice as a stack\nvar stack []int\n\n/* Push elements onto the stack */\nstack = append(stack, 1)\nstack = append(stack, 3)\nstack = append(stack, 2)\nstack = append(stack, 5)\nstack = append(stack, 4)\n\n/* Access the top element of the stack */\npeek := stack[len(stack)-1]\n\n/* Pop an element from the stack */\npop := stack[len(stack)-1]\nstack = stack[:len(stack)-1]\n\n/* Get the length of the stack */\nsize := len(stack)\n\n/* Check if the stack is empty */\nisEmpty := len(stack) == 0\n
stack.swift
/* Initialize the stack */\n// Swift does not have a built-in stack class, so Array can be used as a stack\nvar stack: [Int] = []\n\n/* Push elements onto the stack */\nstack.append(1)\nstack.append(3)\nstack.append(2)\nstack.append(5)\nstack.append(4)\n\n/* Access the top element of the stack */\nlet peek = stack.last!\n\n/* Pop an element from the stack */\nlet pop = stack.removeLast()\n\n/* Get the length of the stack */\nlet size = stack.count\n\n/* Check if the stack is empty */\nlet isEmpty = stack.isEmpty\n
stack.js
/* Initialize the stack */\n// JavaScript does not have a built-in stack class, so Array can be used as a stack\nconst stack = [];\n\n/* Push elements onto the stack */\nstack.push(1);\nstack.push(3);\nstack.push(2);\nstack.push(5);\nstack.push(4);\n\n/* Access the top element of the stack */\nconst peek = stack[stack.length-1];\n\n/* Pop an element from the stack */\nconst pop = stack.pop();\n\n/* Get the length of the stack */\nconst size = stack.length;\n\n/* Check if the stack is empty */\nconst is_empty = stack.length === 0;\n
stack.ts
/* Initialize the stack */\n// TypeScript does not have a built-in stack class, so Array can be used as a stack\nconst stack: number[] = [];\n\n/* Push elements onto the stack */\nstack.push(1);\nstack.push(3);\nstack.push(2);\nstack.push(5);\nstack.push(4);\n\n/* Access the top element of the stack */\nconst peek = stack[stack.length - 1];\n\n/* Pop an element from the stack */\nconst pop = stack.pop();\n\n/* Get the length of the stack */\nconst size = stack.length;\n\n/* Check if the stack is empty */\nconst is_empty = stack.length === 0;\n
stack.dart
/* Initialize the stack */\n// Dart does not have a built-in stack class, so List can be used as a stack\nList<int> stack = [];\n\n/* Push elements onto the stack */\nstack.add(1);\nstack.add(3);\nstack.add(2);\nstack.add(5);\nstack.add(4);\n\n/* Access the top element of the stack */\nint peek = stack.last;\n\n/* Pop an element from the stack */\nint pop = stack.removeLast();\n\n/* Get the length of the stack */\nint size = stack.length;\n\n/* Check if the stack is empty */\nbool isEmpty = stack.isEmpty;\n
stack.rs
/* Initialize the stack */\n// Use Vec as a stack\nlet mut stack: Vec<i32> = Vec::new();\n\n/* Push elements onto the stack */\nstack.push(1);\nstack.push(3);\nstack.push(2);\nstack.push(5);\nstack.push(4);\n\n/* Access the top element of the stack */\nlet top = stack.last().unwrap();\n\n/* Pop an element from the stack */\nlet pop = stack.pop().unwrap();\n\n/* Get the length of the stack */\nlet size = stack.len();\n\n/* Check if the stack is empty */\nlet is_empty = stack.is_empty();\n
stack.c
// C does not provide a built-in stack\n
stack.zig
\n
Visualizing Code

Full Screen >

"},{"location":"chapter_stack_and_queue/stack/#512-implementing-a-stack","title":"5.1.2 \u00a0 Implementing a Stack","text":"

To understand the mechanics of a stack more deeply, let's try implementing a stack class ourselves.

A stack follows the principle of Last-In-First-Out, which means we can only add or remove elements at the top of the stack. However, both arrays and linked lists allow adding and removing elements at any position, therefore a stack can be seen as a restricted array or linked list. In other words, we can \"mask\" some unrelated operations of arrays or linked lists to make their logic conform to the characteristics of a stack.

"},{"location":"chapter_stack_and_queue/stack/#1-implementation-based-on-linked-list","title":"1. \u00a0 Implementation Based on Linked List","text":"

When implementing a stack using a linked list, we can consider the head node of the list as the top of the stack and the tail node as the bottom of the stack.

As shown in the Figure 5-2 , for the push operation, we simply insert elements at the head of the linked list. This method of node insertion is known as \"head insertion.\" For the pop operation, we just need to remove the head node from the list.

LinkedListStackpush()pop()

Figure 5-2 \u00a0 Implementing Stack with Linked List for Push and Pop Operations

Below is an example code for implementing a stack based on a linked list:

PythonC++JavaC#GoSwiftJSTSDartRustCZig linkedlist_stack.py
class LinkedListStack:\n    \"\"\"\u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808\"\"\"\n\n    def __init__(self):\n        \"\"\"\u6784\u9020\u65b9\u6cd5\"\"\"\n        self._peek: ListNode | None = None\n        self._size: int = 0\n\n    def size(self) -> int:\n        \"\"\"\u83b7\u53d6\u6808\u7684\u957f\u5ea6\"\"\"\n        return self._size\n\n    def is_empty(self) -> bool:\n        \"\"\"\u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a\"\"\"\n        return not self._peek\n\n    def push(self, val: int):\n        \"\"\"\u5165\u6808\"\"\"\n        node = ListNode(val)\n        node.next = self._peek\n        self._peek = node\n        self._size += 1\n\n    def pop(self) -> int:\n        \"\"\"\u51fa\u6808\"\"\"\n        num = self.peek()\n        self._peek = self._peek.next\n        self._size -= 1\n        return num\n\n    def peek(self) -> int:\n        \"\"\"\u8bbf\u95ee\u6808\u9876\u5143\u7d20\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u6808\u4e3a\u7a7a\")\n        return self._peek.val\n\n    def to_list(self) -> list[int]:\n        \"\"\"\u8f6c\u5316\u4e3a\u5217\u8868\u7528\u4e8e\u6253\u5370\"\"\"\n        arr = []\n        node = self._peek\n        while node:\n            arr.append(node.val)\n            node = node.next\n        arr.reverse()\n        return arr\n
linkedlist_stack.cpp
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\nclass LinkedListStack {\n  private:\n    ListNode *stackTop; // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    int stkSize;        // \u6808\u7684\u957f\u5ea6\n\n  public:\n    LinkedListStack() {\n        stackTop = nullptr;\n        stkSize = 0;\n    }\n\n    ~LinkedListStack() {\n        // \u904d\u5386\u94fe\u8868\u5220\u9664\u8282\u70b9\uff0c\u91ca\u653e\u5185\u5b58\n        freeMemoryLinkedList(stackTop);\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    int size() {\n        return stkSize;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    bool isEmpty() {\n        return size() == 0;\n    }\n\n    /* \u5165\u6808 */\n    void push(int num) {\n        ListNode *node = new ListNode(num);\n        node->next = stackTop;\n        stackTop = node;\n        stkSize++;\n    }\n\n    /* \u51fa\u6808 */\n    int pop() {\n        int num = top();\n        ListNode *tmp = stackTop;\n        stackTop = stackTop->next;\n        // \u91ca\u653e\u5185\u5b58\n        delete tmp;\n        stkSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    int top() {\n        if (isEmpty())\n            throw out_of_range(\"\u6808\u4e3a\u7a7a\");\n        return stackTop->val;\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    vector<int> toVector() {\n        ListNode *node = stackTop;\n        vector<int> res(size());\n        for (int i = res.size() - 1; i >= 0; i--) {\n            res[i] = node->val;\n            node = node->next;\n        }\n        return res;\n    }\n};\n
linkedlist_stack.java
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\nclass LinkedListStack {\n    private ListNode stackPeek; // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    private int stkSize = 0; // \u6808\u7684\u957f\u5ea6\n\n    public LinkedListStack() {\n        stackPeek = null;\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    public int size() {\n        return stkSize;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /* \u5165\u6808 */\n    public void push(int num) {\n        ListNode node = new ListNode(num);\n        node.next = stackPeek;\n        stackPeek = node;\n        stkSize++;\n    }\n\n    /* \u51fa\u6808 */\n    public int pop() {\n        int num = peek();\n        stackPeek = stackPeek.next;\n        stkSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    public int peek() {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        return stackPeek.val;\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    public int[] toArray() {\n        ListNode node = stackPeek;\n        int[] res = new int[size()];\n        for (int i = res.length - 1; i >= 0; i--) {\n            res[i] = node.val;\n            node = node.next;\n        }\n        return res;\n    }\n}\n
linkedlist_stack.cs
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\nclass LinkedListStack {\n    ListNode? stackPeek;  // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    int stkSize = 0;   // \u6808\u7684\u957f\u5ea6\n\n    public LinkedListStack() {\n        stackPeek = null;\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    public int Size() {\n        return stkSize;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    public bool IsEmpty() {\n        return Size() == 0;\n    }\n\n    /* \u5165\u6808 */\n    public void Push(int num) {\n        ListNode node = new(num) {\n            next = stackPeek\n        };\n        stackPeek = node;\n        stkSize++;\n    }\n\n    /* \u51fa\u6808 */\n    public int Pop() {\n        int num = Peek();\n        stackPeek = stackPeek!.next;\n        stkSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    public int Peek() {\n        if (IsEmpty())\n            throw new Exception();\n        return stackPeek!.val;\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    public int[] ToArray() {\n        if (stackPeek == null)\n            return [];\n\n        ListNode? node = stackPeek;\n        int[] res = new int[Size()];\n        for (int i = res.Length - 1; i >= 0; i--) {\n            res[i] = node!.val;\n            node = node.next;\n        }\n        return res;\n    }\n}\n
linkedlist_stack.go
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\ntype linkedListStack struct {\n    // \u4f7f\u7528\u5185\u7f6e\u5305 list \u6765\u5b9e\u73b0\u6808\n    data *list.List\n}\n\n/* \u521d\u59cb\u5316\u6808 */\nfunc newLinkedListStack() *linkedListStack {\n    return &linkedListStack{\n        data: list.New(),\n    }\n}\n\n/* \u5165\u6808 */\nfunc (s *linkedListStack) push(value int) {\n    s.data.PushBack(value)\n}\n\n/* \u51fa\u6808 */\nfunc (s *linkedListStack) pop() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Back()\n    s.data.Remove(e)\n    return e.Value\n}\n\n/* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\nfunc (s *linkedListStack) peek() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Back()\n    return e.Value\n}\n\n/* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\nfunc (s *linkedListStack) size() int {\n    return s.data.Len()\n}\n\n/* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\nfunc (s *linkedListStack) isEmpty() bool {\n    return s.data.Len() == 0\n}\n\n/* \u83b7\u53d6 List \u7528\u4e8e\u6253\u5370 */\nfunc (s *linkedListStack) toList() *list.List {\n    return s.data\n}\n
linkedlist_stack.swift
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\nclass LinkedListStack {\n    private var _peek: ListNode? // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    private var _size = 0 // \u6808\u7684\u957f\u5ea6\n\n    init() {}\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    func size() -> Int {\n        _size\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    func isEmpty() -> Bool {\n        size() == 0\n    }\n\n    /* \u5165\u6808 */\n    func push(num: Int) {\n        let node = ListNode(x: num)\n        node.next = _peek\n        _peek = node\n        _size += 1\n    }\n\n    /* \u51fa\u6808 */\n    @discardableResult\n    func pop() -> Int {\n        let num = peek()\n        _peek = _peek?.next\n        _size -= 1\n        return num\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    func peek() -> Int {\n        if isEmpty() {\n            fatalError(\"\u6808\u4e3a\u7a7a\")\n        }\n        return _peek!.val\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    func toArray() -> [Int] {\n        var node = _peek\n        var res = Array(repeating: 0, count: _size)\n        for i in sequence(first: res.count - 1, next: { $0 >= 0 + 1 ? $0 - 1 : nil }) {\n            res[i] = node!.val\n            node = node?.next\n        }\n        return res\n    }\n}\n
linkedlist_stack.js
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\nclass LinkedListStack {\n    #stackPeek; // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    #stkSize = 0; // \u6808\u7684\u957f\u5ea6\n\n    constructor() {\n        this.#stackPeek = null;\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    get size() {\n        return this.#stkSize;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    isEmpty() {\n        return this.size === 0;\n    }\n\n    /* \u5165\u6808 */\n    push(num) {\n        const node = new ListNode(num);\n        node.next = this.#stackPeek;\n        this.#stackPeek = node;\n        this.#stkSize++;\n    }\n\n    /* \u51fa\u6808 */\n    pop() {\n        const num = this.peek();\n        this.#stackPeek = this.#stackPeek.next;\n        this.#stkSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    peek() {\n        if (!this.#stackPeek) throw new Error('\u6808\u4e3a\u7a7a');\n        return this.#stackPeek.val;\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    toArray() {\n        let node = this.#stackPeek;\n        const res = new Array(this.size);\n        for (let i = res.length - 1; i >= 0; i--) {\n            res[i] = node.val;\n            node = node.next;\n        }\n        return res;\n    }\n}\n
linkedlist_stack.ts
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\nclass LinkedListStack {\n    private stackPeek: ListNode | null; // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    private stkSize: number = 0; // \u6808\u7684\u957f\u5ea6\n\n    constructor() {\n        this.stackPeek = null;\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    get size(): number {\n        return this.stkSize;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    isEmpty(): boolean {\n        return this.size === 0;\n    }\n\n    /* \u5165\u6808 */\n    push(num: number): void {\n        const node = new ListNode(num);\n        node.next = this.stackPeek;\n        this.stackPeek = node;\n        this.stkSize++;\n    }\n\n    /* \u51fa\u6808 */\n    pop(): number {\n        const num = this.peek();\n        if (!this.stackPeek) throw new Error('\u6808\u4e3a\u7a7a');\n        this.stackPeek = this.stackPeek.next;\n        this.stkSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    peek(): number {\n        if (!this.stackPeek) throw new Error('\u6808\u4e3a\u7a7a');\n        return this.stackPeek.val;\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    toArray(): number[] {\n        let node = this.stackPeek;\n        const res = new Array<number>(this.size);\n        for (let i = res.length - 1; i >= 0; i--) {\n            res[i] = node!.val;\n            node = node!.next;\n        }\n        return res;\n    }\n}\n
linkedlist_stack.dart
/* \u57fa\u4e8e\u94fe\u8868\u7c7b\u5b9e\u73b0\u7684\u6808 */\nclass LinkedListStack {\n  ListNode? _stackPeek; // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n  int _stkSize = 0; // \u6808\u7684\u957f\u5ea6\n\n  LinkedListStack() {\n    _stackPeek = null;\n  }\n\n  /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n  int size() {\n    return _stkSize;\n  }\n\n  /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n  bool isEmpty() {\n    return _stkSize == 0;\n  }\n\n  /* \u5165\u6808 */\n  void push(int _num) {\n    final ListNode node = ListNode(_num);\n    node.next = _stackPeek;\n    _stackPeek = node;\n    _stkSize++;\n  }\n\n  /* \u51fa\u6808 */\n  int pop() {\n    final int _num = peek();\n    _stackPeek = _stackPeek!.next;\n    _stkSize--;\n    return _num;\n  }\n\n  /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n  int peek() {\n    if (_stackPeek == null) {\n      throw Exception(\"\u6808\u4e3a\u7a7a\");\n    }\n    return _stackPeek!.val;\n  }\n\n  /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a List \u5e76\u8fd4\u56de */\n  List<int> toList() {\n    ListNode? node = _stackPeek;\n    List<int> list = [];\n    while (node != null) {\n      list.add(node.val);\n      node = node.next;\n    }\n    list = list.reversed.toList();\n    return list;\n  }\n}\n
linkedlist_stack.rs
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\n#[allow(dead_code)]\npub struct LinkedListStack<T> {\n    stack_peek: Option<Rc<RefCell<ListNode<T>>>>,   // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    stk_size: usize,                                // \u6808\u7684\u957f\u5ea6\n}\n\nimpl<T: Copy> LinkedListStack<T> {\n    pub fn new() -> Self {\n        Self {\n            stack_peek: None,\n            stk_size: 0,\n        }\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    pub fn size(&self) -> usize {\n        return self.stk_size;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    pub fn is_empty(&self) -> bool {\n        return self.size() == 0;\n    }\n\n    /* \u5165\u6808 */\n    pub fn push(&mut self, num: T) {\n        let node = ListNode::new(num);\n        node.borrow_mut().next = self.stack_peek.take();\n        self.stack_peek = Some(node);\n        self.stk_size += 1;\n    }\n\n    /* \u51fa\u6808 */\n    pub fn pop(&mut self) -> Option<T> {\n        self.stack_peek.take().map(|old_head| {\n            match old_head.borrow_mut().next.take() {\n                Some(new_head) => {\n                    self.stack_peek = Some(new_head);\n                }\n                None => {\n                    self.stack_peek = None;\n                }\n            }\n            self.stk_size -= 1;\n            Rc::try_unwrap(old_head).ok().unwrap().into_inner().val\n        })\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    pub fn peek(&self) -> Option<&Rc<RefCell<ListNode<T>>>> {\n        self.stack_peek.as_ref()\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    pub fn to_array(&self, head: Option<&Rc<RefCell<ListNode<T>>>>) -> Vec<T> {\n        if let Some(node) = head {\n            let mut nums = self.to_array(node.borrow().next.as_ref());\n            nums.push(node.borrow().val);\n            return nums;\n        }\n        return Vec::new();\n    }\n}\n
linkedlist_stack.c
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\ntypedef struct {\n    ListNode *top; // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    int size;      // \u6808\u7684\u957f\u5ea6\n} LinkedListStack;\n\n/* \u6784\u9020\u51fd\u6570 */\nLinkedListStack *newLinkedListStack() {\n    LinkedListStack *s = malloc(sizeof(LinkedListStack));\n    s->top = NULL;\n    s->size = 0;\n    return s;\n}\n\n/* \u6790\u6784\u51fd\u6570 */\nvoid delLinkedListStack(LinkedListStack *s) {\n    while (s->top) {\n        ListNode *n = s->top->next;\n        free(s->top);\n        s->top = n;\n    }\n    free(s);\n}\n\n/* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\nint size(LinkedListStack *s) {\n    return s->size;\n}\n\n/* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\nbool isEmpty(LinkedListStack *s) {\n    return size(s) == 0;\n}\n\n/* \u5165\u6808 */\nvoid push(LinkedListStack *s, int num) {\n    ListNode *node = (ListNode *)malloc(sizeof(ListNode));\n    node->next = s->top; // \u66f4\u65b0\u65b0\u52a0\u8282\u70b9\u6307\u9488\u57df\n    node->val = num;     // \u66f4\u65b0\u65b0\u52a0\u8282\u70b9\u6570\u636e\u57df\n    s->top = node;       // \u66f4\u65b0\u6808\u9876\n    s->size++;           // \u66f4\u65b0\u6808\u5927\u5c0f\n}\n\n/* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\nint peek(LinkedListStack *s) {\n    if (s->size == 0) {\n        printf(\"\u6808\u4e3a\u7a7a\\n\");\n        return INT_MAX;\n    }\n    return s->top->val;\n}\n\n/* \u51fa\u6808 */\nint pop(LinkedListStack *s) {\n    int val = peek(s);\n    ListNode *tmp = s->top;\n    s->top = s->top->next;\n    // \u91ca\u653e\u5185\u5b58\n    free(tmp);\n    s->size--;\n    return val;\n}\n
linkedlist_stack.zig
// \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808\nfn LinkedListStack(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        stack_top: ?*inc.ListNode(T) = null,             // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n        stk_size: usize = 0,                             // \u6808\u7684\u957f\u5ea6\n        mem_arena: ?std.heap.ArenaAllocator = null,\n        mem_allocator: std.mem.Allocator = undefined,    // \u5185\u5b58\u5206\u914d\u5668\n\n        // \u6784\u9020\u51fd\u6570\uff08\u5206\u914d\u5185\u5b58+\u521d\u59cb\u5316\u6808\uff09\n        pub fn init(self: *Self, allocator: std.mem.Allocator) !void {\n            if (self.mem_arena == null) {\n                self.mem_arena = std.heap.ArenaAllocator.init(allocator);\n                self.mem_allocator = self.mem_arena.?.allocator();\n            }\n            self.stack_top = null;\n            self.stk_size = 0;\n        }\n\n        // \u6790\u6784\u51fd\u6570\uff08\u91ca\u653e\u5185\u5b58\uff09\n        pub fn deinit(self: *Self) void {\n            if (self.mem_arena == null) return;\n            self.mem_arena.?.deinit();\n        }\n\n        // \u83b7\u53d6\u6808\u7684\u957f\u5ea6\n        pub fn size(self: *Self) usize {\n            return self.stk_size;\n        }\n\n        // \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a\n        pub fn isEmpty(self: *Self) bool {\n            return self.size() == 0;\n        }\n\n        // \u8bbf\u95ee\u6808\u9876\u5143\u7d20\n        pub fn peek(self: *Self) T {\n            if (self.size() == 0) @panic(\"\u6808\u4e3a\u7a7a\");\n            return self.stack_top.?.val;\n        }  \n\n        // \u5165\u6808\n        pub fn push(self: *Self, num: T) !void {\n            var node = try self.mem_allocator.create(inc.ListNode(T));\n            node.init(num);\n            node.next = self.stack_top;\n            self.stack_top = node;\n            self.stk_size += 1;\n        } \n\n        // \u51fa\u6808\n        pub fn pop(self: *Self) T {\n            var num = self.peek();\n            self.stack_top = self.stack_top.?.next;\n            self.stk_size -= 1;\n            return num;\n        } \n\n        // \u5c06\u6808\u8f6c\u6362\u4e3a\u6570\u7ec4\n        pub fn toArray(self: *Self) ![]T {\n            var node = self.stack_top;\n            var res = try self.mem_allocator.alloc(T, self.size());\n            @memset(res, @as(T, 0));\n            var i: usize = 0;\n            while (i < res.len) : (i += 1) {\n                res[res.len - i - 1] = node.?.val;\n                node = node.?.next;\n            }\n            return res;\n        }\n    };\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_stack_and_queue/stack/#2-implementation-based-on-array","title":"2. \u00a0 Implementation Based on Array","text":"

When implementing a stack using an array, we can consider the end of the array as the top of the stack. As shown in the Figure 5-3 , push and pop operations correspond to adding and removing elements at the end of the array, respectively, both with a time complexity of \\(O(1)\\).

ArrayStackpush()pop()

Figure 5-3 \u00a0 Implementing Stack with Array for Push and Pop Operations

Since the elements to be pushed onto the stack may continuously increase, we can use a dynamic array, thus avoiding the need to handle array expansion ourselves. Here is an example code:

PythonC++JavaC#GoSwiftJSTSDartRustCZig array_stack.py
class ArrayStack:\n    \"\"\"\u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808\"\"\"\n\n    def __init__(self):\n        \"\"\"\u6784\u9020\u65b9\u6cd5\"\"\"\n        self._stack: list[int] = []\n\n    def size(self) -> int:\n        \"\"\"\u83b7\u53d6\u6808\u7684\u957f\u5ea6\"\"\"\n        return len(self._stack)\n\n    def is_empty(self) -> bool:\n        \"\"\"\u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a\"\"\"\n        return self._stack == []\n\n    def push(self, item: int):\n        \"\"\"\u5165\u6808\"\"\"\n        self._stack.append(item)\n\n    def pop(self) -> int:\n        \"\"\"\u51fa\u6808\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u6808\u4e3a\u7a7a\")\n        return self._stack.pop()\n\n    def peek(self) -> int:\n        \"\"\"\u8bbf\u95ee\u6808\u9876\u5143\u7d20\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u6808\u4e3a\u7a7a\")\n        return self._stack[-1]\n\n    def to_list(self) -> list[int]:\n        \"\"\"\u8fd4\u56de\u5217\u8868\u7528\u4e8e\u6253\u5370\"\"\"\n        return self._stack\n
array_stack.cpp
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nclass ArrayStack {\n  private:\n    vector<int> stack;\n\n  public:\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    int size() {\n        return stack.size();\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    bool isEmpty() {\n        return stack.size() == 0;\n    }\n\n    /* \u5165\u6808 */\n    void push(int num) {\n        stack.push_back(num);\n    }\n\n    /* \u51fa\u6808 */\n    int pop() {\n        int num = top();\n        stack.pop_back();\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    int top() {\n        if (isEmpty())\n            throw out_of_range(\"\u6808\u4e3a\u7a7a\");\n        return stack.back();\n    }\n\n    /* \u8fd4\u56de Vector */\n    vector<int> toVector() {\n        return stack;\n    }\n};\n
array_stack.java
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nclass ArrayStack {\n    private ArrayList<Integer> stack;\n\n    public ArrayStack() {\n        // \u521d\u59cb\u5316\u5217\u8868\uff08\u52a8\u6001\u6570\u7ec4\uff09\n        stack = new ArrayList<>();\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    public int size() {\n        return stack.size();\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /* \u5165\u6808 */\n    public void push(int num) {\n        stack.add(num);\n    }\n\n    /* \u51fa\u6808 */\n    public int pop() {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        return stack.remove(size() - 1);\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    public int peek() {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        return stack.get(size() - 1);\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    public Object[] toArray() {\n        return stack.toArray();\n    }\n}\n
array_stack.cs
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nclass ArrayStack {\n    List<int> stack;\n    public ArrayStack() {\n        // \u521d\u59cb\u5316\u5217\u8868\uff08\u52a8\u6001\u6570\u7ec4\uff09\n        stack = [];\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    public int Size() {\n        return stack.Count;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    public bool IsEmpty() {\n        return Size() == 0;\n    }\n\n    /* \u5165\u6808 */\n    public void Push(int num) {\n        stack.Add(num);\n    }\n\n    /* \u51fa\u6808 */\n    public int Pop() {\n        if (IsEmpty())\n            throw new Exception();\n        var val = Peek();\n        stack.RemoveAt(Size() - 1);\n        return val;\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    public int Peek() {\n        if (IsEmpty())\n            throw new Exception();\n        return stack[Size() - 1];\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    public int[] ToArray() {\n        return [.. stack];\n    }\n}\n
array_stack.go
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\ntype arrayStack struct {\n    data []int // \u6570\u636e\n}\n\n/* \u521d\u59cb\u5316\u6808 */\nfunc newArrayStack() *arrayStack {\n    return &arrayStack{\n        // \u8bbe\u7f6e\u6808\u7684\u957f\u5ea6\u4e3a 0\uff0c\u5bb9\u91cf\u4e3a 16\n        data: make([]int, 0, 16),\n    }\n}\n\n/* \u6808\u7684\u957f\u5ea6 */\nfunc (s *arrayStack) size() int {\n    return len(s.data)\n}\n\n/* \u6808\u662f\u5426\u4e3a\u7a7a */\nfunc (s *arrayStack) isEmpty() bool {\n    return s.size() == 0\n}\n\n/* \u5165\u6808 */\nfunc (s *arrayStack) push(v int) {\n    // \u5207\u7247\u4f1a\u81ea\u52a8\u6269\u5bb9\n    s.data = append(s.data, v)\n}\n\n/* \u51fa\u6808 */\nfunc (s *arrayStack) pop() any {\n    val := s.peek()\n    s.data = s.data[:len(s.data)-1]\n    return val\n}\n\n/* \u83b7\u53d6\u6808\u9876\u5143\u7d20 */\nfunc (s *arrayStack) peek() any {\n    if s.isEmpty() {\n        return nil\n    }\n    val := s.data[len(s.data)-1]\n    return val\n}\n\n/* \u83b7\u53d6 Slice \u7528\u4e8e\u6253\u5370 */\nfunc (s *arrayStack) toSlice() []int {\n    return s.data\n}\n
array_stack.swift
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nclass ArrayStack {\n    private var stack: [Int]\n\n    init() {\n        // \u521d\u59cb\u5316\u5217\u8868\uff08\u52a8\u6001\u6570\u7ec4\uff09\n        stack = []\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    func size() -> Int {\n        stack.count\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    func isEmpty() -> Bool {\n        stack.isEmpty\n    }\n\n    /* \u5165\u6808 */\n    func push(num: Int) {\n        stack.append(num)\n    }\n\n    /* \u51fa\u6808 */\n    @discardableResult\n    func pop() -> Int {\n        if isEmpty() {\n            fatalError(\"\u6808\u4e3a\u7a7a\")\n        }\n        return stack.removeLast()\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    func peek() -> Int {\n        if isEmpty() {\n            fatalError(\"\u6808\u4e3a\u7a7a\")\n        }\n        return stack.last!\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    func toArray() -> [Int] {\n        stack\n    }\n}\n
array_stack.js
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nclass ArrayStack {\n    #stack;\n    constructor() {\n        this.#stack = [];\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    get size() {\n        return this.#stack.length;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    isEmpty() {\n        return this.#stack.length === 0;\n    }\n\n    /* \u5165\u6808 */\n    push(num) {\n        this.#stack.push(num);\n    }\n\n    /* \u51fa\u6808 */\n    pop() {\n        if (this.isEmpty()) throw new Error('\u6808\u4e3a\u7a7a');\n        return this.#stack.pop();\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    top() {\n        if (this.isEmpty()) throw new Error('\u6808\u4e3a\u7a7a');\n        return this.#stack[this.#stack.length - 1];\n    }\n\n    /* \u8fd4\u56de Array */\n    toArray() {\n        return this.#stack;\n    }\n}\n
array_stack.ts
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nclass ArrayStack {\n    private stack: number[];\n    constructor() {\n        this.stack = [];\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    get size(): number {\n        return this.stack.length;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    isEmpty(): boolean {\n        return this.stack.length === 0;\n    }\n\n    /* \u5165\u6808 */\n    push(num: number): void {\n        this.stack.push(num);\n    }\n\n    /* \u51fa\u6808 */\n    pop(): number | undefined {\n        if (this.isEmpty()) throw new Error('\u6808\u4e3a\u7a7a');\n        return this.stack.pop();\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    top(): number | undefined {\n        if (this.isEmpty()) throw new Error('\u6808\u4e3a\u7a7a');\n        return this.stack[this.stack.length - 1];\n    }\n\n    /* \u8fd4\u56de Array */\n    toArray() {\n        return this.stack;\n    }\n}\n
array_stack.dart
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nclass ArrayStack {\n  late List<int> _stack;\n  ArrayStack() {\n    _stack = [];\n  }\n\n  /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n  int size() {\n    return _stack.length;\n  }\n\n  /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n  bool isEmpty() {\n    return _stack.isEmpty;\n  }\n\n  /* \u5165\u6808 */\n  void push(int _num) {\n    _stack.add(_num);\n  }\n\n  /* \u51fa\u6808 */\n  int pop() {\n    if (isEmpty()) {\n      throw Exception(\"\u6808\u4e3a\u7a7a\");\n    }\n    return _stack.removeLast();\n  }\n\n  /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n  int peek() {\n    if (isEmpty()) {\n      throw Exception(\"\u6808\u4e3a\u7a7a\");\n    }\n    return _stack.last;\n  }\n\n  /* \u5c06\u6808\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n  List<int> toArray() => _stack;\n}\n
array_stack.rs
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nstruct ArrayStack<T> {\n    stack: Vec<T>,\n}\n\nimpl<T> ArrayStack<T> {\n    /* \u521d\u59cb\u5316\u6808 */\n    fn new() -> ArrayStack<T> {\n        ArrayStack::<T> { stack: Vec::<T>::new() }\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    fn size(&self) -> usize {\n        self.stack.len()\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    fn is_empty(&self) -> bool {\n        self.size() == 0\n    }\n\n    /* \u5165\u6808 */\n    fn push(&mut self, num: T) {\n        self.stack.push(num);\n    }\n\n    /* \u51fa\u6808 */\n    fn pop(&mut self) -> Option<T> {\n        match self.stack.pop() {\n            Some(num) => Some(num),\n            None => None,\n        }\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    fn peek(&self) -> Option<&T> {\n        if self.is_empty() { panic!(\"\u6808\u4e3a\u7a7a\") };\n        self.stack.last()\n    }\n\n    /* \u8fd4\u56de &Vec */\n    fn to_array(&self) -> &Vec<T> {\n        &self.stack\n    }\n}\n
array_stack.c
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\ntypedef struct {\n    int *data;\n    int size;\n} ArrayStack;\n\n/* \u6784\u9020\u51fd\u6570 */\nArrayStack *newArrayStack() {\n    ArrayStack *stack = malloc(sizeof(ArrayStack));\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u5927\u5bb9\u91cf\uff0c\u907f\u514d\u6269\u5bb9\n    stack->data = malloc(sizeof(int) * MAX_SIZE);\n    stack->size = 0;\n    return stack;\n}\n\n/* \u6790\u6784\u51fd\u6570 */\nvoid delArrayStack(ArrayStack *stack) {\n    free(stack->data);\n    free(stack);\n}\n\n/* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\nint size(ArrayStack *stack) {\n    return stack->size;\n}\n\n/* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\nbool isEmpty(ArrayStack *stack) {\n    return stack->size == 0;\n}\n\n/* \u5165\u6808 */\nvoid push(ArrayStack *stack, int num) {\n    if (stack->size == MAX_SIZE) {\n        printf(\"\u6808\u5df2\u6ee1\\n\");\n        return;\n    }\n    stack->data[stack->size] = num;\n    stack->size++;\n}\n\n/* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\nint peek(ArrayStack *stack) {\n    if (stack->size == 0) {\n        printf(\"\u6808\u4e3a\u7a7a\\n\");\n        return INT_MAX;\n    }\n    return stack->data[stack->size - 1];\n}\n\n/* \u51fa\u6808 */\nint pop(ArrayStack *stack) {\n    int val = peek(stack);\n    stack->size--;\n    return val;\n}\n
array_stack.zig
// \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808\nfn ArrayStack(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        stack: ?std.ArrayList(T) = null,     \n\n        // \u6784\u9020\u65b9\u6cd5\uff08\u5206\u914d\u5185\u5b58+\u521d\u59cb\u5316\u6808\uff09\n        pub fn init(self: *Self, allocator: std.mem.Allocator) void {\n            if (self.stack == null) {\n                self.stack = std.ArrayList(T).init(allocator);\n            }\n        }\n\n        // \u6790\u6784\u65b9\u6cd5\uff08\u91ca\u653e\u5185\u5b58\uff09\n        pub fn deinit(self: *Self) void {\n            if (self.stack == null) return;\n            self.stack.?.deinit();\n        }\n\n        // \u83b7\u53d6\u6808\u7684\u957f\u5ea6\n        pub fn size(self: *Self) usize {\n            return self.stack.?.items.len;\n        }\n\n        // \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a\n        pub fn isEmpty(self: *Self) bool {\n            return self.size() == 0;\n        }\n\n        // \u8bbf\u95ee\u6808\u9876\u5143\u7d20\n        pub fn peek(self: *Self) T {\n            if (self.isEmpty()) @panic(\"\u6808\u4e3a\u7a7a\");\n            return self.stack.?.items[self.size() - 1];\n        }  \n\n        // \u5165\u6808\n        pub fn push(self: *Self, num: T) !void {\n            try self.stack.?.append(num);\n        } \n\n        // \u51fa\u6808\n        pub fn pop(self: *Self) T {\n            var num = self.stack.?.pop();\n            return num;\n        } \n\n        // \u8fd4\u56de ArrayList\n        pub fn toList(self: *Self) std.ArrayList(T) {\n            return self.stack.?;\n        }\n    };\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_stack_and_queue/stack/#513-comparison-of-the-two-implementations","title":"5.1.3 \u00a0 Comparison of the Two Implementations","text":"

Supported Operations

Both implementations support all the operations defined in a stack. The array implementation additionally supports random access, but this is beyond the scope of a stack definition and is generally not used.

Time Efficiency

In the array-based implementation, both push and pop operations occur in pre-allocated continuous memory, which has good cache locality and therefore higher efficiency. However, if the push operation exceeds the array capacity, it triggers a resizing mechanism, making the time complexity of that push operation \\(O(n)\\).

In the linked list implementation, list expansion is very flexible, and there is no efficiency decrease issue as in array expansion. However, the push operation requires initializing a node object and modifying pointers, so its efficiency is relatively lower. If the elements being pushed are already node objects, then the initialization step can be skipped, improving efficiency.

Thus, when the elements for push and pop operations are basic data types like int or double, we can draw the following conclusions:

  • The array-based stack implementation's efficiency decreases during expansion, but since expansion is a low-frequency operation, its average efficiency is higher.
  • The linked list-based stack implementation provides more stable efficiency performance.

Space Efficiency

When initializing a list, the system allocates an \"initial capacity,\" which might exceed the actual need; moreover, the expansion mechanism usually increases capacity by a specific factor (like doubling), which may also exceed the actual need. Therefore, the array-based stack might waste some space.

However, since linked list nodes require extra space for storing pointers, the space occupied by linked list nodes is relatively larger.

In summary, we cannot simply determine which implementation is more memory-efficient. It requires analysis based on specific circumstances.

"},{"location":"chapter_stack_and_queue/stack/#514-typical-applications-of-stack","title":"5.1.4 \u00a0 Typical Applications of Stack","text":"
  • Back and forward in browsers, undo and redo in software. Every time we open a new webpage, the browser pushes the previous page onto the stack, allowing us to go back to the previous page through the back operation, which is essentially a pop operation. To support both back and forward, two stacks are needed to work together.
  • Memory management in programs. Each time a function is called, the system adds a stack frame at the top of the stack to record the function's context information. In recursive functions, the downward recursion phase keeps pushing onto the stack, while the upward backtracking phase keeps popping from the stack.
"},{"location":"chapter_stack_and_queue/summary/","title":"5.4 \u00a0 Summary","text":""},{"location":"chapter_stack_and_queue/summary/#1-key-review","title":"1. \u00a0 Key Review","text":"
  • A stack is a data structure that follows the Last-In-First-Out (LIFO) principle and can be implemented using either arrays or linked lists.
  • In terms of time efficiency, the array implementation of a stack has higher average efficiency, but during expansion, the time complexity for a single push operation can degrade to \\(O(n)\\). In contrast, the linked list implementation of a stack offers more stable efficiency.
  • Regarding space efficiency, the array implementation of a stack may lead to some level of space wastage. However, it's important to note that the memory space occupied by nodes in a linked list is generally larger than that for elements in an array.
  • A queue is a data structure that follows the First-In-First-Out (FIFO) principle, and it can also be implemented using either arrays or linked lists. The conclusions regarding time and space efficiency for queues are similar to those for stacks.
  • A double-ended queue is a more flexible type of queue that allows adding and removing elements from both ends.
"},{"location":"chapter_stack_and_queue/summary/#2-q-a","title":"2. \u00a0 Q & A","text":"

Q: Is the browser's forward and backward functionality implemented with a doubly linked list?

The forward and backward functionality of a browser fundamentally represents the \"stack\" concept. When a user visits a new page, it is added to the top of the stack; when they click the back button, the page is popped from the top. A double-ended queue can conveniently implement some additional operations, as mentioned in the \"Double-Ended Queue\" section.

Q: After popping from a stack, is it necessary to free the memory of the popped node?

If the popped node will still be used later, it's not necessary to free its memory. In languages like Java and Python that have automatic garbage collection, manual memory release isn't required; in C and C++, manual memory release is necessary if the node will no longer be used.

Q: A double-ended queue seems like two stacks joined together. What are its uses?

A double-ended queue is essentially a combination of a stack and a queue, or like two stacks joined together. It exhibits both stack and queue logic, therefore enabling the implementation of all applications of stacks and queues with added flexibility.

Q: How exactly are undo and redo implemented?

Undo and redo are implemented using two stacks: Stack A for undo and Stack B for redo.

  1. Each time a user performs an operation, it is pushed onto Stack A, and Stack B is cleared.
  2. When the user executes an \"undo\", the most recent operation is popped from Stack A and pushed onto Stack B.
  3. When the user executes a \"redo\", the most recent operation is popped from Stack B and pushed back onto Stack A.
"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Home","text":"Hello Algo

Data Structures and Algorithms Crash Course with Animated Illustrations and Off-the-Shelf Code

Dive In Clone Repo Get PDF

The English edition is brewing...

Feel free to engage in Chinese-to-English translation and pull request review! For guidelines, please see #914.

Quote

\"An easy-to-understand book on data structures and algorithms, which guides readers to learn by minds-on and hands-on. Strongly recommended for algorithm beginners!\"

\u2014\u2014 Junhui Deng, Professor of Computer Science, Tsinghua University

Quote

\"If I had 'Hello Algo' when I was learning data structures and algorithms, it would have been 10 times easier!\"

\u2014\u2014 Mu Li, Senior Principal Scientist, Amazon

Animated illustrations

Easy to understandSmooth learning curve

\"A picture is worth a thousand words.\"

Off-the-Shelf Code

Multi programming languagesRun with one click

\"Talk is cheap. Show me the code.\"

Learning Together

Discussion and questions welcomeReaders progress together

\"Knowledge increases by sharing.\"

Preface

Two years ago, I shared the \"Sword Offer\" series of problem solutions on LeetCode, which received much love and support from many students. During my interactions with readers, the most common question I encountered was \"How to get started with algorithms.\" Gradually, I developed a deep interest in this question.

Blindly solving problems seems to be the most popular method, being simple, direct, and effective. However, problem-solving is like playing a \"Minesweeper\" game, where students with strong self-learning abilities can successfully clear the mines one by one, but those with insufficient foundations may end up bruised from explosions, retreating step by step in frustration. Thoroughly reading textbooks is also common, but for students aiming for job applications, the energy consumed by graduation, resume submissions, and preparing for written tests and interviews makes tackling thick books a daunting challenge.

If you are facing similar troubles, then you are lucky to have found this book. This book is my answer to this question, not necessarily the best solution, but at least an active attempt. Although this book won't directly land you an Offer, it will guide you through the \"knowledge map\" of data structures and algorithms, help you understand the shape, size, and distribution of different \"mines,\" and equip you with various \"demining methods.\" With these skills, I believe you can more comfortably solve problems and read literature, gradually building a complete knowledge system.

I deeply agree with Professor Feynman's saying: \"Knowledge isn't free. You have to pay attention.\" In this sense, this book is not entirely \"free.\" To not disappoint the precious \"attention\" you pay to this book, I will do my utmost, investing the greatest \"attention\" to complete the creation of this book.

Author

Yudong Jin(Krahets), Senior Algorithm Engineer in a top tech company, Master's degree from Shanghai Jiao Tong University. The highest-read blogger across the entire LeetCode, his published \"Illustration of Algorithm Data Structures\" has been subscribed to by over 300k.

Contribution

This book is continuously improved with the joint efforts of many contributors from the open-source community. Thanks to each writer who invested their time and energy, listed in the order generated by GitHub:

The code review work for this book was completed by codingonion, Gonglja, gvenusleo, hpstory, justin\u2010tse, krahets, night-cruise, nuomi1, and Reanon (listed in alphabetical order). Thanks to them for their time and effort, ensuring the standardization and uniformity of the code in various languages.

codingonionRust, Zig GongljaC, C++ gvenusleoDart hpstoryC# justin-tseJS, TS krahetsJava, Python night-cruiseRust nuomi1Swift ReanonGo, C"},{"location":"chapter_array_and_linkedlist/","title":"Chapter 4. \u00a0 Arrays and Linked Lists","text":"

Abstract

The world of data structures resembles a sturdy brick wall.

In arrays, envision bricks snugly aligned, each resting seamlessly beside the next, creating a unified formation. Meanwhile, in linked lists, these bricks disperse freely, embraced by vines gracefully knitting connections between them.

"},{"location":"chapter_array_and_linkedlist/#chapter-contents","title":"Chapter Contents","text":"
  • 4.1 \u00a0 Array
  • 4.2 \u00a0 Linked List
  • 4.3 \u00a0 List
  • 4.4 \u00a0 Memory and Cache
  • 4.5 \u00a0 Summary
"},{"location":"chapter_array_and_linkedlist/array/","title":"4.1 \u00a0 Arrays","text":"

An \"array\" is a linear data structure that operates as a lineup of similar items, stored together in a computer's memory in contiguous spaces. It's like a sequence that maintains organized storage. Each item in this lineup has its unique 'spot' known as an \"index\". Please refer to the Figure 4-1 to observe how arrays work and grasp these key terms.

Figure 4-1 \u00a0 Array Definition and Storage Method

"},{"location":"chapter_array_and_linkedlist/array/#411-common-operations-on-arrays","title":"4.1.1 \u00a0 Common Operations on Arrays","text":""},{"location":"chapter_array_and_linkedlist/array/#1-initializing-arrays","title":"1. \u00a0 Initializing Arrays","text":"

Arrays can be initialized in two ways depending on the needs: either without initial values or with specified initial values. When initial values are not specified, most programming languages will set the array elements to \\(0\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig array.py
# Initialize array\narr: list[int] = [0] * 5  # [ 0, 0, 0, 0, 0 ]\nnums: list[int] = [1, 3, 2, 5, 4]\n
array.cpp
/* Initialize array */\n// Stored on stack\nint arr[5];\nint nums[5] = { 1, 3, 2, 5, 4 };\n// Stored on heap (manual memory release needed)\nint* arr1 = new int[5];\nint* nums1 = new int[5] { 1, 3, 2, 5, 4 };\n
array.java
/* Initialize array */\nint[] arr = new int[5]; // { 0, 0, 0, 0, 0 }\nint[] nums = { 1, 3, 2, 5, 4 };\n
array.cs
/* Initialize array */\nint[] arr = new int[5]; // [ 0, 0, 0, 0, 0 ]\nint[] nums = [1, 3, 2, 5, 4];\n
array.go
/* Initialize array */\nvar arr [5]int\n// In Go, specifying the length ([5]int) denotes an array, while not specifying it ([]int) denotes a slice.\n// Since Go's arrays are designed to have compile-time fixed length, only constants can be used to specify the length.\n// For convenience in implementing the extend() method, the Slice will be considered as an Array here.\nnums := []int{1, 3, 2, 5, 4}\n
array.swift
/* Initialize array */\nlet arr = Array(repeating: 0, count: 5) // [0, 0, 0, 0, 0]\nlet nums = [1, 3, 2, 5, 4]\n
array.js
/* Initialize array */\nvar arr = new Array(5).fill(0);\nvar nums = [1, 3, 2, 5, 4];\n
array.ts
/* Initialize array */\nlet arr: number[] = new Array(5).fill(0);\nlet nums: number[] = [1, 3, 2, 5, 4];\n
array.dart
/* Initialize array */\nList<int> arr = List.filled(5, 0); // [0, 0, 0, 0, 0]\nList<int> nums = [1, 3, 2, 5, 4];\n
array.rs
/* Initialize array */\nlet arr: Vec<i32> = vec![0; 5]; // [0, 0, 0, 0, 0]\nlet nums: Vec<i32> = vec![1, 3, 2, 5, 4];\n
array.c
/* Initialize array */\nint arr[5] = { 0 }; // { 0, 0, 0, 0, 0 }\nint nums[5] = { 1, 3, 2, 5, 4 };\n
array.zig
// Initialize array\nvar arr = [_]i32{0} ** 5; // { 0, 0, 0, 0, 0 }\nvar nums = [_]i32{ 1, 3, 2, 5, 4 };\n
"},{"location":"chapter_array_and_linkedlist/array/#2-accessing-elements","title":"2. \u00a0 Accessing Elements","text":"

Elements in an array are stored in contiguous memory spaces, making it simpler to compute each element's memory address. The formula shown in the Figure below aids in determining an element's memory address, utilizing the array's memory address (specifically, the first element's address) and the element's index. This computation streamlines direct access to the desired element.

Figure 4-2 \u00a0 Memory Address Calculation for Array Elements

As observed in the above illustration, array indexing conventionally begins at \\(0\\). While this might appear counterintuitive, considering counting usually starts at \\(1\\), within the address calculation formula, an index is essentially an offset from the memory address. For the first element's address, this offset is \\(0\\), validating its index as \\(0\\).

Accessing elements in an array is highly efficient, allowing us to randomly access any element in \\(O(1)\\) time.

PythonC++JavaC#GoSwiftJSTSDartRustCZig array.py
def random_access(nums: list[int]) -> int:\n    \"\"\"\u968f\u673a\u8bbf\u95ee\u5143\u7d20\"\"\"\n    # \u5728\u533a\u95f4 [0, len(nums)-1] \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    random_index = random.randint(0, len(nums) - 1)\n    # \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    random_num = nums[random_index]\n    return random_num\n
array.cpp
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nint randomAccess(int *nums, int size) {\n    // \u5728\u533a\u95f4 [0, size) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    int randomIndex = rand() % size;\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    int randomNum = nums[randomIndex];\n    return randomNum;\n}\n
array.java
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nint randomAccess(int[] nums) {\n    // \u5728\u533a\u95f4 [0, nums.length) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    int randomIndex = ThreadLocalRandom.current().nextInt(0, nums.length);\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    int randomNum = nums[randomIndex];\n    return randomNum;\n}\n
array.cs
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nint RandomAccess(int[] nums) {\n    Random random = new();\n    // \u5728\u533a\u95f4 [0, nums.Length) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    int randomIndex = random.Next(nums.Length);\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    int randomNum = nums[randomIndex];\n    return randomNum;\n}\n
array.go
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nfunc randomAccess(nums []int) (randomNum int) {\n    // \u5728\u533a\u95f4 [0, nums.length) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    randomIndex := rand.Intn(len(nums))\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    randomNum = nums[randomIndex]\n    return\n}\n
array.swift
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nfunc randomAccess(nums: [Int]) -> Int {\n    // \u5728\u533a\u95f4 [0, nums.count) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    let randomIndex = nums.indices.randomElement()!\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    let randomNum = nums[randomIndex]\n    return randomNum\n}\n
array.js
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nfunction randomAccess(nums) {\n    // \u5728\u533a\u95f4 [0, nums.length) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    const random_index = Math.floor(Math.random() * nums.length);\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    const random_num = nums[random_index];\n    return random_num;\n}\n
array.ts
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nfunction randomAccess(nums: number[]): number {\n    // \u5728\u533a\u95f4 [0, nums.length) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    const random_index = Math.floor(Math.random() * nums.length);\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    const random_num = nums[random_index];\n    return random_num;\n}\n
array.dart
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nint randomAccess(List<int> nums) {\n  // \u5728\u533a\u95f4 [0, nums.length) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n  int randomIndex = Random().nextInt(nums.length);\n  // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n  int randomNum = nums[randomIndex];\n  return randomNum;\n}\n
array.rs
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nfn random_access(nums: &[i32]) -> i32 {\n    // \u5728\u533a\u95f4 [0, nums.len()) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    let random_index = rand::thread_rng().gen_range(0..nums.len());\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    let random_num = nums[random_index];\n    random_num\n}\n
array.c
/* \u968f\u673a\u8bbf\u95ee\u5143\u7d20 */\nint randomAccess(int *nums, int size) {\n    // \u5728\u533a\u95f4 [0, size) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6570\u5b57\n    int randomIndex = rand() % size;\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    int randomNum = nums[randomIndex];\n    return randomNum;\n}\n
array.zig
// \u968f\u673a\u8bbf\u95ee\u5143\u7d20\nfn randomAccess(nums: []i32) i32 {\n    // \u5728\u533a\u95f4 [0, nums.len) \u4e2d\u968f\u673a\u62bd\u53d6\u4e00\u4e2a\u6574\u6570\n    var randomIndex = std.crypto.random.intRangeLessThan(usize, 0, nums.len);\n    // \u83b7\u53d6\u5e76\u8fd4\u56de\u968f\u673a\u5143\u7d20\n    var randomNum = nums[randomIndex];\n    return randomNum;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/array/#3-inserting-elements","title":"3. \u00a0 Inserting Elements","text":"

Array elements are tightly packed in memory, with no space available to accommodate additional data between them. Illustrated in Figure below, inserting an element in the middle of an array requires shifting all subsequent elements back by one position to create room for the new element.

Figure 4-3 \u00a0 Array Element Insertion Example

It's important to note that due to the fixed length of an array, inserting an element will unavoidably result in the loss of the last element in the array. Solutions to address this issue will be explored in the \"List\" chapter.

PythonC++JavaC#GoSwiftJSTSDartRustCZig array.py
def insert(nums: list[int], num: int, index: int):\n    \"\"\"\u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num\"\"\"\n    # \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for i in range(len(nums) - 1, index, -1):\n        nums[i] = nums[i - 1]\n    # \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num\n
array.cpp
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nvoid insert(int *nums, int size, int num, int index) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for (int i = size - 1; i > index; i--) {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
array.java
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nvoid insert(int[] nums, int num, int index) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for (int i = nums.length - 1; i > index; i--) {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
array.cs
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nvoid Insert(int[] nums, int num, int index) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for (int i = nums.Length - 1; i > index; i--) {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
array.go
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nfunc insert(nums []int, num int, index int) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for i := len(nums) - 1; i > index; i-- {\n        nums[i] = nums[i-1]\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num\n}\n
array.swift
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nfunc insert(nums: inout [Int], num: Int, index: Int) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for i in nums.indices.dropFirst(index).reversed() {\n        nums[i] = nums[i - 1]\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num\n}\n
array.js
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nfunction insert(nums, num, index) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for (let i = nums.length - 1; i > index; i--) {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
array.ts
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nfunction insert(nums: number[], num: number, index: number): void {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for (let i = nums.length - 1; i > index; i--) {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
array.dart
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 _num */\nvoid insert(List<int> nums, int _num, int index) {\n  // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n  for (var i = nums.length - 1; i > index; i--) {\n    nums[i] = nums[i - 1];\n  }\n  // \u5c06 _num \u8d4b\u7ed9 index \u5904\u5143\u7d20\n  nums[index] = _num;\n}\n
array.rs
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nfn insert(nums: &mut Vec<i32>, num: i32, index: usize) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for i in (index + 1..nums.len()).rev() {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
array.c
/* \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num */\nvoid insert(int *nums, int size, int num, int index) {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for (int i = size - 1; i > index; i--) {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
array.zig
// \u5728\u6570\u7ec4\u7684\u7d22\u5f15 index \u5904\u63d2\u5165\u5143\u7d20 num\nfn insert(nums: []i32, num: i32, index: usize) void {\n    // \u628a\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    var i = nums.len - 1;\n    while (i > index) : (i -= 1) {\n        nums[i] = nums[i - 1];\n    }\n    // \u5c06 num \u8d4b\u7ed9 index \u5904\u7684\u5143\u7d20\n    nums[index] = num;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/array/#4-deleting-elements","title":"4. \u00a0 Deleting Elements","text":"

Similarly, as depicted in the Figure 4-4 , to delete an element at index \\(i\\), all elements following index \\(i\\) must be moved forward by one position.

Figure 4-4 \u00a0 Array Element Deletion Example

Please note that after deletion, the former last element becomes \"meaningless,\" hence requiring no specific modification.

PythonC++JavaC#GoSwiftJSTSDartRustCZig array.py
def remove(nums: list[int], index: int):\n    \"\"\"\u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20\"\"\"\n    # \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for i in range(index, len(nums) - 1):\n        nums[i] = nums[i + 1]\n
array.cpp
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nvoid remove(int *nums, int size, int index) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for (int i = index; i < size - 1; i++) {\n        nums[i] = nums[i + 1];\n    }\n}\n
array.java
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nvoid remove(int[] nums, int index) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for (int i = index; i < nums.length - 1; i++) {\n        nums[i] = nums[i + 1];\n    }\n}\n
array.cs
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nvoid Remove(int[] nums, int index) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for (int i = index; i < nums.Length - 1; i++) {\n        nums[i] = nums[i + 1];\n    }\n}\n
array.go
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nfunc remove(nums []int, index int) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for i := index; i < len(nums)-1; i++ {\n        nums[i] = nums[i+1]\n    }\n}\n
array.swift
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nfunc remove(nums: inout [Int], index: Int) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for i in nums.indices.dropFirst(index).dropLast() {\n        nums[i] = nums[i + 1]\n    }\n}\n
array.js
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nfunction remove(nums, index) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for (let i = index; i < nums.length - 1; i++) {\n        nums[i] = nums[i + 1];\n    }\n}\n
array.ts
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nfunction remove(nums: number[], index: number): void {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for (let i = index; i < nums.length - 1; i++) {\n        nums[i] = nums[i + 1];\n    }\n}\n
array.dart
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nvoid remove(List<int> nums, int index) {\n  // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n  for (var i = index; i < nums.length - 1; i++) {\n    nums[i] = nums[i + 1];\n  }\n}\n
array.rs
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\nfn remove(nums: &mut Vec<i32>, index: usize) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for i in index..nums.len() - 1 {\n        nums[i] = nums[i + 1];\n    }\n}\n
array.c
/* \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20 */\n// \u6ce8\u610f\uff1astdio.h \u5360\u7528\u4e86 remove \u5173\u952e\u8bcd\nvoid removeItem(int *nums, int size, int index) {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for (int i = index; i < size - 1; i++) {\n        nums[i] = nums[i + 1];\n    }\n}\n
array.zig
// \u5220\u9664\u7d22\u5f15 index \u5904\u7684\u5143\u7d20\nfn remove(nums: []i32, index: usize) void {\n    // \u628a\u7d22\u5f15 index \u4e4b\u540e\u7684\u6240\u6709\u5143\u7d20\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    var i = index;\n    while (i < nums.len - 1) : (i += 1) {\n        nums[i] = nums[i + 1];\n    }\n}\n
Visualizing Code

Full Screen >

In summary, the insertion and deletion operations in arrays present the following disadvantages:

  • High Time Complexity: Both insertion and deletion in an array have an average time complexity of \\(O(n)\\), where \\(n\\) is the length of the array.
  • Loss of Elements: Due to the fixed length of arrays, elements that exceed the array's capacity are lost during insertion.
  • Waste of Memory: Initializing a longer array and utilizing only the front part results in \"meaningless\" end elements during insertion, leading to some wasted memory space.
"},{"location":"chapter_array_and_linkedlist/array/#5-traversing-arrays","title":"5. \u00a0 Traversing Arrays","text":"

In most programming languages, we can traverse an array either by using indices or by directly iterating over each element:

PythonC++JavaC#GoSwiftJSTSDartRustCZig array.py
def traverse(nums: list[int]):\n    \"\"\"\u904d\u5386\u6570\u7ec4\"\"\"\n    count = 0\n    # \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for i in range(len(nums)):\n        count += nums[i]\n    # \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for num in nums:\n        count += num\n    # \u540c\u65f6\u904d\u5386\u6570\u636e\u7d22\u5f15\u548c\u5143\u7d20\n    for i, num in enumerate(nums):\n        count += nums[i]\n        count += num\n
array.cpp
/* \u904d\u5386\u6570\u7ec4 */\nvoid traverse(int *nums, int size) {\n    int count = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for (int i = 0; i < size; i++) {\n        count += nums[i];\n    }\n}\n
array.java
/* \u904d\u5386\u6570\u7ec4 */\nvoid traverse(int[] nums) {\n    int count = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for (int i = 0; i < nums.length; i++) {\n        count += nums[i];\n    }\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for (int num : nums) {\n        count += num;\n    }\n}\n
array.cs
/* \u904d\u5386\u6570\u7ec4 */\nvoid Traverse(int[] nums) {\n    int count = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for (int i = 0; i < nums.Length; i++) {\n        count += nums[i];\n    }\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    foreach (int num in nums) {\n        count += num;\n    }\n}\n
array.go
/* \u904d\u5386\u6570\u7ec4 */\nfunc traverse(nums []int) {\n    count := 0\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for i := 0; i < len(nums); i++ {\n        count += nums[i]\n    }\n    count = 0\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for _, num := range nums {\n        count += num\n    }\n    // \u540c\u65f6\u904d\u5386\u6570\u636e\u7d22\u5f15\u548c\u5143\u7d20\n    for i, num := range nums {\n        count += nums[i]\n        count += num\n    }\n}\n
array.swift
/* \u904d\u5386\u6570\u7ec4 */\nfunc traverse(nums: [Int]) {\n    var count = 0\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for i in nums.indices {\n        count += nums[i]\n    }\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for num in nums {\n        count += num\n    }\n}\n
array.js
/* \u904d\u5386\u6570\u7ec4 */\nfunction traverse(nums) {\n    let count = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for (let i = 0; i < nums.length; i++) {\n        count += nums[i];\n    }\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for (const num of nums) {\n        count += num;\n    }\n}\n
array.ts
/* \u904d\u5386\u6570\u7ec4 */\nfunction traverse(nums: number[]): void {\n    let count = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for (let i = 0; i < nums.length; i++) {\n        count += nums[i];\n    }\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for (const num of nums) {\n        count += num;\n    }\n}\n
array.dart
/* \u904d\u5386\u6570\u7ec4\u5143\u7d20 */\nvoid traverse(List<int> nums) {\n  int count = 0;\n  // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n  for (var i = 0; i < nums.length; i++) {\n    count += nums[i];\n  }\n  // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n  for (int _num in nums) {\n    count += _num;\n  }\n  // \u901a\u8fc7 forEach \u65b9\u6cd5\u904d\u5386\u6570\u7ec4\n  nums.forEach((_num) {\n    count += _num;\n  });\n}\n
array.rs
/* \u904d\u5386\u6570\u7ec4 */\nfn traverse(nums: &[i32]) {\n    let mut _count = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for i in 0..nums.len() {\n        _count += nums[i];\n    }\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for num in nums {\n        _count += num;\n    }\n}\n
array.c
/* \u904d\u5386\u6570\u7ec4 */\nvoid traverse(int *nums, int size) {\n    int count = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    for (int i = 0; i < size; i++) {\n        count += nums[i];\n    }\n}\n
array.zig
// \u904d\u5386\u6570\u7ec4\nfn traverse(nums: []i32) void {\n    var count: i32 = 0;\n    // \u901a\u8fc7\u7d22\u5f15\u904d\u5386\u6570\u7ec4\n    var i: i32 = 0;\n    while (i < nums.len) : (i += 1) {\n        count += nums[i];\n    }\n    count = 0;\n    // \u76f4\u63a5\u904d\u5386\u6570\u7ec4\u5143\u7d20\n    for (nums) |num| {\n        count += num;\n    }\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/array/#6-finding-elements","title":"6. \u00a0 Finding Elements","text":"

Locating a specific element within an array involves iterating through the array, checking each element to determine if it matches the desired value.

Because arrays are linear data structures, this operation is commonly referred to as \"linear search.\"

PythonC++JavaC#GoSwiftJSTSDartRustCZig array.py
def find(nums: list[int], target: int) -> int:\n    \"\"\"\u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20\"\"\"\n    for i in range(len(nums)):\n        if nums[i] == target:\n            return i\n    return -1\n
array.cpp
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nint find(int *nums, int size, int target) {\n    for (int i = 0; i < size; i++) {\n        if (nums[i] == target)\n            return i;\n    }\n    return -1;\n}\n
array.java
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nint find(int[] nums, int target) {\n    for (int i = 0; i < nums.length; i++) {\n        if (nums[i] == target)\n            return i;\n    }\n    return -1;\n}\n
array.cs
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nint Find(int[] nums, int target) {\n    for (int i = 0; i < nums.Length; i++) {\n        if (nums[i] == target)\n            return i;\n    }\n    return -1;\n}\n
array.go
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nfunc find(nums []int, target int) (index int) {\n    index = -1\n    for i := 0; i < len(nums); i++ {\n        if nums[i] == target {\n            index = i\n            break\n        }\n    }\n    return\n}\n
array.swift
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nfunc find(nums: [Int], target: Int) -> Int {\n    for i in nums.indices {\n        if nums[i] == target {\n            return i\n        }\n    }\n    return -1\n}\n
array.js
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nfunction find(nums, target) {\n    for (let i = 0; i < nums.length; i++) {\n        if (nums[i] === target) return i;\n    }\n    return -1;\n}\n
array.ts
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nfunction find(nums: number[], target: number): number {\n    for (let i = 0; i < nums.length; i++) {\n        if (nums[i] === target) {\n            return i;\n        }\n    }\n    return -1;\n}\n
array.dart
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nint find(List<int> nums, int target) {\n  for (var i = 0; i < nums.length; i++) {\n    if (nums[i] == target) return i;\n  }\n  return -1;\n}\n
array.rs
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nfn find(nums: &[i32], target: i32) -> Option<usize> {\n    for i in 0..nums.len() {\n        if nums[i] == target {\n            return Some(i);\n        }\n    }\n    None\n}\n
array.c
/* \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20 */\nint find(int *nums, int size, int target) {\n    for (int i = 0; i < size; i++) {\n        if (nums[i] == target)\n            return i;\n    }\n    return -1;\n}\n
array.zig
// \u5728\u6570\u7ec4\u4e2d\u67e5\u627e\u6307\u5b9a\u5143\u7d20\nfn find(nums: []i32, target: i32) i32 {\n    for (nums, 0..) |num, i| {\n        if (num == target) return @intCast(i);\n    }\n    return -1;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/array/#7-expanding-arrays","title":"7. \u00a0 Expanding Arrays","text":"

In complex system environments, ensuring the availability of memory space after an array for safe capacity extension becomes challenging. Consequently, in most programming languages, the length of an array is immutable.

To expand an array, it's necessary to create a larger array and then copy the elements from the original array. This operation has a time complexity of \\(O(n)\\) and can be time-consuming for large arrays. The code are as follows:

PythonC++JavaC#GoSwiftJSTSDartRustCZig array.py
def extend(nums: list[int], enlarge: int) -> list[int]:\n    \"\"\"\u6269\u5c55\u6570\u7ec4\u957f\u5ea6\"\"\"\n    # \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    res = [0] * (len(nums) + enlarge)\n    # \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for i in range(len(nums)):\n        res[i] = nums[i]\n    # \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res\n
array.cpp
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nint *extend(int *nums, int size, int enlarge) {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    int *res = new int[size + enlarge];\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for (int i = 0; i < size; i++) {\n        res[i] = nums[i];\n    }\n    // \u91ca\u653e\u5185\u5b58\n    delete[] nums;\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res;\n}\n
array.java
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nint[] extend(int[] nums, int enlarge) {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    int[] res = new int[nums.length + enlarge];\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for (int i = 0; i < nums.length; i++) {\n        res[i] = nums[i];\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res;\n}\n
array.cs
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nint[] Extend(int[] nums, int enlarge) {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    int[] res = new int[nums.Length + enlarge];\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for (int i = 0; i < nums.Length; i++) {\n        res[i] = nums[i];\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res;\n}\n
array.go
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nfunc extend(nums []int, enlarge int) []int {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    res := make([]int, len(nums)+enlarge)\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for i, num := range nums {\n        res[i] = num\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res\n}\n
array.swift
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nfunc extend(nums: [Int], enlarge: Int) -> [Int] {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    var res = Array(repeating: 0, count: nums.count + enlarge)\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for i in nums.indices {\n        res[i] = nums[i]\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res\n}\n
array.js
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\n// \u8bf7\u6ce8\u610f\uff0cJavaScript \u7684 Array \u662f\u52a8\u6001\u6570\u7ec4\uff0c\u53ef\u4ee5\u76f4\u63a5\u6269\u5c55\n// \u4e3a\u4e86\u65b9\u4fbf\u5b66\u4e60\uff0c\u672c\u51fd\u6570\u5c06 Array \u770b\u4f5c\u957f\u5ea6\u4e0d\u53ef\u53d8\u7684\u6570\u7ec4\nfunction extend(nums, enlarge) {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    const res = new Array(nums.length + enlarge).fill(0);\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for (let i = 0; i < nums.length; i++) {\n        res[i] = nums[i];\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res;\n}\n
array.ts
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\n// \u8bf7\u6ce8\u610f\uff0cTypeScript \u7684 Array \u662f\u52a8\u6001\u6570\u7ec4\uff0c\u53ef\u4ee5\u76f4\u63a5\u6269\u5c55\n// \u4e3a\u4e86\u65b9\u4fbf\u5b66\u4e60\uff0c\u672c\u51fd\u6570\u5c06 Array \u770b\u4f5c\u957f\u5ea6\u4e0d\u53ef\u53d8\u7684\u6570\u7ec4\nfunction extend(nums: number[], enlarge: number): number[] {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    const res = new Array(nums.length + enlarge).fill(0);\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for (let i = 0; i < nums.length; i++) {\n        res[i] = nums[i];\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res;\n}\n
array.dart
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nList<int> extend(List<int> nums, int enlarge) {\n  // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n  List<int> res = List.filled(nums.length + enlarge, 0);\n  // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n  for (var i = 0; i < nums.length; i++) {\n    res[i] = nums[i];\n  }\n  // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n  return res;\n}\n
array.rs
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nfn extend(nums: Vec<i32>, enlarge: usize) -> Vec<i32> {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    let mut res: Vec<i32> = vec![0; nums.len() + enlarge];\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\n    for i in 0..nums.len() {\n        res[i] = nums[i];\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    res\n}\n
array.c
/* \u6269\u5c55\u6570\u7ec4\u957f\u5ea6 */\nint *extend(int *nums, int size, int enlarge) {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    int *res = (int *)malloc(sizeof(int) * (size + enlarge));\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    for (int i = 0; i < size; i++) {\n        res[i] = nums[i];\n    }\n    // \u521d\u59cb\u5316\u6269\u5c55\u540e\u7684\u7a7a\u95f4\n    for (int i = size; i < size + enlarge; i++) {\n        res[i] = 0;\n    }\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res;\n}\n
array.zig
// \u6269\u5c55\u6570\u7ec4\u957f\u5ea6\nfn extend(mem_allocator: std.mem.Allocator, nums: []i32, enlarge: usize) ![]i32 {\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u6269\u5c55\u957f\u5ea6\u540e\u7684\u6570\u7ec4\n    var res = try mem_allocator.alloc(i32, nums.len + enlarge);\n    @memset(res, 0);\n    // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    std.mem.copy(i32, res, nums);\n    // \u8fd4\u56de\u6269\u5c55\u540e\u7684\u65b0\u6570\u7ec4\n    return res;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/array/#412-advantages-and-limitations-of-arrays","title":"4.1.2 \u00a0 Advantages and Limitations of Arrays","text":"

Arrays are stored in contiguous memory spaces and consist of elements of the same type. This approach provides substantial prior information that systems can leverage to optimize the efficiency of data structure operations.

  • High Space Efficiency: Arrays allocate a contiguous block of memory for data, eliminating the need for additional structural overhead.
  • Support for Random Access: Arrays allow \\(O(1)\\) time access to any element.
  • Cache Locality: When accessing array elements, the computer not only loads them but also caches the surrounding data, utilizing high-speed cache to enchance subsequent operation speeds.

However, continuous space storage is a double-edged sword, with the following limitations:

  • Low Efficiency in Insertion and Deletion: As arrays accumulate many elements, inserting or deleting elements requires shifting a large number of elements.
  • Fixed Length: The length of an array is fixed after initialization. Expanding an array requires copying all data to a new array, incurring significant costs.
  • Space Wastage: If the allocated array size exceeds the what is necessary, the extra space is wasted.
"},{"location":"chapter_array_and_linkedlist/array/#413-typical-applications-of-arrays","title":"4.1.3 \u00a0 Typical Applications of Arrays","text":"

Arrays are fundamental and widely used data structures. They find frequent application in various algorithms and serve in the implementation of complex data structures.

  • Random Access: Arrays are ideal for storing data when random sampling is required. By generating a random sequence based on indices, we can achieve random sampling efficiently.
  • Sorting and Searching: Arrays are the most commonly used data structure for sorting and searching algorithms. Techniques like quick sort, merge sort, binary search, etc., are primarily operate on arrays.
  • Lookup Tables: Arrays serve as efficient lookup tables for quick element or relationship retrieval. For instance, mapping characters to ASCII codes becomes seamless by using the ASCII code values as indices and storing corresponding elements in the array.
  • Machine Learning: Within the domain of neural networks, arrays play a pivotal role in executing crucial linear algebra operations involving vectors, matrices, and tensors. Arrays serve as the primary and most extensively used data structure in neural network programming.
  • Data Structure Implementation: Arrays serve as the building blocks for implementing various data structures like stacks, queues, hash tables, heaps, graphs, etc. For instance, the adjacency matrix representation of a graph is essentially a two-dimensional array.
"},{"location":"chapter_array_and_linkedlist/linked_list/","title":"4.2 \u00a0 Linked Lists","text":"

Memory space is a common resource for all programs. In a complex system environment, free memory space can be scattered throughout memory. We know that the memory space for storing an array must be contiguous, and when the array is very large, it may not be possible to provide such a large contiguous space. This is where the flexibility advantage of linked lists becomes apparent.

A \"linked list\" is a linear data structure where each element is a node object, and the nodes are connected via \"references\". A reference records the memory address of the next node, allowing access to the next node from the current one.

The design of a linked list allows its nodes to be scattered throughout memory, with no need for contiguous memory addresses.

Figure 4-5 \u00a0 Linked List Definition and Storage Method

Observing the image above, the fundamental unit of a linked list is the \"node\" object. Each node contains two pieces of data: the \"value\" of the node and the \"reference\" to the next node.

  • The first node of a linked list is known as the \"head node\", and the last one is called the \"tail node\".
  • The tail node points to \"null\", which is represented as null in Java, nullptr in C++, and None in Python.
  • In languages that support pointers, like C, C++, Go, and Rust, the aforementioned \"reference\" should be replaced with a \"pointer\".

As shown in the following code, a linked list node ListNode, apart from containing a value, also needs to store a reference (pointer). Therefore, a linked list consumes more memory space than an array for the same amount of data.

PythonC++JavaC#GoSwiftJSTSDartRustCZig
class ListNode:\n    \"\"\"Linked List Node Class\"\"\"\n    def __init__(self, val: int):\n        self.val: int = val               # Node value\n        self.next: ListNode | None = None # Reference to the next node\n
/* Linked List Node Structure */\nstruct ListNode {\n    int val;         // Node value\n    ListNode *next;  // Pointer to the next node\n    ListNode(int x) : val(x), next(nullptr) {}  // Constructor\n};\n
/* Linked List Node Class */\nclass ListNode {\n    int val;        // Node value\n    ListNode next;  // Reference to the next node\n    ListNode(int x) { val = x; }  // Constructor\n}\n
/* Linked List Node Class */\nclass ListNode(int x) {  // Constructor\n    int val = x;         // Node value\n    ListNode? next;      // Reference to the next node\n}\n
/* Linked List Node Structure */\ntype ListNode struct {\n    Val  int       // Node value\n    Next *ListNode // Pointer to the next node\n}\n\n// NewListNode Constructor, creates a new linked list\nfunc NewListNode(val int) *ListNode {\n    return &ListNode{\n        Val:  val,\n        Next: nil,\n    }\n}\n
/* Linked List Node Class */\nclass ListNode {\n    var val: Int // Node value\n    var next: ListNode? // Reference to the next node\n\n    init(x: Int) { // Constructor\n        val = x\n    }\n}\n
/* Linked List Node Class */\nclass ListNode {\n    constructor(val, next) {\n        this.val = (val === undefined ? 0 : val);       // Node value\n        this.next = (next === undefined ? null : next); // Reference to the next node\n    }\n}\n
/* Linked List Node Class */\nclass ListNode {\n    val: number;\n    next: ListNode | null;\n    constructor(val?: number, next?: ListNode | null) {\n        this.val = val === undefined ? 0 : val;        // Node value\n        this.next = next === undefined ? null : next;  // Reference to the next node\n    }\n}\n
/* \u94fe\u8868\u8282\u70b9\u7c7b */\nclass ListNode {\n  int val; // Node value\n  ListNode? next; // Reference to the next node\n  ListNode(this.val, [this.next]); // Constructor\n}\n
use std::rc::Rc;\nuse std::cell::RefCell;\n/* Linked List Node Class */\n#[derive(Debug)]\nstruct ListNode {\n    val: i32, // Node value\n    next: Option<Rc<RefCell<ListNode>>>, // Pointer to the next node\n}\n
/* Linked List Node Structure */\ntypedef struct ListNode {\n    int val;               // Node value\n    struct ListNode *next; // Pointer to the next node\n} ListNode;\n\n/* Constructor */\nListNode *newListNode(int val) {\n    ListNode *node;\n    node = (ListNode *) malloc(sizeof(ListNode));\n    node->val = val;\n    node->next = NULL;\n    return node;\n}\n
// Linked List Node Class\npub fn ListNode(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        val: T = 0, // Node value\n        next: ?*Self = null, // Pointer to the next node\n\n        // Constructor\n        pub fn init(self: *Self, x: i32) void {\n            self.val = x;\n            self.next = null;\n        }\n    };\n}\n
"},{"location":"chapter_array_and_linkedlist/linked_list/#421-common-operations-on-linked-lists","title":"4.2.1 \u00a0 Common Operations on Linked Lists","text":""},{"location":"chapter_array_and_linkedlist/linked_list/#1-initializing-a-linked-list","title":"1. \u00a0 Initializing a Linked List","text":"

Building a linked list involves two steps: initializing each node object and then establishing the references between nodes. Once initialized, we can access all nodes sequentially from the head node via the next reference.

PythonC++JavaC#GoSwiftJSTSDartRustCZig linked_list.py
# Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4\n# Initialize each node\nn0 = ListNode(1)\nn1 = ListNode(3)\nn2 = ListNode(2)\nn3 = ListNode(5)\nn4 = ListNode(4)\n# Build references between nodes\nn0.next = n1\nn1.next = n2\nn2.next = n3\nn3.next = n4\n
linked_list.cpp
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nListNode* n0 = new ListNode(1);\nListNode* n1 = new ListNode(3);\nListNode* n2 = new ListNode(2);\nListNode* n3 = new ListNode(5);\nListNode* n4 = new ListNode(4);\n// Build references between nodes\nn0->next = n1;\nn1->next = n2;\nn2->next = n3;\nn3->next = n4;\n
linked_list.java
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nListNode n0 = new ListNode(1);\nListNode n1 = new ListNode(3);\nListNode n2 = new ListNode(2);\nListNode n3 = new ListNode(5);\nListNode n4 = new ListNode(4);\n// Build references between nodes\nn0.next = n1;\nn1.next = n2;\nn2.next = n3;\nn3.next = n4;\n
linked_list.cs
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nListNode n0 = new(1);\nListNode n1 = new(3);\nListNode n2 = new(2);\nListNode n3 = new(5);\nListNode n4 = new(4);\n// Build references between nodes\nn0.next = n1;\nn1.next = n2;\nn2.next = n3;\nn3.next = n4;\n
linked_list.go
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nn0 := NewListNode(1)\nn1 := NewListNode(3)\nn2 := NewListNode(2)\nn3 := NewListNode(5)\nn4 := NewListNode(4)\n// Build references between nodes\nn0.Next = n1\nn1.Next = n2\nn2.Next = n3\nn3.Next = n4\n
linked_list.swift
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nlet n0 = ListNode(x: 1)\nlet n1 = ListNode(x: 3)\nlet n2 = ListNode(x: 2)\nlet n3 = ListNode(x: 5)\nlet n4 = ListNode(x: 4)\n// Build references between nodes\nn0.next = n1\nn1.next = n2\nn2.next = n3\nn3.next = n4\n
linked_list.js
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nconst n0 = new ListNode(1);\nconst n1 = new ListNode(3);\nconst n2 = new ListNode(2);\nconst n3 = new ListNode(5);\nconst n4 = new ListNode(4);\n// Build references between nodes\nn0.next = n1;\nn1.next = n2;\nn2.next = n3;\nn3.next = n4;\n
linked_list.ts
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nconst n0 = new ListNode(1);\nconst n1 = new ListNode(3);\nconst n2 = new ListNode(2);\nconst n3 = new ListNode(5);\nconst n4 = new ListNode(4);\n// Build references between nodes\nn0.next = n1;\nn1.next = n2;\nn2.next = n3;\nn3.next = n4;\n
linked_list.dart
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nListNode n0 = ListNode(1);\nListNode n1 = ListNode(3);\nListNode n2 = ListNode(2);\nListNode n3 = ListNode(5);\nListNode n4 = ListNode(4);\n// Build references between nodes\nn0.next = n1;\nn1.next = n2;\nn2.next = n3;\nn3.next = n4;\n
linked_list.rs
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nlet n0 = Rc::new(RefCell::new(ListNode { val: 1, next: None }));\nlet n1 = Rc::new(RefCell::new(ListNode { val: 3, next: None }));\nlet n2 = Rc::new(RefCell::new(ListNode { val: 2, next: None }));\nlet n3 = Rc::new(RefCell::new(ListNode { val: 5, next: None }));\nlet n4 = Rc::new(RefCell::new(ListNode { val: 4, next: None }));\n\n// Build references between nodes\nn0.borrow_mut().next = Some(n1.clone());\nn1.borrow_mut().next = Some(n2.clone());\nn2.borrow_mut().next = Some(n3.clone());\nn3.borrow_mut().next = Some(n4.clone());\n
linked_list.c
/* Initialize linked list: 1 -> 3 -> 2 -> 5 -> 4 */\n// Initialize each node\nListNode* n0 = newListNode(1);\nListNode* n1 = newListNode(3);\nListNode* n2 = newListNode(2);\nListNode* n3 = newListNode(5);\nListNode* n4 = newListNode(4);\n// Build references between nodes\nn0->next = n1;\nn1->next = n2;\nn2->next = n3;\nn3->next = n4;\n
linked_list.zig
// Initialize linked list\n// Initialize each node\nvar n0 = inc.ListNode(i32){.val = 1};\nvar n1 = inc.ListNode(i32){.val = 3};\nvar n2 = inc.ListNode(i32){.val = 2};\nvar n3 = inc.ListNode(i32){.val = 5};\nvar n4 = inc.ListNode(i32){.val = 4};\n// Build references between nodes\nn0.next = &n1;\nn1.next = &n2;\nn2.next = &n3;\nn3.next = &n4;\n

An array is a single variable, such as the array nums containing elements nums[0], nums[1], etc., while a linked list is composed of multiple independent node objects. We usually refer to the linked list by its head node, as in the linked list n0 in the above code.

"},{"location":"chapter_array_and_linkedlist/linked_list/#2-inserting-a-node","title":"2. \u00a0 Inserting a Node","text":"

Inserting a node in a linked list is very easy. As shown in the image below, suppose we want to insert a new node P between two adjacent nodes n0 and n1. This requires changing only two node references (pointers), with a time complexity of \\(O(1)\\).

In contrast, the time complexity of inserting an element in an array is \\(O(n)\\), which is less efficient with large data volumes.

Figure 4-6 \u00a0 Linked List Node Insertion Example

PythonC++JavaC#GoSwiftJSTSDartRustCZig linked_list.py
def insert(n0: ListNode, P: ListNode):\n    \"\"\"\u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P\"\"\"\n    n1 = n0.next\n    P.next = n1\n    n0.next = P\n
linked_list.cpp
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nvoid insert(ListNode *n0, ListNode *P) {\n    ListNode *n1 = n0->next;\n    P->next = n1;\n    n0->next = P;\n}\n
linked_list.java
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nvoid insert(ListNode n0, ListNode P) {\n    ListNode n1 = n0.next;\n    P.next = n1;\n    n0.next = P;\n}\n
linked_list.cs
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nvoid Insert(ListNode n0, ListNode P) {\n    ListNode? n1 = n0.next;\n    P.next = n1;\n    n0.next = P;\n}\n
linked_list.go
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nfunc insertNode(n0 *ListNode, P *ListNode) {\n    n1 := n0.Next\n    P.Next = n1\n    n0.Next = P\n}\n
linked_list.swift
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nfunc insert(n0: ListNode, P: ListNode) {\n    let n1 = n0.next\n    P.next = n1\n    n0.next = P\n}\n
linked_list.js
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nfunction insert(n0, P) {\n    const n1 = n0.next;\n    P.next = n1;\n    n0.next = P;\n}\n
linked_list.ts
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nfunction insert(n0: ListNode, P: ListNode): void {\n    const n1 = n0.next;\n    P.next = n1;\n    n0.next = P;\n}\n
linked_list.dart
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nvoid insert(ListNode n0, ListNode P) {\n  ListNode? n1 = n0.next;\n  P.next = n1;\n  n0.next = P;\n}\n
linked_list.rs
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\n#[allow(non_snake_case)]\npub fn insert<T>(n0: &Rc<RefCell<ListNode<T>>>, P: Rc<RefCell<ListNode<T>>>) {\n    let n1 =  n0.borrow_mut().next.take();\n    P.borrow_mut().next = n1;\n    n0.borrow_mut().next = Some(P);\n}\n
linked_list.c
/* \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P */\nvoid insert(ListNode *n0, ListNode *P) {\n    ListNode *n1 = n0->next;\n    P->next = n1;\n    n0->next = P;\n}\n
linked_list.zig
// \u5728\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u63d2\u5165\u8282\u70b9 P\nfn insert(n0: ?*inc.ListNode(i32), P: ?*inc.ListNode(i32)) void {\n    var n1 = n0.?.next;\n    P.?.next = n1;\n    n0.?.next = P;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/linked_list/#3-deleting-a-node","title":"3. \u00a0 Deleting a Node","text":"

As shown below, deleting a node in a linked list is also very convenient, requiring only the change of one node's reference (pointer).

Note that although node P still points to n1 after the deletion operation is completed, it is no longer accessible when traversing the list, meaning P is no longer part of the list.

Figure 4-7 \u00a0 Linked List Node Deletion

PythonC++JavaC#GoSwiftJSTSDartRustCZig linked_list.py
def remove(n0: ListNode):\n    \"\"\"\u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9\"\"\"\n    if not n0.next:\n        return\n    # n0 -> P -> n1\n    P = n0.next\n    n1 = P.next\n    n0.next = n1\n
linked_list.cpp
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nvoid remove(ListNode *n0) {\n    if (n0->next == nullptr)\n        return;\n    // n0 -> P -> n1\n    ListNode *P = n0->next;\n    ListNode *n1 = P->next;\n    n0->next = n1;\n    // \u91ca\u653e\u5185\u5b58\n    delete P;\n}\n
linked_list.java
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nvoid remove(ListNode n0) {\n    if (n0.next == null)\n        return;\n    // n0 -> P -> n1\n    ListNode P = n0.next;\n    ListNode n1 = P.next;\n    n0.next = n1;\n}\n
linked_list.cs
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nvoid Remove(ListNode n0) {\n    if (n0.next == null)\n        return;\n    // n0 -> P -> n1\n    ListNode P = n0.next;\n    ListNode? n1 = P.next;\n    n0.next = n1;\n}\n
linked_list.go
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nfunc removeItem(n0 *ListNode) {\n    if n0.Next == nil {\n        return\n    }\n    // n0 -> P -> n1\n    P := n0.Next\n    n1 := P.Next\n    n0.Next = n1\n}\n
linked_list.swift
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nfunc remove(n0: ListNode) {\n    if n0.next == nil {\n        return\n    }\n    // n0 -> P -> n1\n    let P = n0.next\n    let n1 = P?.next\n    n0.next = n1\n    P?.next = nil\n}\n
linked_list.js
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nfunction remove(n0) {\n    if (!n0.next) return;\n    // n0 -> P -> n1\n    const P = n0.next;\n    const n1 = P.next;\n    n0.next = n1;\n}\n
linked_list.ts
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nfunction remove(n0: ListNode): void {\n    if (!n0.next) {\n        return;\n    }\n    // n0 -> P -> n1\n    const P = n0.next;\n    const n1 = P.next;\n    n0.next = n1;\n}\n
linked_list.dart
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\nvoid remove(ListNode n0) {\n  if (n0.next == null) return;\n  // n0 -> P -> n1\n  ListNode P = n0.next!;\n  ListNode? n1 = P.next;\n  n0.next = n1;\n}\n
linked_list.rs
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\n#[allow(non_snake_case)]\npub fn remove<T>(n0: &Rc<RefCell<ListNode<T>>>) {\n    if n0.borrow().next.is_none() {return};\n    // n0 -> P -> n1\n    let P = n0.borrow_mut().next.take();\n    if let Some(node) = P {\n        let n1 = node.borrow_mut().next.take();\n        n0.borrow_mut().next = n1;\n    }\n}\n
linked_list.c
/* \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9 */\n// \u6ce8\u610f\uff1astdio.h \u5360\u7528\u4e86 remove \u5173\u952e\u8bcd\nvoid removeItem(ListNode *n0) {\n    if (!n0->next)\n        return;\n    // n0 -> P -> n1\n    ListNode *P = n0->next;\n    ListNode *n1 = P->next;\n    n0->next = n1;\n    // \u91ca\u653e\u5185\u5b58\n    free(P);\n}\n
linked_list.zig
// \u5220\u9664\u94fe\u8868\u7684\u8282\u70b9 n0 \u4e4b\u540e\u7684\u9996\u4e2a\u8282\u70b9\nfn remove(n0: ?*inc.ListNode(i32)) void {\n    if (n0.?.next == null) return;\n    // n0 -> P -> n1\n    var P = n0.?.next;\n    var n1 = P.?.next;\n    n0.?.next = n1;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/linked_list/#4-accessing-nodes","title":"4. \u00a0 Accessing Nodes","text":"

Accessing nodes in a linked list is less efficient. As mentioned earlier, any element in an array can be accessed in \\(O(1)\\) time. However, in a linked list, the program needs to start from the head node and traverse each node sequentially until it finds the target node. That is, accessing the \\(i\\)-th node of a linked list requires \\(i - 1\\) iterations, with a time complexity of \\(O(n)\\).

PythonC++JavaC#GoSwiftJSTSDartRustCZig linked_list.py
def access(head: ListNode, index: int) -> ListNode | None:\n    \"\"\"\u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9\"\"\"\n    for _ in range(index):\n        if not head:\n            return None\n        head = head.next\n    return head\n
linked_list.cpp
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nListNode *access(ListNode *head, int index) {\n    for (int i = 0; i < index; i++) {\n        if (head == nullptr)\n            return nullptr;\n        head = head->next;\n    }\n    return head;\n}\n
linked_list.java
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nListNode access(ListNode head, int index) {\n    for (int i = 0; i < index; i++) {\n        if (head == null)\n            return null;\n        head = head.next;\n    }\n    return head;\n}\n
linked_list.cs
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nListNode? Access(ListNode? head, int index) {\n    for (int i = 0; i < index; i++) {\n        if (head == null)\n            return null;\n        head = head.next;\n    }\n    return head;\n}\n
linked_list.go
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nfunc access(head *ListNode, index int) *ListNode {\n    for i := 0; i < index; i++ {\n        if head == nil {\n            return nil\n        }\n        head = head.Next\n    }\n    return head\n}\n
linked_list.swift
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nfunc access(head: ListNode, index: Int) -> ListNode? {\n    var head: ListNode? = head\n    for _ in 0 ..< index {\n        if head == nil {\n            return nil\n        }\n        head = head?.next\n    }\n    return head\n}\n
linked_list.js
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nfunction access(head, index) {\n    for (let i = 0; i < index; i++) {\n        if (!head) {\n            return null;\n        }\n        head = head.next;\n    }\n    return head;\n}\n
linked_list.ts
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nfunction access(head: ListNode | null, index: number): ListNode | null {\n    for (let i = 0; i < index; i++) {\n        if (!head) {\n            return null;\n        }\n        head = head.next;\n    }\n    return head;\n}\n
linked_list.dart
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nListNode? access(ListNode? head, int index) {\n  for (var i = 0; i < index; i++) {\n    if (head == null) return null;\n    head = head.next;\n  }\n  return head;\n}\n
linked_list.rs
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\npub fn access<T>(head: Rc<RefCell<ListNode<T>>>, index: i32) -> Rc<RefCell<ListNode<T>>> {\n    if index <= 0 {return head};\n    if let Some(node) = &head.borrow_mut().next {\n        return access(node.clone(), index - 1);\n    }\n    return head;\n}\n
linked_list.c
/* \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9 */\nListNode *access(ListNode *head, int index) {\n    for (int i = 0; i < index; i++) {\n        if (head == NULL)\n            return NULL;\n        head = head->next;\n    }\n    return head;\n}\n
linked_list.zig
// \u8bbf\u95ee\u94fe\u8868\u4e2d\u7d22\u5f15\u4e3a index \u7684\u8282\u70b9\nfn access(node: ?*inc.ListNode(i32), index: i32) ?*inc.ListNode(i32) {\n    var head = node;\n    var i: i32 = 0;\n    while (i < index) : (i += 1) {\n        head = head.?.next;\n        if (head == null) return null;\n    }\n    return head;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/linked_list/#5-finding-nodes","title":"5. \u00a0 Finding Nodes","text":"

Traverse the linked list to find a node with a value equal to target, and output the index of that node in the linked list. This process also falls under linear search. The code is as follows:

PythonC++JavaC#GoSwiftJSTSDartRustCZig linked_list.py
def find(head: ListNode, target: int) -> int:\n    \"\"\"\u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9\"\"\"\n    index = 0\n    while head:\n        if head.val == target:\n            return index\n        head = head.next\n        index += 1\n    return -1\n
linked_list.cpp
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nint find(ListNode *head, int target) {\n    int index = 0;\n    while (head != nullptr) {\n        if (head->val == target)\n            return index;\n        head = head->next;\n        index++;\n    }\n    return -1;\n}\n
linked_list.java
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nint find(ListNode head, int target) {\n    int index = 0;\n    while (head != null) {\n        if (head.val == target)\n            return index;\n        head = head.next;\n        index++;\n    }\n    return -1;\n}\n
linked_list.cs
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nint Find(ListNode? head, int target) {\n    int index = 0;\n    while (head != null) {\n        if (head.val == target)\n            return index;\n        head = head.next;\n        index++;\n    }\n    return -1;\n}\n
linked_list.go
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nfunc findNode(head *ListNode, target int) int {\n    index := 0\n    for head != nil {\n        if head.Val == target {\n            return index\n        }\n        head = head.Next\n        index++\n    }\n    return -1\n}\n
linked_list.swift
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nfunc find(head: ListNode, target: Int) -> Int {\n    var head: ListNode? = head\n    var index = 0\n    while head != nil {\n        if head?.val == target {\n            return index\n        }\n        head = head?.next\n        index += 1\n    }\n    return -1\n}\n
linked_list.js
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nfunction find(head, target) {\n    let index = 0;\n    while (head !== null) {\n        if (head.val === target) {\n            return index;\n        }\n        head = head.next;\n        index += 1;\n    }\n    return -1;\n}\n
linked_list.ts
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nfunction find(head: ListNode | null, target: number): number {\n    let index = 0;\n    while (head !== null) {\n        if (head.val === target) {\n            return index;\n        }\n        head = head.next;\n        index += 1;\n    }\n    return -1;\n}\n
linked_list.dart
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nint find(ListNode? head, int target) {\n  int index = 0;\n  while (head != null) {\n    if (head.val == target) {\n      return index;\n    }\n    head = head.next;\n    index++;\n  }\n  return -1;\n}\n
linked_list.rs
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\npub fn find<T: PartialEq>(head: Rc<RefCell<ListNode<T>>>, target: T, index: i32) -> i32 {\n    if head.borrow().val == target {return index};\n    if let Some(node) = &head.borrow_mut().next {\n        return find(node.clone(), target, index + 1);\n    }\n    return -1;\n}\n
linked_list.c
/* \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9 */\nint find(ListNode *head, int target) {\n    int index = 0;\n    while (head) {\n        if (head->val == target)\n            return index;\n        head = head->next;\n        index++;\n    }\n    return -1;\n}\n
linked_list.zig
// \u5728\u94fe\u8868\u4e2d\u67e5\u627e\u503c\u4e3a target \u7684\u9996\u4e2a\u8282\u70b9\nfn find(node: ?*inc.ListNode(i32), target: i32) i32 {\n    var head = node;\n    var index: i32 = 0;\n    while (head != null) {\n        if (head.?.val == target) return index;\n        head = head.?.next;\n        index += 1;\n    }\n    return -1;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/linked_list/#422-arrays-vs-linked-lists","title":"4.2.2 \u00a0 Arrays vs. Linked Lists","text":"

The following table summarizes the characteristics of arrays and linked lists and compares their operational efficiencies. Since they employ two opposite storage strategies, their properties and operational efficiencies also show contrasting features.

Table 4-1 \u00a0 Efficiency Comparison of Arrays and Linked Lists

Arrays Linked Lists Storage Contiguous Memory Space Dispersed Memory Space Capacity Expansion Fixed Length Flexible Expansion Memory Efficiency Less Memory per Element, Potential Space Wastage More Memory per Element Accessing Elements \\(O(1)\\) \\(O(n)\\) Adding Elements \\(O(n)\\) \\(O(1)\\) Deleting Elements \\(O(n)\\) \\(O(1)\\)"},{"location":"chapter_array_and_linkedlist/linked_list/#423-common-types-of-linked-lists","title":"4.2.3 \u00a0 Common Types of Linked Lists","text":"

As shown in the following image, there are three common types of linked lists.

  • Singly Linked List: This is the regular linked list introduced earlier. The nodes of a singly linked list contain the value and a reference to the next node. The first node is called the head node, and the last node, pointing to null (None), is the tail node.
  • Circular Linked List: If the tail node of a singly linked list points back to the head node (forming a loop), it becomes a circular linked list. In a circular linked list, any node can be considered the head node.
  • Doubly Linked List: Compared to a singly linked list, a doubly linked list stores references in two directions. Its nodes contain references to both the next (successor) and the previous (predecessor) nodes. Doubly linked lists are more flexible as they allow traversal in both directions but require more memory space.
PythonC++JavaC#GoSwiftJSTSDartRustCZig
class ListNode:\n    \"\"\"Bidirectional linked list node class\"\"\"\"\n    def __init__(self, val: int):\n        self.val: int = val                # Node value\n        self.next: ListNode | None = None  # Reference to the successor node\n        self.prev: ListNode | None = None  # Reference to a predecessor node\n
/* Bidirectional linked list node structure */\nstruct ListNode {\n    int val;         // Node value\n    ListNode *next;  // Pointer to the successor node\n    ListNode *prev;  // Pointer to the predecessor node\n    ListNode(int x) : val(x), next(nullptr), prev(nullptr) {}  // Constructor\n};\n
/* Bidirectional linked list node class */\nclass ListNode {\n    int val;        // Node value\n    ListNode next;  // Reference to the next node\n    ListNode prev;  // Reference to the predecessor node\n    ListNode(int x) { val = x; }  // Constructor\n}\n
/* Bidirectional linked list node class */\nclass ListNode(int x) {  // Constructor\n    int val = x;    // Node value\n    ListNode next;  // Reference to the next node\n    ListNode prev;  // Reference to the predecessor node\n}\n
/* Bidirectional linked list node structure */\ntype DoublyListNode struct {\n    Val  int             // Node value\n    Next *DoublyListNode // Pointer to the successor node\n    Prev *DoublyListNode // Pointer to the predecessor node\n}\n\n// NewDoublyListNode initialization\nfunc NewDoublyListNode(val int) *DoublyListNode {\n    return &DoublyListNode{\n        Val:  val,\n        Next: nil,\n        Prev: nil,\n    }\n}\n
/* Bidirectional linked list node class */\nclass ListNode {\n    var val: Int // Node value\n    var next: ListNode? // Reference to the next node\n    var prev: ListNode? // Reference to the predecessor node\n\n    init(x: Int) { // Constructor\n        val = x\n    }\n}\n
/* Bidirectional linked list node class */\nclass ListNode {\n    constructor(val, next, prev) {\n        this.val = val  ===  undefined ? 0 : val;        // Node value\n        this.next = next  ===  undefined ? null : next;  // Reference to the successor node\n        this.prev = prev  ===  undefined ? null : prev;  // Reference to the predecessor node\n    }\n}\n
/* Bidirectional linked list node class */\nclass ListNode {\n    val: number;\n    next: ListNode | null;\n    prev: ListNode | null;\n    constructor(val?: number, next?: ListNode | null, prev?: ListNode | null) {\n        this.val = val  ===  undefined ? 0 : val;        // Node value\n        this.next = next  ===  undefined ? null : next;  // Reference to the successor node\n        this.prev = prev  ===  undefined ? null : prev;  // Reference to the predecessor node\n    }\n}\n
/* Bidirectional linked list node class */\nclass ListNode {\n    int val;        // Node value\n    ListNode next;  // Reference to the next node\n    ListNode prev;  // Reference to the predecessor node\n    ListNode(this.val, [this.next, this.prev]);  // Constructor\n}\n
use std::rc::Rc;\nuse std::cell::RefCell;\n\n/* Bidirectional linked list node type */\n#[derive(Debug)]\nstruct ListNode {\n    val: i32, // Node value\n    next: Option<Rc<RefCell<ListNode>>>, // Pointer to successor node\n    prev: Option<Rc<RefCell<ListNode>>>, // Pointer to predecessor node\n}\n\n/* Constructors */\nimpl ListNode {\n    fn new(val: i32) -> Self {\n        ListNode {\n            val,\n            next: None,\n            prev: None,\n        }\n    }\n}\n
/* Bidirectional linked list node structure */\ntypedef struct ListNode {\n    int val;               // Node value\n    struct ListNode *next; // Pointer to the successor node\n    struct ListNode *prev; // Pointer to the predecessor node\n} ListNode;\n\n/* Constructors */\nListNode *newListNode(int val) {\n    ListNode *node, *next;\n    node = (ListNode *) malloc(sizeof(ListNode));\n    node->val = val;\n    node->next = NULL;\n    node->prev = NULL;\n    return node;\n}\n
// Bidirectional linked list node class\npub fn ListNode(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        val: T = 0, // Node value\n        next: ?*Self = null, // Pointer to the successor node\n        prev: ?*Self = null, // Pointer to the predecessor node\n\n        // Constructor\n        pub fn init(self: *Self, x: i32) void {\n            self.val = x;\n            self.next = null;\n            self.prev = null;\n        }\n    };\n}\n

Figure 4-8 \u00a0 Common Types of Linked Lists

"},{"location":"chapter_array_and_linkedlist/linked_list/#424-typical-applications-of-linked-lists","title":"4.2.4 \u00a0 Typical Applications of Linked Lists","text":"

Singly linked lists are commonly used to implement stacks, queues, hash tables, and graphs.

  • Stacks and Queues: When insertion and deletion operations are performed at one end of the linked list, it exhibits last-in-first-out characteristics, corresponding to a stack. When insertion is at one end and deletion is at the other, it shows first-in-first-out characteristics, corresponding to a queue.
  • Hash Tables: Chaining is one of the mainstream solutions to hash collisions, where all colliding elements are placed in a linked list.
  • Graphs: Adjacency lists are a common way to represent graphs, where each vertex is associated with a linked list. Each element in the list represents other vertices connected to that vertex.

Doubly linked lists are commonly used in scenarios that require quick access to the previous and next elements.

  • Advanced Data Structures: For example, in red-black trees and B-trees, we need to access a node's parent, which can be achieved by storing a reference to the parent node in each node, similar to a doubly linked list.
  • Browser History: In web browsers, when a user clicks the forward or backward button, the browser needs to know the previously and next visited web pages. The properties of a doubly linked list make this operation simple.
  • LRU Algorithm: In Least Recently Used (LRU) cache eviction algorithms, we need to quickly find the least recently used data and support rapid addition and deletion of nodes. Here, using a doubly linked list is very appropriate.

Circular linked lists are commonly used in scenarios requiring periodic operations, such as resource scheduling in operating systems.

  • Round-Robin Scheduling Algorithm: In operating systems, the round-robin scheduling algorithm is a common CPU scheduling algorithm that cycles through a group of processes. Each process is assigned a time slice, and when it expires, the CPU switches to the next process. This circular operation can be implemented using a circular linked list.
  • Data Buffers: Circular linked lists may also be used in some data buffer implementations. For instance, in audio and video players, the data stream might be divided into multiple buffer blocks placed in a circular linked list to achieve seamless playback.
"},{"location":"chapter_array_and_linkedlist/list/","title":"4.3 \u00a0 List","text":"

A \"list\" is an abstract data structure concept, representing an ordered collection of elements. It supports operations like element access, modification, addition, deletion, and traversal, without requiring users to consider capacity limitations. Lists can be implemented based on linked lists or arrays.

  • A linked list naturally functions as a list, supporting operations for adding, deleting, searching, and modifying elements, and can dynamically adjust its size.
  • Arrays also support these operations, but due to their fixed length, they can be considered as a list with a length limit.

When using arrays to implement lists, the fixed length property reduces the practicality of the list. This is because we often cannot determine in advance how much data needs to be stored, making it difficult to choose an appropriate list length. If the length is too small, it may not meet the requirements; if too large, it may waste memory space.

To solve this problem, we can use a \"dynamic array\" to implement lists. It inherits the advantages of arrays and can dynamically expand during program execution.

In fact, many programming languages' standard libraries implement lists using dynamic arrays, such as Python's list, Java's ArrayList, C++'s vector, and C#'s List. In the following discussion, we will consider \"list\" and \"dynamic array\" as synonymous concepts.

"},{"location":"chapter_array_and_linkedlist/list/#431-common-list-operations","title":"4.3.1 \u00a0 Common List Operations","text":""},{"location":"chapter_array_and_linkedlist/list/#1-initializing-a-list","title":"1. \u00a0 Initializing a List","text":"

We typically use two methods of initialization: \"without initial values\" and \"with initial values\".

PythonC++JavaC#GoSwiftJSTSDartRustCZig list.py
# Initialize list\n# Without initial values\nnums1: list[int] = []\n# With initial values\nnums: list[int] = [1, 3, 2, 5, 4]\n
list.cpp
/* Initialize list */\n// Note, in C++ the vector is the equivalent of nums described here\n// Without initial values\nvector<int> nums1;\n// With initial values\nvector<int> nums = { 1, 3, 2, 5, 4 };\n
list.java
/* Initialize list */\n// Without initial values\nList<Integer> nums1 = new ArrayList<>();\n// With initial values (note the element type should be the wrapper class Integer[] for int[])\nInteger[] numbers = new Integer[] { 1, 3, 2, 5, 4 };\nList<Integer> nums = new ArrayList<>(Arrays.asList(numbers));\n
list.cs
/* Initialize list */\n// Without initial values\nList<int> nums1 = [];\n// With initial values\nint[] numbers = [1, 3, 2, 5, 4];\nList<int> nums = [.. numbers];\n
list_test.go
/* Initialize list */\n// Without initial values\nnums1 := []int{}\n// With initial values\nnums := []int{1, 3, 2, 5, 4}\n
list.swift
/* Initialize list */\n// Without initial values\nlet nums1: [Int] = []\n// With initial values\nvar nums = [1, 3, 2, 5, 4]\n
list.js
/* Initialize list */\n// Without initial values\nconst nums1 = [];\n// With initial values\nconst nums = [1, 3, 2, 5, 4];\n
list.ts
/* Initialize list */\n// Without initial values\nconst nums1: number[] = [];\n// With initial values\nconst nums: number[] = [1, 3, 2, 5, 4];\n
list.dart
/* Initialize list */\n// Without initial values\nList<int> nums1 = [];\n// With initial values\nList<int> nums = [1, 3, 2, 5, 4];\n
list.rs
/* Initialize list */\n// Without initial values\nlet nums1: Vec<i32> = Vec::new();\n// With initial values\nlet nums: Vec<i32> = vec![1, 3, 2, 5, 4];\n
list.c
// C does not provide built-in dynamic arrays\n
list.zig
// Initialize list\nvar nums = std.ArrayList(i32).init(std.heap.page_allocator);\ndefer nums.deinit();\ntry nums.appendSlice(&[_]i32{ 1, 3, 2, 5, 4 });\n
"},{"location":"chapter_array_and_linkedlist/list/#2-accessing-elements","title":"2. \u00a0 Accessing Elements","text":"

Lists are essentially arrays, so accessing and updating elements can be done in \\(O(1)\\) time, which is very efficient.

PythonC++JavaC#GoSwiftJSTSDartRustCZig list.py
# Access elements\nnum: int = nums[1]  # Access the element at index 1\n\n# Update elements\nnums[1] = 0    # Update the element at index 1 to 0\n
list.cpp
/* Access elements */\nint num = nums[1];  // Access the element at index 1\n\n/* Update elements */\nnums[1] = 0;  // Update the element at index 1 to 0\n
list.java
/* Access elements */\nint num = nums.get(1);  // Access the element at index 1\n\n/* Update elements */\nnums.set(1, 0);  // Update the element at index 1 to 0\n
list.cs
/* Access elements */\nint num = nums[1];  // Access the element at index 1\n\n/* Update elements */\nnums[1] = 0;  // Update the element at index 1 to 0\n
list_test.go
/* Access elements */\nnum := nums[1]  // Access the element at index 1\n\n/* Update elements */\nnums[1] = 0     // Update the element at index 1 to 0\n
list.swift
/* Access elements */\nlet num = nums[1] // Access the element at index 1\n\n/* Update elements */\nnums[1] = 0 // Update the element at index 1 to 0\n
list.js
/* Access elements */\nconst num = nums[1];  // Access the element at index 1\n\n/* Update elements */\nnums[1] = 0;  // Update the element at index 1 to 0\n
list.ts
/* Access elements */\nconst num: number = nums[1];  // Access the element at index 1\n\n/* Update elements */\nnums[1] = 0;  // Update the element at index 1 to 0\n
list.dart
/* Access elements */\nint num = nums[1];  // Access the element at index 1\n\n/* Update elements */\nnums[1] = 0;  // Update the element at index 1 to 0\n
list.rs
/* Access elements */\nlet num: i32 = nums[1];  // Access the element at index 1\n/* Update elements */\nnums[1] = 0;             // Update the element at index 1 to 0\n
list.c
// C does not provide built-in dynamic arrays\n
list.zig
// Access elements\nvar num = nums.items[1]; // Access the element at index 1\n\n// Update elements\nnums.items[1] = 0; // Update the element at index 1 to 0  \n
"},{"location":"chapter_array_and_linkedlist/list/#3-inserting-and-deleting-elements","title":"3. \u00a0 Inserting and Deleting Elements","text":"

Compared to arrays, lists can freely add and remove elements. Adding elements at the end of the list has a time complexity of \\(O(1)\\), but the efficiency of inserting and deleting elements is still the same as in arrays, with a time complexity of \\(O(n)\\).

PythonC++JavaC#GoSwiftJSTSDartRustCZig list.py
# Clear list\nnums.clear()\n\n# Append elements at the end\nnums.append(1)\nnums.append(3)\nnums.append(2)\nnums.append(5)\nnums.append(4)\n\n# Insert element in the middle\nnums.insert(3, 6)  # Insert number 6 at index 3\n\n# Remove elements\nnums.pop(3)        # Remove the element at index 3\n
list.cpp
/* Clear list */\nnums.clear();\n\n/* Append elements at the end */\nnums.push_back(1);\nnums.push_back(3);\nnums.push_back(2);\nnums.push_back(5);\nnums.push_back(4);\n\n/* Insert element in the middle */\nnums.insert(nums.begin() + 3, 6);  // Insert number 6 at index 3\n\n/* Remove elements */\nnums.erase(nums.begin() + 3);      // Remove the element at index 3\n
list.java
/* Clear list */\nnums.clear();\n\n/* Append elements at the end */\nnums.add(1);\nnums.add(3);\nnums.add(2);\nnums.add(5);\nnums.add(4);\n\n/* Insert element in the middle */\nnums.add(3, 6);  // Insert number 6 at index 3\n\n/* Remove elements */\nnums.remove(3);  // Remove the element at index 3\n
list.cs
/* Clear list */\nnums.Clear();\n\n/* Append elements at the end */\nnums.Add(1);\nnums.Add(3);\nnums.Add(2);\nnums.Add(5);\nnums.Add(4);\n\n/* Insert element in the middle */\nnums.Insert(3, 6);\n\n/* Remove elements */\nnums.RemoveAt(3);\n
list_test.go
/* Clear list */\nnums = nil\n\n/* Append elements at the end */\nnums = append(nums, 1)\nnums = append(nums, 3)\nnums = append(nums, 2)\nnums = append(nums, 5)\nnums = append(nums, 4)\n\n/* Insert element in the middle */\nnums = append(nums[:3], append([]int{6}, nums[3:]...)...) // Insert number 6 at index 3\n\n/* Remove elements */\nnums = append(nums[:3], nums[4:]...) // Remove the element at index 3\n
list.swift
/* Clear list */\nnums.removeAll()\n\n/* Append elements at the end */\nnums.append(1)\nnums.append(3)\nnums.append(2)\nnums.append(5)\nnums.append(4)\n\n/* Insert element in the middle */\nnums.insert(6, at: 3) // Insert number 6 at index 3\n\n/* Remove elements */\nnums.remove(at: 3) // Remove the element at index 3\n
list.js
/* Clear list */\nnums.length = 0;\n\n/* Append elements at the end */\nnums.push(1);\nnums.push(3);\nnums.push(2);\nnums.push(5);\nnums.push(4);\n\n/* Insert element in the middle */\nnums.splice(3, 0, 6);\n\n/* Remove elements */\nnums.splice(3, 1);\n
list.ts
/* Clear list */\nnums.length = 0;\n\n/* Append elements at the end */\nnums.push(1);\nnums.push(3);\nnums.push(2);\nnums.push(5);\nnums.push(4);\n\n/* Insert element in the middle */\nnums.splice(3, 0, 6);\n\n/* Remove elements */\nnums.splice(3, 1);\n
list.dart
/* Clear list */\nnums.clear();\n\n/* Append elements at the end */\nnums.add(1);\nnums.add(3);\nnums.add(2);\nnums.add(5);\nnums.add(4);\n\n/* Insert element in the middle */\nnums.insert(3, 6); // Insert number 6 at index 3\n\n/* Remove elements */\nnums.removeAt(3); // Remove the element at index 3\n
list.rs
/* Clear list */\nnums.clear();\n\n/* Append elements at the end */\nnums.push(1);\nnums.push(3);\nnums.push(2);\nnums.push(5);\nnums.push(4);\n\n/* Insert element in the middle */\nnums.insert(3, 6);  // Insert number 6 at index 3\n\n/* Remove elements */\nnums.remove(3);    // Remove the element at index 3\n
list.c
// C does not provide built-in dynamic arrays\n
list.zig
// Clear list\nnums.clearRetainingCapacity();\n\n// Append elements at the end\ntry nums.append(1);\ntry nums.append(3);\ntry nums.append(2);\ntry nums.append(5);\ntry nums.append(4);\n\n// Insert element in the middle\ntry nums.insert(3, 6); // Insert number 6 at index 3\n\n// Remove elements\n_ = nums.orderedRemove(3); // Remove the element at index 3\n
"},{"location":"chapter_array_and_linkedlist/list/#4-traversing-the-list","title":"4. \u00a0 Traversing the List","text":"

Like arrays, lists can be traversed based on index, or by directly iterating over each element.

PythonC++JavaC#GoSwiftJSTSDartRustCZig list.py
# Iterate through the list by index\ncount = 0\nfor i in range(len(nums)):\n    count += nums[i]\n\n# Iterate directly through list elements\nfor num in nums:\n    count += num\n
list.cpp
/* Iterate through the list by index */\nint count = 0;\nfor (int i = 0; i < nums.size(); i++) {\n    count += nums[i];\n}\n\n/* Iterate directly through list elements */\ncount = 0;\nfor (int num : nums) {\n    count += num;\n}\n
list.java
/* Iterate through the list by index */\nint count = 0;\nfor (int i = 0; i < nums.size(); i++) {\n    count += nums.get(i);\n}\n\n/* Iterate directly through list elements */\nfor (int num : nums) {\n    count += num;\n}\n
list.cs
/* Iterate through the list by index */\nint count = 0;\nfor (int i = 0; i < nums.Count; i++) {\n    count += nums[i];\n}\n\n/* Iterate directly through list elements */\ncount = 0;\nforeach (int num in nums) {\n    count += num;\n}\n
list_test.go
/* Iterate through the list by index */\ncount := 0\nfor i := 0; i < len(nums); i++ {\n    count += nums[i]\n}\n\n/* Iterate directly through list elements */\ncount = 0\nfor _, num := range nums {\n    count += num\n}\n
list.swift
/* Iterate through the list by index */\nvar count = 0\nfor i in nums.indices {\n    count += nums[i]\n}\n\n/* Iterate directly through list elements */\ncount = 0\nfor num in nums {\n    count += num\n}\n
list.js
/* Iterate through the list by index */\nlet count = 0;\nfor (let i = 0; i < nums.length; i++) {\n    count += nums[i];\n}\n\n/* Iterate directly through list elements */\ncount = 0;\nfor (const num of nums) {\n    count += num;\n}\n
list.ts
/* Iterate through the list by index */\nlet count = 0;\nfor (let i = 0; i < nums.length; i++) {\n    count += nums[i];\n}\n\n/* Iterate directly through list elements */\ncount = 0;\nfor (const num of nums) {\n    count += num;\n}\n
list.dart
/* Iterate through the list by index */\nint count = 0;\nfor (var i = 0; i < nums.length; i++) {\n    count += nums[i];\n}\n\n/* Iterate directly through list elements */\ncount = 0;\nfor (var num in nums) {\n    count += num;\n}\n
list.rs
// Iterate through the list by index\nlet mut _count = 0;\nfor i in 0..nums.len() {\n    _count += nums[i];\n}\n\n// Iterate directly through list elements\n_count = 0;\nfor num in &nums {\n    _count += num;\n}\n
list.c
// C does not provide built-in dynamic arrays\n
list.zig
// Iterate through the list by index\nvar count: i32 = 0;\nvar i: i32 = 0;\nwhile (i < nums.items.len) : (i += 1) {\n    count += nums[i];\n}\n\n// Iterate directly through list elements\ncount = 0;\nfor (nums.items) |num| {\n    count += num;\n}\n
"},{"location":"chapter_array_and_linkedlist/list/#5-concatenating-lists","title":"5. \u00a0 Concatenating Lists","text":"

Given a new list nums1, we can append it to the end of the original list.

PythonC++JavaC#GoSwiftJSTSDartRustCZig list.py
# Concatenate two lists\nnums1: list[int] = [6, 8, 7, 10, 9]\nnums += nums1  # Concatenate nums1 to the end of nums\n
list.cpp
/* Concatenate two lists */\nvector<int> nums1 = { 6, 8, 7, 10, 9 };\n// Concatenate nums1 to the end of nums\nnums.insert(nums.end(), nums1.begin(), nums1.end());\n
list.java
/* Concatenate two lists */\nList<Integer> nums1 = new ArrayList<>(Arrays.asList(new Integer[] { 6, 8, 7, 10, 9 }));\nnums.addAll(nums1);  // Concatenate nums1 to the end of nums\n
list.cs
/* Concatenate two lists */\nList<int> nums1 = [6, 8, 7, 10, 9];\nnums.AddRange(nums1);  // Concatenate nums1 to the end of nums\n
list_test.go
/* Concatenate two lists */\nnums1 := []int{6, 8, 7, 10, 9}\nnums = append(nums, nums1...)  // Concatenate nums1 to the end of nums\n
list.swift
/* Concatenate two lists */\nlet nums1 = [6, 8, 7, 10, 9]\nnums.append(contentsOf: nums1) // Concatenate nums1 to the end of nums\n
list.js
/* Concatenate two lists */\nconst nums1 = [6, 8, 7, 10, 9];\nnums.push(...nums1);  // Concatenate nums1 to the end of nums\n
list.ts
/* Concatenate two lists */\nconst nums1: number[] = [6, 8, 7, 10, 9];\nnums.push(...nums1);  // Concatenate nums1 to the end of nums\n
list.dart
/* Concatenate two lists */\nList<int> nums1 = [6, 8, 7, 10, 9];\nnums.addAll(nums1);  // Concatenate nums1 to the end of nums\n
list.rs
/* Concatenate two lists */\nlet nums1: Vec<i32> = vec![6, 8, 7, 10, 9];\nnums.extend(nums1);\n
list.c
// C does not provide built-in dynamic arrays\n
list.zig
// Concatenate two lists\nvar nums1 = std.ArrayList(i32).init(std.heap.page_allocator);\ndefer nums1.deinit();\ntry nums1.appendSlice(&[_]i32{ 6, 8, 7, 10, 9 });\ntry nums.insertSlice(nums.items.len, nums1.items); // Concatenate nums1 to the end of nums\n
"},{"location":"chapter_array_and_linkedlist/list/#6-sorting-the-list","title":"6. \u00a0 Sorting the List","text":"

After sorting the list, we can use algorithms often tested in array-related algorithm problems, such as \"binary search\" and \"two-pointer\" algorithms.

PythonC++JavaC#GoSwiftJSTSDartRustCZig list.py
# Sort the list\nnums.sort()  # After sorting, the list elements are in ascending order\n
list.cpp
/* Sort the list */\nsort(nums.begin(), nums.end());  // After sorting, the list elements are in ascending order\n
list.java
/* Sort the list */\nCollections.sort(nums);  // After sorting, the list elements are in ascending order\n
list.cs
/* Sort the list */\nnums.Sort(); // After sorting, the list elements are in ascending order\n
list_test.go
/* Sort the list */\nsort.Ints(nums)  // After sorting, the list elements are in ascending order\n
list.swift
/* Sort the list */\nnums.sort() // After sorting, the list elements are in ascending order\n
list.js
/* Sort the list */  \nnums.sort((a, b) => a - b);  // After sorting, the list elements are in ascending order\n
list.ts
/* Sort the list */\nnums.sort((a, b) => a - b);  // After sorting, the list elements are in ascending order\n
list.dart
/* Sort the list */\nnums.sort(); // After sorting, the list elements are in ascending order\n
list.rs
/* Sort the list */\nnums.sort(); // After sorting, the list elements are in ascending order\n
list.c
// C does not provide built-in dynamic arrays\n
list.zig
// Sort the list\nstd.sort.sort(i32, nums.items, {}, comptime std.sort.asc(i32));\n
"},{"location":"chapter_array_and_linkedlist/list/#432-list-implementation","title":"4.3.2 \u00a0 List Implementation","text":"

Many programming languages have built-in lists, such as Java, C++, Python, etc. Their implementations are quite complex, with very meticulous settings for parameters such as initial capacity and expansion multiplier. Interested readers can refer to the source code for learning.

To deepen the understanding of how lists work, let's try implementing a simple version of a list, focusing on three key designs.

  • Initial Capacity: Choose a reasonable initial capacity for the array. In this example, we choose 10 as the initial capacity.
  • Size Recording: Declare a variable size to record the current number of elements in the list, updating in real-time with element insertion and deletion. With this variable, we can locate the end of the list and determine whether expansion is needed.
  • Expansion Mechanism: If the list's capacity is full when inserting an element, expansion is necessary. First, create a larger array based on the expansion multiplier, then move all elements of the current array to the new array. In this example, we define that each time the array will expand to twice its previous size.
PythonC++JavaC#GoSwiftJSTSDartRustCZig my_list.py
class MyList:\n    \"\"\"\u5217\u8868\u7c7b\"\"\"\n\n    def __init__(self):\n        \"\"\"\u6784\u9020\u65b9\u6cd5\"\"\"\n        self._capacity: int = 10  # \u5217\u8868\u5bb9\u91cf\n        self._arr: list[int] = [0] * self._capacity  # \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n        self._size: int = 0  # \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n        self._extend_ratio: int = 2  # \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n    def size(self) -> int:\n        \"\"\"\u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\"\"\"\n        return self._size\n\n    def capacity(self) -> int:\n        \"\"\"\u83b7\u53d6\u5217\u8868\u5bb9\u91cf\"\"\"\n        return self._capacity\n\n    def get(self, index: int) -> int:\n        \"\"\"\u8bbf\u95ee\u5143\u7d20\"\"\"\n        # \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n        if index < 0 or index >= self._size:\n            raise IndexError(\"\u7d22\u5f15\u8d8a\u754c\")\n        return self._arr[index]\n\n    def set(self, num: int, index: int):\n        \"\"\"\u66f4\u65b0\u5143\u7d20\"\"\"\n        if index < 0 or index >= self._size:\n            raise IndexError(\"\u7d22\u5f15\u8d8a\u754c\")\n        self._arr[index] = num\n\n    def add(self, num: int):\n        \"\"\"\u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20\"\"\"\n        # \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if self.size() == self.capacity():\n            self.extend_capacity()\n        self._arr[self._size] = num\n        self._size += 1\n\n    def insert(self, num: int, index: int):\n        \"\"\"\u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20\"\"\"\n        if index < 0 or index >= self._size:\n            raise IndexError(\"\u7d22\u5f15\u8d8a\u754c\")\n        # \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if self._size == self.capacity():\n            self.extend_capacity()\n        # \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for j in range(self._size - 1, index - 1, -1):\n            self._arr[j + 1] = self._arr[j]\n        self._arr[index] = num\n        # \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        self._size += 1\n\n    def remove(self, index: int) -> int:\n        \"\"\"\u5220\u9664\u5143\u7d20\"\"\"\n        if index < 0 or index >= self._size:\n            raise IndexError(\"\u7d22\u5f15\u8d8a\u754c\")\n        num = self._arr[index]\n        # \u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for j in range(index, self._size - 1):\n            self._arr[j] = self._arr[j + 1]\n        # \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        self._size -= 1\n        # \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num\n\n    def extend_capacity(self):\n        \"\"\"\u5217\u8868\u6269\u5bb9\"\"\"\n        # \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 _extend_ratio \u500d\u7684\u65b0\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        self._arr = self._arr + [0] * self.capacity() * (self._extend_ratio - 1)\n        # \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n        self._capacity = len(self._arr)\n\n    def to_array(self) -> list[int]:\n        \"\"\"\u8fd4\u56de\u6709\u6548\u957f\u5ea6\u7684\u5217\u8868\"\"\"\n        return self._arr[: self._size]\n
my_list.cpp
/* \u5217\u8868\u7c7b */\nclass MyList {\n  private:\n    int *arr;             // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    int arrCapacity = 10; // \u5217\u8868\u5bb9\u91cf\n    int arrSize = 0;      // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n    int extendRatio = 2;   // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n  public:\n    /* \u6784\u9020\u65b9\u6cd5 */\n    MyList() {\n        arr = new int[arrCapacity];\n    }\n\n    /* \u6790\u6784\u65b9\u6cd5 */\n    ~MyList() {\n        delete[] arr;\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09*/\n    int size() {\n        return arrSize;\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n    int capacity() {\n        return arrCapacity;\n    }\n\n    /* \u8bbf\u95ee\u5143\u7d20 */\n    int get(int index) {\n        // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n        if (index < 0 || index >= size())\n            throw out_of_range(\"\u7d22\u5f15\u8d8a\u754c\");\n        return arr[index];\n    }\n\n    /* \u66f4\u65b0\u5143\u7d20 */\n    void set(int index, int num) {\n        if (index < 0 || index >= size())\n            throw out_of_range(\"\u7d22\u5f15\u8d8a\u754c\");\n        arr[index] = num;\n    }\n\n    /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n    void add(int num) {\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (size() == capacity())\n            extendCapacity();\n        arr[size()] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        arrSize++;\n    }\n\n    /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n    void insert(int index, int num) {\n        if (index < 0 || index >= size())\n            throw out_of_range(\"\u7d22\u5f15\u8d8a\u754c\");\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (size() == capacity())\n            extendCapacity();\n        // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for (int j = size() - 1; j >= index; j--) {\n            arr[j + 1] = arr[j];\n        }\n        arr[index] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        arrSize++;\n    }\n\n    /* \u5220\u9664\u5143\u7d20 */\n    int remove(int index) {\n        if (index < 0 || index >= size())\n            throw out_of_range(\"\u7d22\u5f15\u8d8a\u754c\");\n        int num = arr[index];\n        // \u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for (int j = index; j < size() - 1; j++) {\n            arr[j] = arr[j + 1];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        arrSize--;\n        // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num;\n    }\n\n    /* \u5217\u8868\u6269\u5bb9 */\n    void extendCapacity() {\n        // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 extendRatio \u500d\u7684\u65b0\u6570\u7ec4\n        int newCapacity = capacity() * extendRatio;\n        int *tmp = arr;\n        arr = new int[newCapacity];\n        // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        for (int i = 0; i < size(); i++) {\n            arr[i] = tmp[i];\n        }\n        // \u91ca\u653e\u5185\u5b58\n        delete[] tmp;\n        arrCapacity = newCapacity;\n    }\n\n    /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a Vector \u7528\u4e8e\u6253\u5370 */\n    vector<int> toVector() {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        vector<int> vec(size());\n        for (int i = 0; i < size(); i++) {\n            vec[i] = arr[i];\n        }\n        return vec;\n    }\n};\n
my_list.java
/* \u5217\u8868\u7c7b */\nclass MyList {\n    private int[] arr; // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    private int capacity = 10; // \u5217\u8868\u5bb9\u91cf\n    private int size = 0; // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n    private int extendRatio = 2; // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n    /* \u6784\u9020\u65b9\u6cd5 */\n    public MyList() {\n        arr = new int[capacity];\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09 */\n    public int size() {\n        return size;\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n    public int capacity() {\n        return capacity;\n    }\n\n    /* \u8bbf\u95ee\u5143\u7d20 */\n    public int get(int index) {\n        // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n        if (index < 0 || index >= size)\n            throw new IndexOutOfBoundsException(\"\u7d22\u5f15\u8d8a\u754c\");\n        return arr[index];\n    }\n\n    /* \u66f4\u65b0\u5143\u7d20 */\n    public void set(int index, int num) {\n        if (index < 0 || index >= size)\n            throw new IndexOutOfBoundsException(\"\u7d22\u5f15\u8d8a\u754c\");\n        arr[index] = num;\n    }\n\n    /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n    public void add(int num) {\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (size == capacity())\n            extendCapacity();\n        arr[size] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        size++;\n    }\n\n    /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n    public void insert(int index, int num) {\n        if (index < 0 || index >= size)\n            throw new IndexOutOfBoundsException(\"\u7d22\u5f15\u8d8a\u754c\");\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (size == capacity())\n            extendCapacity();\n        // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for (int j = size - 1; j >= index; j--) {\n            arr[j + 1] = arr[j];\n        }\n        arr[index] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        size++;\n    }\n\n    /* \u5220\u9664\u5143\u7d20 */\n    public int remove(int index) {\n        if (index < 0 || index >= size)\n            throw new IndexOutOfBoundsException(\"\u7d22\u5f15\u8d8a\u754c\");\n        int num = arr[index];\n        // \u5c06\u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for (int j = index; j < size - 1; j++) {\n            arr[j] = arr[j + 1];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        size--;\n        // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num;\n    }\n\n    /* \u5217\u8868\u6269\u5bb9 */\n    public void extendCapacity() {\n        // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 extendRatio \u500d\u7684\u65b0\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        arr = Arrays.copyOf(arr, capacity() * extendRatio);\n        // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n        capacity = arr.length;\n    }\n\n    /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4 */\n    public int[] toArray() {\n        int size = size();\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        int[] arr = new int[size];\n        for (int i = 0; i < size; i++) {\n            arr[i] = get(i);\n        }\n        return arr;\n    }\n}\n
my_list.cs
/* \u5217\u8868\u7c7b */\nclass MyList {\n    private int[] arr;           // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    private int arrCapacity = 10;    // \u5217\u8868\u5bb9\u91cf\n    private int arrSize = 0;         // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n    private readonly int extendRatio = 2;  // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n    /* \u6784\u9020\u65b9\u6cd5 */\n    public MyList() {\n        arr = new int[arrCapacity];\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09*/\n    public int Size() {\n        return arrSize;\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n    public int Capacity() {\n        return arrCapacity;\n    }\n\n    /* \u8bbf\u95ee\u5143\u7d20 */\n    public int Get(int index) {\n        // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n        if (index < 0 || index >= arrSize)\n            throw new IndexOutOfRangeException(\"\u7d22\u5f15\u8d8a\u754c\");\n        return arr[index];\n    }\n\n    /* \u66f4\u65b0\u5143\u7d20 */\n    public void Set(int index, int num) {\n        if (index < 0 || index >= arrSize)\n            throw new IndexOutOfRangeException(\"\u7d22\u5f15\u8d8a\u754c\");\n        arr[index] = num;\n    }\n\n    /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n    public void Add(int num) {\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (arrSize == arrCapacity)\n            ExtendCapacity();\n        arr[arrSize] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        arrSize++;\n    }\n\n    /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n    public void Insert(int index, int num) {\n        if (index < 0 || index >= arrSize)\n            throw new IndexOutOfRangeException(\"\u7d22\u5f15\u8d8a\u754c\");\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (arrSize == arrCapacity)\n            ExtendCapacity();\n        // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for (int j = arrSize - 1; j >= index; j--) {\n            arr[j + 1] = arr[j];\n        }\n        arr[index] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        arrSize++;\n    }\n\n    /* \u5220\u9664\u5143\u7d20 */\n    public int Remove(int index) {\n        if (index < 0 || index >= arrSize)\n            throw new IndexOutOfRangeException(\"\u7d22\u5f15\u8d8a\u754c\");\n        int num = arr[index];\n        // \u5c06\u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for (int j = index; j < arrSize - 1; j++) {\n            arr[j] = arr[j + 1];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        arrSize--;\n        // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num;\n    }\n\n    /* \u5217\u8868\u6269\u5bb9 */\n    public void ExtendCapacity() {\n        // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a arrCapacity * extendRatio \u7684\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        Array.Resize(ref arr, arrCapacity * extendRatio);\n        // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n        arrCapacity = arr.Length;\n    }\n\n    /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4 */\n    public int[] ToArray() {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        int[] arr = new int[arrSize];\n        for (int i = 0; i < arrSize; i++) {\n            arr[i] = Get(i);\n        }\n        return arr;\n    }\n}\n
my_list.go
/* \u5217\u8868\u7c7b */\ntype myList struct {\n    arrCapacity int\n    arr         []int\n    arrSize     int\n    extendRatio int\n}\n\n/* \u6784\u9020\u51fd\u6570 */\nfunc newMyList() *myList {\n    return &myList{\n        arrCapacity: 10,              // \u5217\u8868\u5bb9\u91cf\n        arr:         make([]int, 10), // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n        arrSize:     0,               // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n        extendRatio: 2,               // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n    }\n}\n\n/* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09 */\nfunc (l *myList) size() int {\n    return l.arrSize\n}\n\n/*  \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\nfunc (l *myList) capacity() int {\n    return l.arrCapacity\n}\n\n/* \u8bbf\u95ee\u5143\u7d20 */\nfunc (l *myList) get(index int) int {\n    // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n    if index < 0 || index >= l.arrSize {\n        panic(\"\u7d22\u5f15\u8d8a\u754c\")\n    }\n    return l.arr[index]\n}\n\n/* \u66f4\u65b0\u5143\u7d20 */\nfunc (l *myList) set(num, index int) {\n    if index < 0 || index >= l.arrSize {\n        panic(\"\u7d22\u5f15\u8d8a\u754c\")\n    }\n    l.arr[index] = num\n}\n\n/* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\nfunc (l *myList) add(num int) {\n    // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n    if l.arrSize == l.arrCapacity {\n        l.extendCapacity()\n    }\n    l.arr[l.arrSize] = num\n    // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n    l.arrSize++\n}\n\n/* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\nfunc (l *myList) insert(num, index int) {\n    if index < 0 || index >= l.arrSize {\n        panic(\"\u7d22\u5f15\u8d8a\u754c\")\n    }\n    // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n    if l.arrSize == l.arrCapacity {\n        l.extendCapacity()\n    }\n    // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for j := l.arrSize - 1; j >= index; j-- {\n        l.arr[j+1] = l.arr[j]\n    }\n    l.arr[index] = num\n    // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n    l.arrSize++\n}\n\n/* \u5220\u9664\u5143\u7d20 */\nfunc (l *myList) remove(index int) int {\n    if index < 0 || index >= l.arrSize {\n        panic(\"\u7d22\u5f15\u8d8a\u754c\")\n    }\n    num := l.arr[index]\n    // \u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for j := index; j < l.arrSize-1; j++ {\n        l.arr[j] = l.arr[j+1]\n    }\n    // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n    l.arrSize--\n    // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n    return num\n}\n\n/* \u5217\u8868\u6269\u5bb9 */\nfunc (l *myList) extendCapacity() {\n    // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 extendRatio \u500d\u7684\u65b0\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    l.arr = append(l.arr, make([]int, l.arrCapacity*(l.extendRatio-1))...)\n    // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n    l.arrCapacity = len(l.arr)\n}\n\n/* \u8fd4\u56de\u6709\u6548\u957f\u5ea6\u7684\u5217\u8868 */\nfunc (l *myList) toArray() []int {\n    // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n    return l.arr[:l.arrSize]\n}\n
my_list.swift
/* \u5217\u8868\u7c7b */\nclass MyList {\n    private var arr: [Int] // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    private var _capacity = 10 // \u5217\u8868\u5bb9\u91cf\n    private var _size = 0 // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n    private let extendRatio = 2 // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n    /* \u6784\u9020\u65b9\u6cd5 */\n    init() {\n        arr = Array(repeating: 0, count: _capacity)\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09*/\n    func size() -> Int {\n        _size\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n    func capacity() -> Int {\n        _capacity\n    }\n\n    /* \u8bbf\u95ee\u5143\u7d20 */\n    func get(index: Int) -> Int {\n        // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\u5219\u629b\u51fa\u9519\u8bef\uff0c\u4e0b\u540c\n        if index < 0 || index >= _size {\n            fatalError(\"\u7d22\u5f15\u8d8a\u754c\")\n        }\n        return arr[index]\n    }\n\n    /* \u66f4\u65b0\u5143\u7d20 */\n    func set(index: Int, num: Int) {\n        if index < 0 || index >= _size {\n            fatalError(\"\u7d22\u5f15\u8d8a\u754c\")\n        }\n        arr[index] = num\n    }\n\n    /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n    func add(num: Int) {\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if _size == _capacity {\n            extendCapacity()\n        }\n        arr[_size] = num\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        _size += 1\n    }\n\n    /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n    func insert(index: Int, num: Int) {\n        if index < 0 || index >= _size {\n            fatalError(\"\u7d22\u5f15\u8d8a\u754c\")\n        }\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if _size == _capacity {\n            extendCapacity()\n        }\n        // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for j in sequence(first: _size - 1, next: { $0 >= index + 1 ? $0 - 1 : nil }) {\n            arr[j + 1] = arr[j]\n        }\n        arr[index] = num\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        _size += 1\n    }\n\n    /* \u5220\u9664\u5143\u7d20 */\n    @discardableResult\n    func remove(index: Int) -> Int {\n        if index < 0 || index >= _size {\n            fatalError(\"\u7d22\u5f15\u8d8a\u754c\")\n        }\n        let num = arr[index]\n        // \u5c06\u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for j in index ..< (_size - 1) {\n            arr[j] = arr[j + 1]\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        _size -= 1\n        // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num\n    }\n\n    /* \u5217\u8868\u6269\u5bb9 */\n    func extendCapacity() {\n        // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 extendRatio \u500d\u7684\u65b0\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        arr = arr + Array(repeating: 0, count: _capacity * (extendRatio - 1))\n        // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n        _capacity = arr.count\n    }\n\n    /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4 */\n    func toArray() -> [Int] {\n        var arr = Array(repeating: 0, count: _size)\n        for i in 0 ..< _size {\n            arr[i] = get(index: i)\n        }\n        return arr\n    }\n}\n
my_list.js
/* \u5217\u8868\u7c7b */\nclass MyList {\n    #arr = new Array(); // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    #capacity = 10; // \u5217\u8868\u5bb9\u91cf\n    #size = 0; // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n    #extendRatio = 2; // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n    /* \u6784\u9020\u65b9\u6cd5 */\n    constructor() {\n        this.#arr = new Array(this.#capacity);\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09*/\n    size() {\n        return this.#size;\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n    capacity() {\n        return this.#capacity;\n    }\n\n    /* \u8bbf\u95ee\u5143\u7d20 */\n    get(index) {\n        // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n        if (index < 0 || index >= this.#size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        return this.#arr[index];\n    }\n\n    /* \u66f4\u65b0\u5143\u7d20 */\n    set(index, num) {\n        if (index < 0 || index >= this.#size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        this.#arr[index] = num;\n    }\n\n    /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n    add(num) {\n        // \u5982\u679c\u957f\u5ea6\u7b49\u4e8e\u5bb9\u91cf\uff0c\u5219\u9700\u8981\u6269\u5bb9\n        if (this.#size === this.#capacity) {\n            this.extendCapacity();\n        }\n        // \u5c06\u65b0\u5143\u7d20\u6dfb\u52a0\u5230\u5217\u8868\u5c3e\u90e8\n        this.#arr[this.#size] = num;\n        this.#size++;\n    }\n\n    /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n    insert(index, num) {\n        if (index < 0 || index >= this.#size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (this.#size === this.#capacity) {\n            this.extendCapacity();\n        }\n        // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for (let j = this.#size - 1; j >= index; j--) {\n            this.#arr[j + 1] = this.#arr[j];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        this.#arr[index] = num;\n        this.#size++;\n    }\n\n    /* \u5220\u9664\u5143\u7d20 */\n    remove(index) {\n        if (index < 0 || index >= this.#size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        let num = this.#arr[index];\n        // \u5c06\u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for (let j = index; j < this.#size - 1; j++) {\n            this.#arr[j] = this.#arr[j + 1];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        this.#size--;\n        // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num;\n    }\n\n    /* \u5217\u8868\u6269\u5bb9 */\n    extendCapacity() {\n        // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 extendRatio \u500d\u7684\u65b0\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        this.#arr = this.#arr.concat(\n            new Array(this.capacity() * (this.#extendRatio - 1))\n        );\n        // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n        this.#capacity = this.#arr.length;\n    }\n\n    /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4 */\n    toArray() {\n        let size = this.size();\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        const arr = new Array(size);\n        for (let i = 0; i < size; i++) {\n            arr[i] = this.get(i);\n        }\n        return arr;\n    }\n}\n
my_list.ts
/* \u5217\u8868\u7c7b */\nclass MyList {\n    private arr: Array<number>; // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    private _capacity: number = 10; // \u5217\u8868\u5bb9\u91cf\n    private _size: number = 0; // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n    private extendRatio: number = 2; // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n    /* \u6784\u9020\u65b9\u6cd5 */\n    constructor() {\n        this.arr = new Array(this._capacity);\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09*/\n    public size(): number {\n        return this._size;\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n    public capacity(): number {\n        return this._capacity;\n    }\n\n    /* \u8bbf\u95ee\u5143\u7d20 */\n    public get(index: number): number {\n        // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n        if (index < 0 || index >= this._size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        return this.arr[index];\n    }\n\n    /* \u66f4\u65b0\u5143\u7d20 */\n    public set(index: number, num: number): void {\n        if (index < 0 || index >= this._size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        this.arr[index] = num;\n    }\n\n    /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n    public add(num: number): void {\n        // \u5982\u679c\u957f\u5ea6\u7b49\u4e8e\u5bb9\u91cf\uff0c\u5219\u9700\u8981\u6269\u5bb9\n        if (this._size === this._capacity) this.extendCapacity();\n        // \u5c06\u65b0\u5143\u7d20\u6dfb\u52a0\u5230\u5217\u8868\u5c3e\u90e8\n        this.arr[this._size] = num;\n        this._size++;\n    }\n\n    /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n    public insert(index: number, num: number): void {\n        if (index < 0 || index >= this._size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if (this._size === this._capacity) {\n            this.extendCapacity();\n        }\n        // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for (let j = this._size - 1; j >= index; j--) {\n            this.arr[j + 1] = this.arr[j];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        this.arr[index] = num;\n        this._size++;\n    }\n\n    /* \u5220\u9664\u5143\u7d20 */\n    public remove(index: number): number {\n        if (index < 0 || index >= this._size) throw new Error('\u7d22\u5f15\u8d8a\u754c');\n        let num = this.arr[index];\n        // \u5c06\u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for (let j = index; j < this._size - 1; j++) {\n            this.arr[j] = this.arr[j + 1];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        this._size--;\n        // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num;\n    }\n\n    /* \u5217\u8868\u6269\u5bb9 */\n    public extendCapacity(): void {\n        // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a size \u7684\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        this.arr = this.arr.concat(\n            new Array(this.capacity() * (this.extendRatio - 1))\n        );\n        // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n        this._capacity = this.arr.length;\n    }\n\n    /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4 */\n    public toArray(): number[] {\n        let size = this.size();\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        const arr = new Array(size);\n        for (let i = 0; i < size; i++) {\n            arr[i] = this.get(i);\n        }\n        return arr;\n    }\n}\n
my_list.dart
/* \u5217\u8868\u7c7b */\nclass MyList {\n  late List<int> _arr; // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n  int _capacity = 10; // \u5217\u8868\u5bb9\u91cf\n  int _size = 0; // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n  int _extendRatio = 2; // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n\n  /* \u6784\u9020\u65b9\u6cd5 */\n  MyList() {\n    _arr = List.filled(_capacity, 0);\n  }\n\n  /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09*/\n  int size() => _size;\n\n  /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n  int capacity() => _capacity;\n\n  /* \u8bbf\u95ee\u5143\u7d20 */\n  int get(int index) {\n    if (index >= _size) throw RangeError('\u7d22\u5f15\u8d8a\u754c');\n    return _arr[index];\n  }\n\n  /* \u66f4\u65b0\u5143\u7d20 */\n  void set(int index, int _num) {\n    if (index >= _size) throw RangeError('\u7d22\u5f15\u8d8a\u754c');\n    _arr[index] = _num;\n  }\n\n  /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n  void add(int _num) {\n    // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n    if (_size == _capacity) extendCapacity();\n    _arr[_size] = _num;\n    // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n    _size++;\n  }\n\n  /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n  void insert(int index, int _num) {\n    if (index >= _size) throw RangeError('\u7d22\u5f15\u8d8a\u754c');\n    // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n    if (_size == _capacity) extendCapacity();\n    // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n    for (var j = _size - 1; j >= index; j--) {\n      _arr[j + 1] = _arr[j];\n    }\n    _arr[index] = _num;\n    // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n    _size++;\n  }\n\n  /* \u5220\u9664\u5143\u7d20 */\n  int remove(int index) {\n    if (index >= _size) throw RangeError('\u7d22\u5f15\u8d8a\u754c');\n    int _num = _arr[index];\n    // \u5c06\u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n    for (var j = index; j < _size - 1; j++) {\n      _arr[j] = _arr[j + 1];\n    }\n    // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n    _size--;\n    // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n    return _num;\n  }\n\n  /* \u5217\u8868\u6269\u5bb9 */\n  void extendCapacity() {\n    // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 _extendRatio \u500d\u7684\u65b0\u6570\u7ec4\n    final _newNums = List.filled(_capacity * _extendRatio, 0);\n    // \u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n    List.copyRange(_newNums, 0, _arr);\n    // \u66f4\u65b0 _arr \u7684\u5f15\u7528\n    _arr = _newNums;\n    // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n    _capacity = _arr.length;\n  }\n\n  /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4 */\n  List<int> toArray() {\n    List<int> arr = [];\n    for (var i = 0; i < _size; i++) {\n      arr.add(get(i));\n    }\n    return arr;\n  }\n}\n
my_list.rs
/* \u5217\u8868\u7c7b */\n#[allow(dead_code)]\nstruct MyList {\n    arr: Vec<i32>,       // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    capacity: usize,      // \u5217\u8868\u5bb9\u91cf\n    size: usize,          // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n    extend_ratio: usize,  // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n}\n\n#[allow(unused,unused_comparisons)]\nimpl MyList {\n    /* \u6784\u9020\u65b9\u6cd5 */\n    pub fn new(capacity: usize) -> Self {\n        let mut vec = Vec::new(); \n        vec.resize(capacity, 0);\n        Self {\n            arr: vec,\n            capacity,\n            size: 0,\n            extend_ratio: 2,\n        }\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09*/\n    pub fn size(&self) -> usize {\n        return self.size;\n    }\n\n    /* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\n    pub fn capacity(&self) -> usize {\n        return self.capacity;\n    }\n\n    /* \u8bbf\u95ee\u5143\u7d20 */\n    pub fn get(&self, index: usize) -> i32 {\n        // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n        if index >= self.size {panic!(\"\u7d22\u5f15\u8d8a\u754c\")};\n        return self.arr[index];\n    }\n\n    /* \u66f4\u65b0\u5143\u7d20 */\n    pub fn set(&mut self, index: usize, num: i32) {\n        if index >= self.size {panic!(\"\u7d22\u5f15\u8d8a\u754c\")};\n        self.arr[index] = num;\n    }\n\n    /* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\n    pub fn add(&mut self, num: i32) {\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if self.size == self.capacity() {\n            self.extend_capacity();\n        }\n        self.arr[self.size] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        self.size += 1;\n    }\n\n    /* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\n    pub fn insert(&mut self, index: usize, num: i32) {\n        if index >= self.size() {panic!(\"\u7d22\u5f15\u8d8a\u754c\")};\n        // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n        if self.size == self.capacity() {\n            self.extend_capacity();\n        }\n        // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n        for j in (index..self.size).rev() {\n            self.arr[j + 1] = self.arr[j];\n        }\n        self.arr[index] = num;\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        self.size += 1;\n    }\n\n    /* \u5220\u9664\u5143\u7d20 */\n    pub fn remove(&mut self, index: usize) -> i32 {\n        if index >= self.size() {panic!(\"\u7d22\u5f15\u8d8a\u754c\")};\n        let num = self.arr[index];\n        // \u5c06\u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n        for j in (index..self.size - 1) {\n            self.arr[j] = self.arr[j + 1];\n        }\n        // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n        self.size -= 1;\n        // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n        return num;\n    }\n\n    /* \u5217\u8868\u6269\u5bb9 */\n    pub fn extend_capacity(&mut self) {\n        // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a\u539f\u6570\u7ec4 extend_ratio \u500d\u7684\u65b0\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n        let new_capacity = self.capacity * self.extend_ratio;\n        self.arr.resize(new_capacity, 0);\n        // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n        self.capacity = new_capacity;\n    }\n\n    /* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4 */\n    pub fn to_array(&mut self) -> Vec<i32> {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        let mut arr = Vec::new();\n        for i in 0..self.size {\n            arr.push(self.get(i));\n        }\n        arr\n    }\n}\n
my_list.c
/* \u5217\u8868\u7c7b */\ntypedef struct {\n    int *arr;        // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n    int capacity;    // \u5217\u8868\u5bb9\u91cf\n    int size;        // \u5217\u8868\u5927\u5c0f\n    int extendRatio; // \u5217\u8868\u6bcf\u6b21\u6269\u5bb9\u7684\u500d\u6570\n} MyList;\n\n/* \u6784\u9020\u51fd\u6570 */\nMyList *newMyList() {\n    MyList *nums = malloc(sizeof(MyList));\n    nums->capacity = 10;\n    nums->arr = malloc(sizeof(int) * nums->capacity);\n    nums->size = 0;\n    nums->extendRatio = 2;\n    return nums;\n}\n\n/* \u6790\u6784\u51fd\u6570 */\nvoid delMyList(MyList *nums) {\n    free(nums->arr);\n    free(nums);\n}\n\n/* \u83b7\u53d6\u5217\u8868\u957f\u5ea6 */\nint size(MyList *nums) {\n    return nums->size;\n}\n\n/* \u83b7\u53d6\u5217\u8868\u5bb9\u91cf */\nint capacity(MyList *nums) {\n    return nums->capacity;\n}\n\n/* \u8bbf\u95ee\u5143\u7d20 */\nint get(MyList *nums, int index) {\n    assert(index >= 0 && index < nums->size);\n    return nums->arr[index];\n}\n\n/* \u66f4\u65b0\u5143\u7d20 */\nvoid set(MyList *nums, int index, int num) {\n    assert(index >= 0 && index < nums->size);\n    nums->arr[index] = num;\n}\n\n/* \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20 */\nvoid add(MyList *nums, int num) {\n    if (size(nums) == capacity(nums)) {\n        extendCapacity(nums); // \u6269\u5bb9\n    }\n    nums->arr[size(nums)] = num;\n    nums->size++;\n}\n\n/* \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20 */\nvoid insert(MyList *nums, int index, int num) {\n    assert(index >= 0 && index < size(nums));\n    // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n    if (size(nums) == capacity(nums)) {\n        extendCapacity(nums); // \u6269\u5bb9\n    }\n    for (int i = size(nums); i > index; --i) {\n        nums->arr[i] = nums->arr[i - 1];\n    }\n    nums->arr[index] = num;\n    nums->size++;\n}\n\n/* \u5220\u9664\u5143\u7d20 */\n// \u6ce8\u610f\uff1astdio.h \u5360\u7528\u4e86 remove \u5173\u952e\u8bcd\nint removeItem(MyList *nums, int index) {\n    assert(index >= 0 && index < size(nums));\n    int num = nums->arr[index];\n    for (int i = index; i < size(nums) - 1; i++) {\n        nums->arr[i] = nums->arr[i + 1];\n    }\n    nums->size--;\n    return num;\n}\n\n/* \u5217\u8868\u6269\u5bb9 */\nvoid extendCapacity(MyList *nums) {\n    // \u5148\u5206\u914d\u7a7a\u95f4\n    int newCapacity = capacity(nums) * nums->extendRatio;\n    int *extend = (int *)malloc(sizeof(int) * newCapacity);\n    int *temp = nums->arr;\n\n    // \u62f7\u8d1d\u65e7\u6570\u636e\u5230\u65b0\u6570\u636e\n    for (int i = 0; i < size(nums); i++)\n        extend[i] = nums->arr[i];\n\n    // \u91ca\u653e\u65e7\u6570\u636e\n    free(temp);\n\n    // \u66f4\u65b0\u65b0\u6570\u636e\n    nums->arr = extend;\n    nums->capacity = newCapacity;\n}\n\n/* \u5c06\u5217\u8868\u8f6c\u6362\u4e3a Array \u7528\u4e8e\u6253\u5370 */\nint *toArray(MyList *nums) {\n    return nums->arr;\n}\n
my_list.zig
// \u5217\u8868\u7c7b\nfn MyList(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        arr: []T = undefined,                        // \u6570\u7ec4\uff08\u5b58\u50a8\u5217\u8868\u5143\u7d20\uff09\n        arrCapacity: usize = 10,                     // \u5217\u8868\u5bb9\u91cf\n        numSize: usize = 0,                           // \u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n        extendRatio: usize = 2,                       // \u6bcf\u6b21\u5217\u8868\u6269\u5bb9\u7684\u500d\u6570\n        mem_arena: ?std.heap.ArenaAllocator = null,\n        mem_allocator: std.mem.Allocator = undefined, // \u5185\u5b58\u5206\u914d\u5668\n\n        // \u6784\u9020\u51fd\u6570\uff08\u5206\u914d\u5185\u5b58+\u521d\u59cb\u5316\u5217\u8868\uff09\n        pub fn init(self: *Self, allocator: std.mem.Allocator) !void {\n            if (self.mem_arena == null) {\n                self.mem_arena = std.heap.ArenaAllocator.init(allocator);\n                self.mem_allocator = self.mem_arena.?.allocator();\n            }\n            self.arr = try self.mem_allocator.alloc(T, self.arrCapacity);\n            @memset(self.arr, @as(T, 0));\n        }\n\n        // \u6790\u6784\u51fd\u6570\uff08\u91ca\u653e\u5185\u5b58\uff09\n        pub fn deinit(self: *Self) void {\n            if (self.mem_arena == null) return;\n            self.mem_arena.?.deinit();\n        }\n\n        // \u83b7\u53d6\u5217\u8868\u957f\u5ea6\uff08\u5f53\u524d\u5143\u7d20\u6570\u91cf\uff09\n        pub fn size(self: *Self) usize {\n            return self.numSize;\n        }\n\n        // \u83b7\u53d6\u5217\u8868\u5bb9\u91cf\n        pub fn capacity(self: *Self) usize {\n            return self.arrCapacity;\n        }\n\n        // \u8bbf\u95ee\u5143\u7d20\n        pub fn get(self: *Self, index: usize) T {\n            // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n            if (index < 0 or index >= self.size()) @panic(\"\u7d22\u5f15\u8d8a\u754c\");\n            return self.arr[index];\n        }  \n\n        // \u66f4\u65b0\u5143\u7d20\n        pub fn set(self: *Self, index: usize, num: T) void {\n            // \u7d22\u5f15\u5982\u679c\u8d8a\u754c\uff0c\u5219\u629b\u51fa\u5f02\u5e38\uff0c\u4e0b\u540c\n            if (index < 0 or index >= self.size()) @panic(\"\u7d22\u5f15\u8d8a\u754c\");\n            self.arr[index] = num;\n        }  \n\n        // \u5728\u5c3e\u90e8\u6dfb\u52a0\u5143\u7d20\n        pub fn add(self: *Self, num: T) !void {\n            // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n            if (self.size() == self.capacity()) try self.extendCapacity();\n            self.arr[self.size()] = num;\n            // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n            self.numSize += 1;\n        }  \n\n        // \u5728\u4e2d\u95f4\u63d2\u5165\u5143\u7d20\n        pub fn insert(self: *Self, index: usize, num: T) !void {\n            if (index < 0 or index >= self.size()) @panic(\"\u7d22\u5f15\u8d8a\u754c\");\n            // \u5143\u7d20\u6570\u91cf\u8d85\u51fa\u5bb9\u91cf\u65f6\uff0c\u89e6\u53d1\u6269\u5bb9\u673a\u5236\n            if (self.size() == self.capacity()) try self.extendCapacity();\n            // \u5c06\u7d22\u5f15 index \u4ee5\u53ca\u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\n            var j = self.size() - 1;\n            while (j >= index) : (j -= 1) {\n                self.arr[j + 1] = self.arr[j];\n            }\n            self.arr[index] = num;\n            // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n            self.numSize += 1;\n        }\n\n        // \u5220\u9664\u5143\u7d20\n        pub fn remove(self: *Self, index: usize) T {\n            if (index < 0 or index >= self.size()) @panic(\"\u7d22\u5f15\u8d8a\u754c\");\n            var num = self.arr[index];\n            // \u5c06\u7d22\u5f15 index \u4e4b\u540e\u7684\u5143\u7d20\u90fd\u5411\u524d\u79fb\u52a8\u4e00\u4f4d\n            var j = index;\n            while (j < self.size() - 1) : (j += 1) {\n                self.arr[j] = self.arr[j + 1];\n            }\n            // \u66f4\u65b0\u5143\u7d20\u6570\u91cf\n            self.numSize -= 1;\n            // \u8fd4\u56de\u88ab\u5220\u9664\u7684\u5143\u7d20\n            return num;\n        }\n\n        // \u5217\u8868\u6269\u5bb9\n        pub fn extendCapacity(self: *Self) !void {\n            // \u65b0\u5efa\u4e00\u4e2a\u957f\u5ea6\u4e3a size * extendRatio \u7684\u6570\u7ec4\uff0c\u5e76\u5c06\u539f\u6570\u7ec4\u590d\u5236\u5230\u65b0\u6570\u7ec4\n            var newCapacity = self.capacity() * self.extendRatio;\n            var extend = try self.mem_allocator.alloc(T, newCapacity);\n            @memset(extend, @as(T, 0));\n            // \u5c06\u539f\u6570\u7ec4\u4e2d\u7684\u6240\u6709\u5143\u7d20\u590d\u5236\u5230\u65b0\u6570\u7ec4\n            std.mem.copy(T, extend, self.arr);\n            self.arr = extend;\n            // \u66f4\u65b0\u5217\u8868\u5bb9\u91cf\n            self.arrCapacity = newCapacity;\n        }\n\n        // \u5c06\u5217\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4\n        pub fn toArray(self: *Self) ![]T {\n            // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n            var arr = try self.mem_allocator.alloc(T, self.size());\n           @memset(arr, @as(T, 0));\n            for (arr, 0..) |*num, i| {\n                num.* = self.get(i);\n            }\n            return arr;\n        }\n    };\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_array_and_linkedlist/ram_and_cache/","title":"4.4 \u00a0 Memory and Cache *","text":"

In the first two sections of this chapter, we explored arrays and linked lists, two fundamental and important data structures, representing \"continuous storage\" and \"dispersed storage\" respectively.

In fact, the physical structure largely determines the efficiency of a program's use of memory and cache, which in turn affects the overall performance of the algorithm.

"},{"location":"chapter_array_and_linkedlist/ram_and_cache/#441-computer-storage-devices","title":"4.4.1 \u00a0 Computer Storage Devices","text":"

There are three types of storage devices in computers: \"hard disk,\" \"random-access memory (RAM),\" and \"cache memory.\" The following table shows their different roles and performance characteristics in computer systems.

Table 4-2 \u00a0 Computer Storage Devices

Hard Disk Memory Cache Usage Long-term storage of data, including OS, programs, files, etc. Temporary storage of currently running programs and data being processed Stores frequently accessed data and instructions, reducing the number of CPU accesses to memory Volatility Data is not lost after power off Data is lost after power off Data is lost after power off Capacity Larger, TB level Smaller, GB level Very small, MB level Speed Slower, several hundred to thousands MB/s Faster, several tens of GB/s Very fast, several tens to hundreds of GB/s Price Cheaper, several cents to yuan / GB More expensive, tens to hundreds of yuan / GB Very expensive, priced with CPU

We can imagine the computer storage system as a pyramid structure shown in the Figure 4-9 . The storage devices closer to the top of the pyramid are faster, have smaller capacity, and are more costly. This multi-level design is not accidental, but the result of careful consideration by computer scientists and engineers.

  • Hard disks are difficult to replace with memory. Firstly, data in memory is lost after power off, making it unsuitable for long-term data storage; secondly, the cost of memory is dozens of times that of hard disks, making it difficult to popularize in the consumer market.
  • It is difficult for caches to have both large capacity and high speed. As the capacity of L1, L2, L3 caches gradually increases, their physical size becomes larger, increasing the physical distance from the CPU core, leading to increased data transfer time and higher element access latency. Under current technology, a multi-level cache structure is the best balance between capacity, speed, and cost.

Figure 4-9 \u00a0 Computer Storage System

Note

The storage hierarchy of computers reflects a delicate balance between speed, capacity, and cost. In fact, this kind of trade-off is common in all industrial fields, requiring us to find the best balance between different advantages and limitations.

Overall, hard disks are used for long-term storage of large amounts of data, memory is used for temporary storage of data being processed during program execution, and cache is used to store frequently accessed data and instructions to improve program execution efficiency. Together, they ensure the efficient operation of computer systems.

As shown in the Figure 4-10 , during program execution, data is read from the hard disk into memory for CPU computation. The cache can be considered a part of the CPU, smartly loading data from memory to provide fast data access to the CPU, significantly enhancing program execution efficiency and reducing reliance on slower memory.

Figure 4-10 \u00a0 Data Flow Between Hard Disk, Memory, and Cache

"},{"location":"chapter_array_and_linkedlist/ram_and_cache/#442-memory-efficiency-of-data-structures","title":"4.4.2 \u00a0 Memory Efficiency of Data Structures","text":"

In terms of memory space utilization, arrays and linked lists have their advantages and limitations.

On one hand, memory is limited and cannot be shared by multiple programs, so we hope that data structures can use space as efficiently as possible. The elements of an array are tightly packed without extra space for storing references (pointers) between linked list nodes, making them more space-efficient. However, arrays require allocating sufficient continuous memory space at once, which may lead to memory waste, and array expansion also requires additional time and space costs. In contrast, linked lists allocate and reclaim memory dynamically on a per-node basis, providing greater flexibility.

On the other hand, during program execution, as memory is repeatedly allocated and released, the degree of fragmentation of free memory becomes higher, leading to reduced memory utilization efficiency. Arrays, due to their continuous storage method, are relatively less likely to cause memory fragmentation. In contrast, the elements of a linked list are dispersedly stored, and frequent insertion and deletion operations make memory fragmentation more likely.

"},{"location":"chapter_array_and_linkedlist/ram_and_cache/#443-cache-efficiency-of-data-structures","title":"4.4.3 \u00a0 Cache Efficiency of Data Structures","text":"

Although caches are much smaller in space capacity than memory, they are much faster and play a crucial role in program execution speed. Since the cache's capacity is limited and can only store a small part of frequently accessed data, when the CPU tries to access data not in the cache, a \"cache miss\" occurs, forcing the CPU to load the needed data from slower memory.

Clearly, the fewer the cache misses, the higher the CPU's data read-write efficiency, and the better the program performance. The proportion of successful data retrieval from the cache by the CPU is called the \"cache hit rate,\" a metric often used to measure cache efficiency.

To achieve higher efficiency, caches adopt the following data loading mechanisms.

  • Cache Lines: Caches don't store and load data byte by byte but in units of cache lines. Compared to byte-by-byte transfer, the transmission of cache lines is more efficient.
  • Prefetch Mechanism: Processors try to predict data access patterns (such as sequential access, fixed stride jumping access, etc.) and load data into the cache according to specific patterns to improve the hit rate.
  • Spatial Locality: If data is accessed, data nearby is likely to be accessed in the near future. Therefore, when loading certain data, the cache also loads nearby data to improve the hit rate.
  • Temporal Locality: If data is accessed, it's likely to be accessed again in the near future. Caches use this principle to retain recently accessed data to improve the hit rate.

In fact, arrays and linked lists have different cache utilization efficiencies, mainly reflected in the following aspects.

  • Occupied Space: Linked list elements occupy more space than array elements, resulting in less effective data volume in the cache.
  • Cache Lines: Linked list data is scattered throughout memory, and since caches load \"by line,\" the proportion of loading invalid data is higher.
  • Prefetch Mechanism: The data access pattern of arrays is more \"predictable\" than that of linked lists, meaning the system is more likely to guess which data will be loaded next.
  • Spatial Locality: Arrays are stored in concentrated memory spaces, so the data near the loaded data is more likely to be accessed next.

Overall, arrays have a higher cache hit rate and are generally more efficient in operation than linked lists. This makes data structures based on arrays more popular in solving algorithmic problems.

It should be noted that high cache efficiency does not mean that arrays are always better than linked lists. Which data structure to choose in actual applications should be based on specific requirements. For example, both arrays and linked lists can implement the \"stack\" data structure (which will be detailed in the next chapter), but they are suitable for different scenarios.

  • In algorithm problems, we tend to choose stacks based on arrays because they provide higher operational efficiency and random access capabilities, with the only cost being the need to pre-allocate a certain amount of memory space for the array.
  • If the data volume is very large, highly dynamic, and the expected size of the stack is difficult to estimate, then a stack based on a linked list is more appropriate. Linked lists can disperse a large amount of data in different parts of the memory and avoid the additional overhead of array expansion.
"},{"location":"chapter_array_and_linkedlist/summary/","title":"4.5 \u00a0 Summary","text":""},{"location":"chapter_array_and_linkedlist/summary/#1-key-review","title":"1. \u00a0 Key Review","text":"
  • Arrays and linked lists are two basic data structures, representing two storage methods in computer memory: contiguous space storage and non-contiguous space storage. Their characteristics complement each other.
  • Arrays support random access and use less memory; however, they are inefficient in inserting and deleting elements and have a fixed length after initialization.
  • Linked lists implement efficient node insertion and deletion through changing references (pointers) and can flexibly adjust their length; however, they have lower node access efficiency and consume more memory.
  • Common types of linked lists include singly linked lists, circular linked lists, and doubly linked lists, each with its own application scenarios.
  • Lists are ordered collections of elements that support addition, deletion, and modification, typically implemented based on dynamic arrays, retaining the advantages of arrays while allowing flexible length adjustment.
  • The advent of lists significantly enhanced the practicality of arrays but may lead to some memory space wastage.
  • During program execution, data is mainly stored in memory. Arrays provide higher memory space efficiency, while linked lists are more flexible in memory usage.
  • Caches provide fast data access to CPUs through mechanisms like cache lines, prefetching, spatial locality, and temporal locality, significantly enhancing program execution efficiency.
  • Due to higher cache hit rates, arrays are generally more efficient than linked lists. When choosing a data structure, the appropriate choice should be made based on specific needs and scenarios.
"},{"location":"chapter_array_and_linkedlist/summary/#2-q-a","title":"2. \u00a0 Q & A","text":"

Q: Does storing arrays on the stack versus the heap affect time and space efficiency?

Arrays stored on both the stack and heap are stored in contiguous memory spaces, and data operation efficiency is essentially the same. However, stacks and heaps have their own characteristics, leading to the following differences.

  1. Allocation and release efficiency: The stack is a smaller memory block, allocated automatically by the compiler; the heap memory is relatively larger and can be dynamically allocated in the code, more prone to fragmentation. Therefore, allocation and release operations on the heap are generally slower than on the stack.
  2. Size limitation: Stack memory is relatively small, while the heap size is generally limited by available memory. Therefore, the heap is more suitable for storing large arrays.
  3. Flexibility: The size of arrays on the stack needs to be determined at compile-time, while the size of arrays on the heap can be dynamically determined at runtime.

Q: Why do arrays require elements of the same type, while linked lists do not emphasize same-type elements?

Linked lists consist of nodes connected by references (pointers), and each node can store data of different types, such as int, double, string, object, etc.

In contrast, array elements must be of the same type, allowing the calculation of offsets to access the corresponding element positions. For example, an array containing both int and long types, with single elements occupying 4 bytes and 8 bytes respectively, cannot use the following formula to calculate offsets, as the array contains elements of two different lengths.

# Element memory address = Array memory address + Element length * Element index\n

Q: After deleting a node, is it necessary to set P.next to None?

Not modifying P.next is also acceptable. From the perspective of the linked list, traversing from the head node to the tail node will no longer encounter P. This means that node P has been effectively removed from the list, and where P points no longer affects the list.

From a garbage collection perspective, for languages with automatic garbage collection mechanisms like Java, Python, and Go, whether node P is collected depends on whether there are still references pointing to it, not on the value of P.next. In languages like C and C++, we need to manually free the node's memory.

Q: In linked lists, the time complexity for insertion and deletion operations is O(1). But searching for the element before insertion or deletion takes O(n) time, so why isn't the time complexity O(n)?

If an element is searched first and then deleted, the time complexity is indeed O(n). However, the O(1) advantage of linked lists in insertion and deletion can be realized in other applications. For example, in the implementation of double-ended queues using linked lists, we maintain pointers always pointing to the head and tail nodes, making each insertion and deletion operation O(1).

Q: In the image \"Linked List Definition and Storage Method\", do the light blue storage nodes occupy a single memory address, or do they share half with the node value?

The diagram is just a qualitative representation; quantitative analysis depends on specific situations.

  • Different types of node values occupy different amounts of space, such as int, long, double, and object instances.
  • The memory space occupied by pointer variables depends on the operating system and compilation environment used, usually 8 bytes or 4 bytes.

Q: Is adding elements to the end of a list always O(1)?

If adding an element exceeds the list length, the list needs to be expanded first. The system will request a new memory block and move all elements of the original list over, in which case the time complexity becomes O(n).

Q: The statement \"The emergence of lists greatly improves the practicality of arrays, but may lead to some memory space wastage\" - does this refer to the memory occupied by additional variables like capacity, length, and expansion multiplier?

The space wastage here mainly refers to two aspects: on the one hand, lists are set with an initial length, which we may not always need; on the other hand, to prevent frequent expansion, expansion usually multiplies by a coefficient, such as \\(\\times 1.5\\). This results in many empty slots, which we typically cannot fully fill.

Q: In Python, after initializing n = [1, 2, 3], the addresses of these 3 elements are contiguous, but initializing m = [2, 1, 3] shows that each element's id is not consecutive but identical to those in n. If the addresses of these elements are not contiguous, is m still an array?

If we replace list elements with linked list nodes n = [n1, n2, n3, n4, n5], these 5 node objects are also typically dispersed throughout memory. However, given a list index, we can still access the node's memory address in O(1) time, thereby accessing the corresponding node. This is because the array stores references to the nodes, not the nodes themselves.

Unlike many languages, in Python, numbers are also wrapped as objects, and lists store references to these numbers, not the numbers themselves. Therefore, we find that the same number in two arrays has the same id, and these numbers' memory addresses need not be contiguous.

Q: The std::list in C++ STL has already implemented a doubly linked list, but it seems that some algorithm books don't directly use it. Is there any limitation?

On the one hand, we often prefer to use arrays to implement algorithms, only using linked lists when necessary, mainly for two reasons.

  • Space overhead: Since each element requires two additional pointers (one for the previous element and one for the next), std::list usually occupies more space than std::vector.
  • Cache unfriendly: As the data is not stored continuously, std::list has a lower cache utilization rate. Generally, std::vector performs better.

On the other hand, linked lists are primarily necessary for binary trees and graphs. Stacks and queues are often implemented using the programming language's stack and queue classes, rather than linked lists.

Q: Does initializing a list res = [0] * self.size() result in each element of res referencing the same address?

No. However, this issue arises with two-dimensional arrays, for example, initializing a two-dimensional list res = [[0] * self.size()] would reference the same list [0] multiple times.

Q: In deleting a node, is it necessary to break the reference to its successor node?

From the perspective of data structures and algorithms (problem-solving), it's okay not to break the link, as long as the program's logic is correct. From the perspective of standard libraries, breaking the link is safer and more logically clear. If the link is not broken, and the deleted node is not properly recycled, it could affect the recycling of the successor node's memory.

"},{"location":"chapter_computational_complexity/","title":"Chapter 2. \u00a0 Complexity Analysis","text":"

Abstract

Complexity analysis is like a space-time navigator in the vast universe of algorithms.

It guides us in exploring deeper within the the dimensions of time and space, seeking more elegant solutions.

"},{"location":"chapter_computational_complexity/#chapter-contents","title":"Chapter Contents","text":"
  • 2.1 \u00a0 Algorithm Efficiency Assessment
  • 2.2 \u00a0 Iteration and Recursion
  • 2.3 \u00a0 Time Complexity
  • 2.4 \u00a0 Space Complexity
  • 2.5 \u00a0 Summary
"},{"location":"chapter_computational_complexity/iteration_and_recursion/","title":"2.2 \u00a0 Iteration and Recursion","text":"

In algorithms, repeatedly performing a task is common and closely related to complexity analysis. Therefore, before introducing time complexity and space complexity, let's first understand how to implement task repetition in programs, focusing on two basic programming control structures: iteration and recursion.

"},{"location":"chapter_computational_complexity/iteration_and_recursion/#221-iteration","title":"2.2.1 \u00a0 Iteration","text":"

\"Iteration\" is a control structure for repeatedly performing a task. In iteration, a program repeats a block of code as long as a certain condition is met, until this condition is no longer satisfied.

"},{"location":"chapter_computational_complexity/iteration_and_recursion/#1-for-loop","title":"1. \u00a0 for Loop","text":"

The for loop is one of the most common forms of iteration, suitable for use when the number of iterations is known in advance.

The following function implements the sum \\(1 + 2 + \\dots + n\\) using a for loop, with the sum result recorded in the variable res. Note that in Python, range(a, b) corresponds to a \"left-closed, right-open\" interval, covering \\(a, a + 1, \\dots, b-1\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig iteration.py
def for_loop(n: int) -> int:\n    \"\"\"for \u5faa\u73af\"\"\"\n    res = 0\n    # \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for i in range(1, n + 1):\n        res += i\n    return res\n
iteration.cpp
/* for \u5faa\u73af */\nint forLoop(int n) {\n    int res = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; ++i) {\n        res += i;\n    }\n    return res;\n}\n
iteration.java
/* for \u5faa\u73af */\nint forLoop(int n) {\n    int res = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; i++) {\n        res += i;\n    }\n    return res;\n}\n
iteration.cs
/* for \u5faa\u73af */\nint ForLoop(int n) {\n    int res = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; i++) {\n        res += i;\n    }\n    return res;\n}\n
iteration.go
/* for \u5faa\u73af */\nfunc forLoop(n int) int {\n    res := 0\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for i := 1; i <= n; i++ {\n        res += i\n    }\n    return res\n}\n
iteration.swift
/* for \u5faa\u73af */\nfunc forLoop(n: Int) -> Int {\n    var res = 0\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for i in 1 ... n {\n        res += i\n    }\n    return res\n}\n
iteration.js
/* for \u5faa\u73af */\nfunction forLoop(n) {\n    let res = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for (let i = 1; i <= n; i++) {\n        res += i;\n    }\n    return res;\n}\n
iteration.ts
/* for \u5faa\u73af */\nfunction forLoop(n: number): number {\n    let res = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for (let i = 1; i <= n; i++) {\n        res += i;\n    }\n    return res;\n}\n
iteration.dart
/* for \u5faa\u73af */\nint forLoop(int n) {\n  int res = 0;\n  // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n  for (int i = 1; i <= n; i++) {\n    res += i;\n  }\n  return res;\n}\n
iteration.rs
/* for \u5faa\u73af */\nfn for_loop(n: i32) -> i32 {\n    let mut res = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for i in 1..=n {\n        res += i;\n    }\n    res\n} \n
iteration.c
/* for \u5faa\u73af */\nint forLoop(int n) {\n    int res = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; i++) {\n        res += i;\n    }\n    return res;\n}\n
iteration.zig
// for \u5faa\u73af\nfn forLoop(n: usize) i32 {\n    var res: i32 = 0;\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for (1..n+1) |i| {\n        res = res + @as(i32, @intCast(i));\n    }\n    return res;\n} \n
Visualizing Code

Full Screen >

The flowchart below represents this sum function.

Figure 2-1 \u00a0 Flowchart of the Sum Function

The number of operations in this sum function is proportional to the input data size \\(n\\), or in other words, it has a \"linear relationship\". This is actually what time complexity describes. This topic will be detailed in the next section.

"},{"location":"chapter_computational_complexity/iteration_and_recursion/#2-while-loop","title":"2. \u00a0 while Loop","text":"

Similar to the for loop, the while loop is another method to implement iteration. In a while loop, the program checks the condition in each round; if the condition is true, it continues, otherwise, the loop ends.

Below we use a while loop to implement the sum \\(1 + 2 + \\dots + n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig iteration.py
def while_loop(n: int) -> int:\n    \"\"\"while \u5faa\u73af\"\"\"\n    res = 0\n    i = 1  # \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    # \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while i <= n:\n        res += i\n        i += 1  # \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    return res\n
iteration.cpp
/* while \u5faa\u73af */\nint whileLoop(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while (i <= n) {\n        res += i;\n        i++; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    return res;\n}\n
iteration.java
/* while \u5faa\u73af */\nint whileLoop(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while (i <= n) {\n        res += i;\n        i++; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    return res;\n}\n
iteration.cs
/* while \u5faa\u73af */\nint WhileLoop(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while (i <= n) {\n        res += i;\n        i += 1; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    return res;\n}\n
iteration.go
/* while \u5faa\u73af */\nfunc whileLoop(n int) int {\n    res := 0\n    // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    i := 1\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    for i <= n {\n        res += i\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i++\n    }\n    return res\n}\n
iteration.swift
/* while \u5faa\u73af */\nfunc whileLoop(n: Int) -> Int {\n    var res = 0\n    var i = 1 // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while i <= n {\n        res += i\n        i += 1 // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    return res\n}\n
iteration.js
/* while \u5faa\u73af */\nfunction whileLoop(n) {\n    let res = 0;\n    let i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while (i <= n) {\n        res += i;\n        i++; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    return res;\n}\n
iteration.ts
/* while \u5faa\u73af */\nfunction whileLoop(n: number): number {\n    let res = 0;\n    let i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while (i <= n) {\n        res += i;\n        i++; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    return res;\n}\n
iteration.dart
/* while \u5faa\u73af */\nint whileLoop(int n) {\n  int res = 0;\n  int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n  // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n  while (i <= n) {\n    res += i;\n    i++; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n  }\n  return res;\n}\n
iteration.rs
/* while \u5faa\u73af */\nfn while_loop(n: i32) -> i32 {\n    let mut res = 0;\n    let mut i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while i <= n {\n        res += i;\n        i += 1; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    res\n}\n
iteration.c
/* while \u5faa\u73af */\nint whileLoop(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while (i <= n) {\n        res += i;\n        i++; // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    }\n    return res;\n}\n
iteration.zig
// while \u5faa\u73af\nfn whileLoop(n: i32) i32 {\n    var res: i32 = 0;\n    var i: i32 = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 2, ..., n-1, n\n    while (i <= n) {\n        res += @intCast(i);\n        i += 1;\n    }\n    return res;\n}\n
Visualizing Code

Full Screen >

The while loop is more flexible than the for loop. In a while loop, we can freely design the initialization and update steps of the condition variable.

For example, in the following code, the condition variable \\(i\\) is updated twice in each round, which would be inconvenient to implement with a for loop:

PythonC++JavaC#GoSwiftJSTSDartRustCZig iteration.py
def while_loop_ii(n: int) -> int:\n    \"\"\"while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09\"\"\"\n    res = 0\n    i = 1  # \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    # \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while i <= n:\n        res += i\n        # \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i += 1\n        i *= 2\n    return res\n
iteration.cpp
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nint whileLoopII(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while (i <= n) {\n        res += i;\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i++;\n        i *= 2;\n    }\n    return res;\n}\n
iteration.java
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nint whileLoopII(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while (i <= n) {\n        res += i;\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i++;\n        i *= 2;\n    }\n    return res;\n}\n
iteration.cs
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nint WhileLoopII(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while (i <= n) {\n        res += i;\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i += 1; \n        i *= 2;\n    }\n    return res;\n}\n
iteration.go
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nfunc whileLoopII(n int) int {\n    res := 0\n    // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    i := 1\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    for i <= n {\n        res += i\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i++\n        i *= 2\n    }\n    return res\n}\n
iteration.swift
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nfunc whileLoopII(n: Int) -> Int {\n    var res = 0\n    var i = 1 // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while i <= n {\n        res += i\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i += 1\n        i *= 2\n    }\n    return res\n}\n
iteration.js
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nfunction whileLoopII(n) {\n    let res = 0;\n    let i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while (i <= n) {\n        res += i;\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i++;\n        i *= 2;\n    }\n    return res;\n}\n
iteration.ts
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nfunction whileLoopII(n: number): number {\n    let res = 0;\n    let i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while (i <= n) {\n        res += i;\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i++;\n        i *= 2;\n    }\n    return res;\n}\n
iteration.dart
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nint whileLoopII(int n) {\n  int res = 0;\n  int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n  // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n  while (i <= n) {\n    res += i;\n    // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n    i++;\n    i *= 2;\n  }\n  return res;\n}\n
iteration.rs
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nfn while_loop_ii(n: i32) -> i32 {\n    let mut res = 0;\n    let mut i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while i <= n {\n        res += i;\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i += 1;\n        i *= 2;\n    }\n    res\n}\n
iteration.c
/* while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09 */\nint whileLoopII(int n) {\n    int res = 0;\n    int i = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while (i <= n) {\n        res += i;\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i++;\n        i *= 2;\n    }\n    return res;\n}\n
iteration.zig
//  while \u5faa\u73af\uff08\u4e24\u6b21\u66f4\u65b0\uff09\nfn whileLoopII(n: i32) i32 {\n    var res: i32 = 0;\n    var i: i32 = 1; // \u521d\u59cb\u5316\u6761\u4ef6\u53d8\u91cf\n    // \u5faa\u73af\u6c42\u548c 1, 4, 10, ...\n    while (i <= n) {\n        res += @intCast(i);\n        // \u66f4\u65b0\u6761\u4ef6\u53d8\u91cf\n        i += 1;\n        i *= 2;\n    }\n    return res;\n}\n
Visualizing Code

Full Screen >

Overall, for loops are more concise, while while loops are more flexible. Both can implement iterative structures. Which one to use should be determined based on the specific requirements of the problem.

"},{"location":"chapter_computational_complexity/iteration_and_recursion/#3-nested-loops","title":"3. \u00a0 Nested Loops","text":"

We can nest one loop structure within another. Below is an example using for loops:

PythonC++JavaC#GoSwiftJSTSDartRustCZig iteration.py
def nested_for_loop(n: int) -> str:\n    \"\"\"\u53cc\u5c42 for \u5faa\u73af\"\"\"\n    res = \"\"\n    # \u5faa\u73af i = 1, 2, ..., n-1, n\n    for i in range(1, n + 1):\n        # \u5faa\u73af j = 1, 2, ..., n-1, n\n        for j in range(1, n + 1):\n            res += f\"({i}, {j}), \"\n    return res\n
iteration.cpp
/* \u53cc\u5c42 for \u5faa\u73af */\nstring nestedForLoop(int n) {\n    ostringstream res;\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; ++i) {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for (int j = 1; j <= n; ++j) {\n            res << \"(\" << i << \", \" << j << \"), \";\n        }\n    }\n    return res.str();\n}\n
iteration.java
/* \u53cc\u5c42 for \u5faa\u73af */\nString nestedForLoop(int n) {\n    StringBuilder res = new StringBuilder();\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; i++) {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for (int j = 1; j <= n; j++) {\n            res.append(\"(\" + i + \", \" + j + \"), \");\n        }\n    }\n    return res.toString();\n}\n
iteration.cs
/* \u53cc\u5c42 for \u5faa\u73af */\nstring NestedForLoop(int n) {\n    StringBuilder res = new();\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; i++) {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for (int j = 1; j <= n; j++) {\n            res.Append($\"({i}, {j}), \");\n        }\n    }\n    return res.ToString();\n}\n
iteration.go
/* \u53cc\u5c42 for \u5faa\u73af */\nfunc nestedForLoop(n int) string {\n    res := \"\"\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for i := 1; i <= n; i++ {\n        for j := 1; j <= n; j++ {\n            // \u5faa\u73af j = 1, 2, ..., n-1, n\n            res += fmt.Sprintf(\"(%d, %d), \", i, j)\n        }\n    }\n    return res\n}\n
iteration.swift
/* \u53cc\u5c42 for \u5faa\u73af */\nfunc nestedForLoop(n: Int) -> String {\n    var res = \"\"\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for i in 1 ... n {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for j in 1 ... n {\n            res.append(\"(\\(i), \\(j)), \")\n        }\n    }\n    return res\n}\n
iteration.js
/* \u53cc\u5c42 for \u5faa\u73af */\nfunction nestedForLoop(n) {\n    let res = '';\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for (let i = 1; i <= n; i++) {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for (let j = 1; j <= n; j++) {\n            res += `(${i}, ${j}), `;\n        }\n    }\n    return res;\n}\n
iteration.ts
/* \u53cc\u5c42 for \u5faa\u73af */\nfunction nestedForLoop(n: number): string {\n    let res = '';\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for (let i = 1; i <= n; i++) {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for (let j = 1; j <= n; j++) {\n            res += `(${i}, ${j}), `;\n        }\n    }\n    return res;\n}\n
iteration.dart
/* \u53cc\u5c42 for \u5faa\u73af */\nString nestedForLoop(int n) {\n  String res = \"\";\n  // \u5faa\u73af i = 1, 2, ..., n-1, n\n  for (int i = 1; i <= n; i++) {\n    // \u5faa\u73af j = 1, 2, ..., n-1, n\n    for (int j = 1; j <= n; j++) {\n      res += \"($i, $j), \";\n    }\n  }\n  return res;\n}\n
iteration.rs
/* \u53cc\u5c42 for \u5faa\u73af */\nfn nested_for_loop(n: i32) -> String {\n    let mut res = vec![];\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for i in 1..=n {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for j in 1..=n {\n            res.push(format!(\"({}, {}), \", i, j));\n        }\n    }\n    res.join(\"\")\n}\n
iteration.c
/* \u53cc\u5c42 for \u5faa\u73af */\nchar *nestedForLoop(int n) {\n    // n * n \u4e3a\u5bf9\u5e94\u70b9\u6570\u91cf\uff0c\"(i, j), \" \u5bf9\u5e94\u5b57\u7b26\u4e32\u957f\u6700\u5927\u4e3a 6+10*2\uff0c\u52a0\u4e0a\u6700\u540e\u4e00\u4e2a\u7a7a\u5b57\u7b26 \\0 \u7684\u989d\u5916\u7a7a\u95f4\n    int size = n * n * 26 + 1;\n    char *res = malloc(size * sizeof(char));\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for (int i = 1; i <= n; i++) {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for (int j = 1; j <= n; j++) {\n            char tmp[26];\n            snprintf(tmp, sizeof(tmp), \"(%d, %d), \", i, j);\n            strncat(res, tmp, size - strlen(res) - 1);\n        }\n    }\n    return res;\n}\n
iteration.zig
// \u53cc\u5c42 for \u5faa\u73af\nfn nestedForLoop(allocator: Allocator, n: usize) ![]const u8 {\n    var res = std.ArrayList(u8).init(allocator);\n    defer res.deinit();\n    var buffer: [20]u8 = undefined;\n    // \u5faa\u73af i = 1, 2, ..., n-1, n\n    for (1..n+1) |i| {\n        // \u5faa\u73af j = 1, 2, ..., n-1, n\n        for (1..n+1) |j| {\n            var _str = try std.fmt.bufPrint(&buffer, \"({d}, {d}), \", .{i, j});\n            try res.appendSlice(_str);\n        }\n    }\n    return res.toOwnedSlice();\n}\n
Visualizing Code

Full Screen >

The flowchart below represents this nested loop.

Figure 2-2 \u00a0 Flowchart of the Nested Loop

In this case, the number of operations in the function is proportional to \\(n^2\\), or the algorithm's running time and the input data size \\(n\\) have a \"quadratic relationship\".

We can continue adding nested loops, each nesting is a \"dimensional escalation,\" which will increase the time complexity to \"cubic,\" \"quartic,\" and so on.

"},{"location":"chapter_computational_complexity/iteration_and_recursion/#222-recursion","title":"2.2.2 \u00a0 Recursion","text":"

\"Recursion\" is an algorithmic strategy that solves problems by having a function call itself. It mainly consists of two phases.

  1. Recursion: The program continuously calls itself, usually with smaller or more simplified parameters, until reaching a \"termination condition.\"
  2. Return: Upon triggering the \"termination condition,\" the program begins to return from the deepest recursive function, aggregating the results of each layer.

From an implementation perspective, recursive code mainly includes three elements.

  1. Termination Condition: Determines when to switch from \"recursion\" to \"return.\"
  2. Recursive Call: Corresponds to \"recursion,\" where the function calls itself, usually with smaller or more simplified parameters.
  3. Return Result: Corresponds to \"return,\" where the result of the current recursion level is returned to the previous layer.

Observe the following code, where calling the function recur(n) completes the computation of \\(1 + 2 + \\dots + n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig recursion.py
def recur(n: int) -> int:\n    \"\"\"\u9012\u5f52\"\"\"\n    # \u7ec8\u6b62\u6761\u4ef6\n    if n == 1:\n        return 1\n    # \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    res = recur(n - 1)\n    # \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res\n
recursion.cpp
/* \u9012\u5f52 */\nint recur(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 1)\n        return 1;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    int res = recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res;\n}\n
recursion.java
/* \u9012\u5f52 */\nint recur(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 1)\n        return 1;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    int res = recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res;\n}\n
recursion.cs
/* \u9012\u5f52 */\nint Recur(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 1)\n        return 1;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    int res = Recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res;\n}\n
recursion.go
/* \u9012\u5f52 */\nfunc recur(n int) int {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if n == 1 {\n        return 1\n    }\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    res := recur(n - 1)\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res\n}\n
recursion.swift
/* \u9012\u5f52 */\nfunc recur(n: Int) -> Int {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if n == 1 {\n        return 1\n    }\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    let res = recur(n: n - 1)\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res\n}\n
recursion.js
/* \u9012\u5f52 */\nfunction recur(n) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n === 1) return 1;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    const res = recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res;\n}\n
recursion.ts
/* \u9012\u5f52 */\nfunction recur(n: number): number {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n === 1) return 1;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    const res = recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res;\n}\n
recursion.dart
/* \u9012\u5f52 */\nint recur(int n) {\n  // \u7ec8\u6b62\u6761\u4ef6\n  if (n == 1) return 1;\n  // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n  int res = recur(n - 1);\n  // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n  return n + res;\n}\n
recursion.rs
/* \u9012\u5f52 */\nfn recur(n: i32) -> i32 {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if n == 1 {\n        return 1;\n    }\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    let res = recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    n + res\n}\n
recursion.c
/* \u9012\u5f52 */\nint recur(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 1)\n        return 1;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    int res = recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res;\n}\n
recursion.zig
// \u9012\u5f52\u51fd\u6570\nfn recur(n: i32) i32 {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 1) {\n        return 1;\n    }\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    var res: i32 = recur(n - 1);\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    return n + res;\n}\n
Visualizing Code

Full Screen >

The Figure 2-3 shows the recursive process of this function.

Figure 2-3 \u00a0 Recursive Process of the Sum Function

Although iteration and recursion can achieve the same results from a computational standpoint, they represent two entirely different paradigms of thinking and solving problems.

  • Iteration: Solves problems \"from the bottom up.\" It starts with the most basic steps, then repeatedly adds or accumulates these steps until the task is complete.
  • Recursion: Solves problems \"from the top down.\" It breaks down the original problem into smaller sub-problems, each of which has the same form as the original problem. These sub-problems are then further decomposed into even smaller sub-problems, stopping at the base case (whose solution is known).

Taking the sum function as an example, let's define the problem as \\(f(n) = 1 + 2 + \\dots + n\\).

  • Iteration: In a loop, simulate the summing process, iterating from \\(1\\) to \\(n\\), performing the sum operation in each round, to obtain \\(f(n)\\).
  • Recursion: Break down the problem into sub-problems \\(f(n) = n + f(n-1)\\), continuously (recursively) decomposing until reaching the base case \\(f(1) = 1\\) and then stopping.
"},{"location":"chapter_computational_complexity/iteration_and_recursion/#1-call-stack","title":"1. \u00a0 Call Stack","text":"

Each time a recursive function calls itself, the system allocates memory for the newly initiated function to store local variables, call addresses, and other information. This leads to two main consequences.

  • The function's context data is stored in a memory area called \"stack frame space\" and is only released after the function returns. Therefore, recursion generally consumes more memory space than iteration.
  • Recursive calls introduce additional overhead. Hence, recursion is usually less time-efficient than loops.

As shown in the Figure 2-4 , there are \\(n\\) unreturned recursive functions before triggering the termination condition, indicating a recursion depth of \\(n\\).

Figure 2-4 \u00a0 Recursion Call Depth

In practice, the depth of recursion allowed by programming languages is usually limited, and excessively deep recursion can lead to stack overflow errors.

"},{"location":"chapter_computational_complexity/iteration_and_recursion/#2-tail-recursion","title":"2. \u00a0 Tail Recursion","text":"

Interestingly, if a function makes its recursive call as the last step before returning, it can be optimized by compilers or interpreters to be as space-efficient as iteration. This scenario is known as \"tail recursion\".

  • Regular Recursion: The function needs to perform more code after returning to the previous level, so the system needs to save the context of the previous call.
  • Tail Recursion: The recursive call is the last operation before the function returns, meaning no further actions are required upon returning to the previous level, so the system doesn't need to save the context of the previous level's function.

For example, in calculating \\(1 + 2 + \\dots + n\\), we can make the result variable res a parameter of the function, thereby achieving tail recursion:

PythonC++JavaC#GoSwiftJSTSDartRustCZig recursion.py
def tail_recur(n, res):\n    \"\"\"\u5c3e\u9012\u5f52\"\"\"\n    # \u7ec8\u6b62\u6761\u4ef6\n    if n == 0:\n        return res\n    # \u5c3e\u9012\u5f52\u8c03\u7528\n    return tail_recur(n - 1, res + n)\n
recursion.cpp
/* \u5c3e\u9012\u5f52 */\nint tailRecur(int n, int res) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 0)\n        return res;\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n - 1, res + n);\n}\n
recursion.java
/* \u5c3e\u9012\u5f52 */\nint tailRecur(int n, int res) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 0)\n        return res;\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n - 1, res + n);\n}\n
recursion.cs
/* \u5c3e\u9012\u5f52 */\nint TailRecur(int n, int res) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 0)\n        return res;\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return TailRecur(n - 1, res + n);\n}\n
recursion.go
/* \u5c3e\u9012\u5f52 */\nfunc tailRecur(n int, res int) int {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if n == 0 {\n        return res\n    }\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n-1, res+n)\n}\n
recursion.swift
/* \u5c3e\u9012\u5f52 */\nfunc tailRecur(n: Int, res: Int) -> Int {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if n == 0 {\n        return res\n    }\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n: n - 1, res: res + n)\n}\n
recursion.js
/* \u5c3e\u9012\u5f52 */\nfunction tailRecur(n, res) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n === 0) return res;\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n - 1, res + n);\n}\n
recursion.ts
/* \u5c3e\u9012\u5f52 */\nfunction tailRecur(n: number, res: number): number {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n === 0) return res;\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n - 1, res + n);\n}\n
recursion.dart
/* \u5c3e\u9012\u5f52 */\nint tailRecur(int n, int res) {\n  // \u7ec8\u6b62\u6761\u4ef6\n  if (n == 0) return res;\n  // \u5c3e\u9012\u5f52\u8c03\u7528\n  return tailRecur(n - 1, res + n);\n}\n
recursion.rs
/* \u5c3e\u9012\u5f52 */\nfn tail_recur(n: i32, res: i32) -> i32 {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if n == 0 {\n        return res;\n    }\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    tail_recur(n - 1, res + n)\n}\n
recursion.c
/* \u5c3e\u9012\u5f52 */\nint tailRecur(int n, int res) {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 0)\n        return res;\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n - 1, res + n);\n}\n
recursion.zig
// \u5c3e\u9012\u5f52\u51fd\u6570\nfn tailRecur(n: i32, res: i32) i32 {\n    // \u7ec8\u6b62\u6761\u4ef6\n    if (n == 0) {\n        return res;\n    }\n    // \u5c3e\u9012\u5f52\u8c03\u7528\n    return tailRecur(n - 1, res + n);\n}\n
Visualizing Code

Full Screen >

The execution process of tail recursion is shown in the following figure. Comparing regular recursion and tail recursion, the point of the summation operation is different.

  • Regular Recursion: The summation operation occurs during the \"return\" phase, requiring another summation after each layer returns.
  • Tail Recursion: The summation operation occurs during the \"recursion\" phase, and the \"return\" phase only involves returning through each layer.

Figure 2-5 \u00a0 Tail Recursion Process

Tip

Note that many compilers or interpreters do not support tail recursion optimization. For example, Python does not support tail recursion optimization by default, so even if the function is in the form of tail recursion, it may still encounter stack overflow issues.

"},{"location":"chapter_computational_complexity/iteration_and_recursion/#3-recursion-tree","title":"3. \u00a0 Recursion Tree","text":"

When dealing with algorithms related to \"divide and conquer\", recursion often offers a more intuitive approach and more readable code than iteration. Take the \"Fibonacci sequence\" as an example.

Question

Given a Fibonacci sequence \\(0, 1, 1, 2, 3, 5, 8, 13, \\dots\\), find the \\(n\\)th number in the sequence.

Let the \\(n\\)th number of the Fibonacci sequence be \\(f(n)\\), it's easy to deduce two conclusions:

  • The first two numbers of the sequence are \\(f(1) = 0\\) and \\(f(2) = 1\\).
  • Each number in the sequence is the sum of the two preceding ones, that is, \\(f(n) = f(n - 1) + f(n - 2)\\).

Using the recursive relation, and considering the first two numbers as termination conditions, we can write the recursive code. Calling fib(n) will yield the \\(n\\)th number of the Fibonacci sequence:

PythonC++JavaC#GoSwiftJSTSDartRustCZig recursion.py
def fib(n: int) -> int:\n    \"\"\"\u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52\"\"\"\n    # \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if n == 1 or n == 2:\n        return n - 1\n    # \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    res = fib(n - 1) + fib(n - 2)\n    # \u8fd4\u56de\u7ed3\u679c f(n)\n    return res\n
recursion.cpp
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nint fib(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if (n == 1 || n == 2)\n        return n - 1;\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    int res = fib(n - 1) + fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res;\n}\n
recursion.java
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nint fib(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if (n == 1 || n == 2)\n        return n - 1;\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    int res = fib(n - 1) + fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res;\n}\n
recursion.cs
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nint Fib(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if (n == 1 || n == 2)\n        return n - 1;\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    int res = Fib(n - 1) + Fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res;\n}\n
recursion.go
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nfunc fib(n int) int {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if n == 1 || n == 2 {\n        return n - 1\n    }\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    res := fib(n-1) + fib(n-2)\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res\n}\n
recursion.swift
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nfunc fib(n: Int) -> Int {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if n == 1 || n == 2 {\n        return n - 1\n    }\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    let res = fib(n: n - 1) + fib(n: n - 2)\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res\n}\n
recursion.js
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nfunction fib(n) {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if (n === 1 || n === 2) return n - 1;\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    const res = fib(n - 1) + fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res;\n}\n
recursion.ts
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nfunction fib(n: number): number {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if (n === 1 || n === 2) return n - 1;\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    const res = fib(n - 1) + fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res;\n}\n
recursion.dart
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nint fib(int n) {\n  // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n  if (n == 1 || n == 2) return n - 1;\n  // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n  int res = fib(n - 1) + fib(n - 2);\n  // \u8fd4\u56de\u7ed3\u679c f(n)\n  return res;\n}\n
recursion.rs
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nfn fib(n: i32) -> i32 {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if n == 1 || n == 2 {\n        return n - 1;\n    }\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    let res = fib(n - 1) + fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c\n    res\n}\n
recursion.c
/* \u6590\u6ce2\u90a3\u5951\u6570\u5217\uff1a\u9012\u5f52 */\nint fib(int n) {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if (n == 1 || n == 2)\n        return n - 1;\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    int res = fib(n - 1) + fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res;\n}\n
recursion.zig
// \u6590\u6ce2\u90a3\u5951\u6570\u5217\nfn fib(n: i32) i32 {\n    // \u7ec8\u6b62\u6761\u4ef6 f(1) = 0, f(2) = 1\n    if (n == 1 or n == 2) {\n        return n - 1;\n    }\n    // \u9012\u5f52\u8c03\u7528 f(n) = f(n-1) + f(n-2)\n    var res: i32 = fib(n - 1) + fib(n - 2);\n    // \u8fd4\u56de\u7ed3\u679c f(n)\n    return res;\n}\n
Visualizing Code

Full Screen >

Observing the above code, we see that it recursively calls two functions within itself, meaning that one call generates two branching calls. As illustrated below, this continuous recursive calling eventually creates a \"recursion tree\" with a depth of \\(n\\).

Figure 2-6 \u00a0 Fibonacci Sequence Recursion Tree

Fundamentally, recursion embodies the paradigm of \"breaking down a problem into smaller sub-problems.\" This divide-and-conquer strategy is crucial.

  • From an algorithmic perspective, many important strategies like searching, sorting, backtracking, divide-and-conquer, and dynamic programming directly or indirectly use this way of thinking.
  • From a data structure perspective, recursion is naturally suited for dealing with linked lists, trees, and graphs, as they are well suited for analysis using the divide-and-conquer approach.
"},{"location":"chapter_computational_complexity/iteration_and_recursion/#223-comparison","title":"2.2.3 \u00a0 Comparison","text":"

Summarizing the above content, the following table shows the differences between iteration and recursion in terms of implementation, performance, and applicability.

Table: Comparison of Iteration and Recursion Characteristics

Iteration Recursion Approach Loop structure Function calls itself Time Efficiency Generally higher efficiency, no function call overhead Each function call generates overhead Memory Usage Typically uses a fixed size of memory space Accumulative function calls can use a substantial amount of stack frame space Suitable Problems Suitable for simple loop tasks, intuitive and readable code Suitable for problem decomposition, like trees, graphs, divide-and-conquer, backtracking, etc., concise and clear code structure

Tip

If you find the following content difficult to understand, consider revisiting it after reading the \"Stack\" chapter.

So, what is the intrinsic connection between iteration and recursion? Taking the above recursive function as an example, the summation operation occurs during the recursion's \"return\" phase. This means that the initially called function is actually the last to complete its summation operation, mirroring the \"last in, first out\" principle of a stack.

In fact, recursive terms like \"call stack\" and \"stack frame space\" hint at the close relationship between recursion and stacks.

  1. Recursion: When a function is called, the system allocates a new stack frame on the \"call stack\" for that function, storing local variables, parameters, return addresses, and other data.
  2. Return: When a function completes execution and returns, the corresponding stack frame is removed from the \"call stack,\" restoring the execution environment of the previous function.

Therefore, we can use an explicit stack to simulate the behavior of the call stack, thus transforming recursion into an iterative form:

PythonC++JavaC#GoSwiftJSTSDartRustCZig recursion.py
def for_loop_recur(n: int) -> int:\n    \"\"\"\u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52\"\"\"\n    # \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    stack = []\n    res = 0\n    # \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for i in range(n, 0, -1):\n        # \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.append(i)\n    # \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while stack:\n        # \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.pop()\n    # res = 1+2+3+...+n\n    return res\n
recursion.cpp
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nint forLoopRecur(int n) {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    stack<int> stack;\n    int res = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for (int i = n; i > 0; i--) {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.push(i);\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while (!stack.empty()) {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.top();\n        stack.pop();\n    }\n    // res = 1+2+3+...+n\n    return res;\n}\n
recursion.java
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nint forLoopRecur(int n) {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    Stack<Integer> stack = new Stack<>();\n    int res = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for (int i = n; i > 0; i--) {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.push(i);\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while (!stack.isEmpty()) {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.pop();\n    }\n    // res = 1+2+3+...+n\n    return res;\n}\n
recursion.cs
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nint ForLoopRecur(int n) {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    Stack<int> stack = new();\n    int res = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for (int i = n; i > 0; i--) {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.Push(i);\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while (stack.Count > 0) {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.Pop();\n    }\n    // res = 1+2+3+...+n\n    return res;\n}\n
recursion.go
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nfunc forLoopRecur(n int) int {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    stack := list.New()\n    res := 0\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for i := n; i > 0; i-- {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.PushBack(i)\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    for stack.Len() != 0 {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.Back().Value.(int)\n        stack.Remove(stack.Back())\n    }\n    // res = 1+2+3+...+n\n    return res\n}\n
recursion.swift
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nfunc forLoopRecur(n: Int) -> Int {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    var stack: [Int] = []\n    var res = 0\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for i in stride(from: n, to: 0, by: -1) {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.append(i)\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while !stack.isEmpty {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.removeLast()\n    }\n    // res = 1+2+3+...+n\n    return res\n}\n
recursion.js
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nfunction forLoopRecur(n) {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    const stack = [];\n    let res = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for (let i = n; i > 0; i--) {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.push(i);\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while (stack.length) {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.pop();\n    }\n    // res = 1+2+3+...+n\n    return res;\n}\n
recursion.ts
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nfunction forLoopRecur(n: number): number {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808 \n    const stack: number[] = [];\n    let res: number = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for (let i = n; i > 0; i--) {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.push(i);\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while (stack.length) {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.pop();\n    }\n    // res = 1+2+3+...+n\n    return res;\n}\n
recursion.dart
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nint forLoopRecur(int n) {\n  // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n  List<int> stack = [];\n  int res = 0;\n  // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n  for (int i = n; i > 0; i--) {\n    // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n    stack.add(i);\n  }\n  // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n  while (!stack.isEmpty) {\n    // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n    res += stack.removeLast();\n  }\n  // res = 1+2+3+...+n\n  return res;\n}\n
recursion.rs
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nfn for_loop_recur(n: i32) -> i32 {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    let mut stack = Vec::new();\n    let mut res = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for i in (1..=n).rev() {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack.push(i);\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while !stack.is_empty() {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack.pop().unwrap();\n    }\n    // res = 1+2+3+...+n\n    res\n}\n
recursion.c
/* \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52 */\nint forLoopRecur(int n) {\n    int stack[1000]; // \u501f\u52a9\u4e00\u4e2a\u5927\u6570\u7ec4\u6765\u6a21\u62df\u6808\n    int top = -1;    // \u6808\u9876\u7d22\u5f15\n    int res = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    for (int i = n; i > 0; i--) {\n        // \u901a\u8fc7\u201c\u5165\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u9012\u201d\n        stack[1 + top++] = i;\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    while (top >= 0) {\n        // \u901a\u8fc7\u201c\u51fa\u6808\u64cd\u4f5c\u201d\u6a21\u62df\u201c\u5f52\u201d\n        res += stack[top--];\n    }\n    // res = 1+2+3+...+n\n    return res;\n}\n
recursion.zig
// \u4f7f\u7528\u8fed\u4ee3\u6a21\u62df\u9012\u5f52\nfn forLoopRecur(comptime n: i32) i32 {\n    // \u4f7f\u7528\u4e00\u4e2a\u663e\u5f0f\u7684\u6808\u6765\u6a21\u62df\u7cfb\u7edf\u8c03\u7528\u6808\n    var stack: [n]i32 = undefined;\n    var res: i32 = 0;\n    // \u9012\uff1a\u9012\u5f52\u8c03\u7528\n    var i: usize = n;\n    while (i > 0) {\n        stack[i - 1] = @intCast(i);\n        i -= 1;\n    }\n    // \u5f52\uff1a\u8fd4\u56de\u7ed3\u679c\n    var index: usize = n;\n    while (index > 0) {\n        index -= 1;\n        res += stack[index];\n    }\n    // res = 1+2+3+...+n\n    return res;\n}\n
Visualizing Code

Full Screen >

Observing the above code, when recursion is transformed into iteration, the code becomes more complex. Although iteration and recursion can often be transformed into each other, it's not always advisable to do so for two reasons:

  • The transformed code may become harder to understand and less readable.
  • For some complex problems, simulating the behavior of the system's call stack can be quite challenging.

In summary, choosing between iteration and recursion depends on the nature of the specific problem. In programming practice, weighing the pros and cons of each and choosing the appropriate method for the situation is essential.

"},{"location":"chapter_computational_complexity/performance_evaluation/","title":"2.1 \u00a0 Algorithm Efficiency Assessment","text":"

In algorithm design, we pursue the following two objectives in sequence.

  1. Finding a Solution to the Problem: The algorithm should reliably find the correct solution within the stipulated range of inputs.
  2. Seeking the Optimal Solution: For the same problem, multiple solutions might exist, and we aim to find the most efficient algorithm possible.

In other words, under the premise of being able to solve the problem, algorithm efficiency has become the main criterion for evaluating the merits of an algorithm, which includes the following two dimensions.

  • Time Efficiency: The speed at which an algorithm runs.
  • Space Efficiency: The size of the memory space occupied by an algorithm.

In short, our goal is to design data structures and algorithms that are both fast and memory-efficient. Effectively assessing algorithm efficiency is crucial because only then can we compare various algorithms and guide the process of algorithm design and optimization.

There are mainly two methods of efficiency assessment: actual testing and theoretical estimation.

"},{"location":"chapter_computational_complexity/performance_evaluation/#211-actual-testing","title":"2.1.1 \u00a0 Actual Testing","text":"

Suppose we have algorithms A and B, both capable of solving the same problem, and we need to compare their efficiencies. The most direct method is to use a computer to run these two algorithms and monitor and record their runtime and memory usage. This assessment method reflects the actual situation but has significant limitations.

On one hand, it's difficult to eliminate interference from the testing environment. Hardware configurations can affect algorithm performance. For example, algorithm A might run faster than B on one computer, but the opposite result may occur on another computer with different configurations. This means we would need to test on a variety of machines to calculate average efficiency, which is impractical.

On the other hand, conducting a full test is very resource-intensive. As the volume of input data changes, the efficiency of the algorithms may vary. For example, with smaller data volumes, algorithm A might run faster than B, but the opposite might be true with larger data volumes. Therefore, to draw convincing conclusions, we need to test a wide range of input data sizes, which requires significant computational resources.

"},{"location":"chapter_computational_complexity/performance_evaluation/#212-theoretical-estimation","title":"2.1.2 \u00a0 Theoretical Estimation","text":"

Due to the significant limitations of actual testing, we can consider evaluating algorithm efficiency solely through calculations. This estimation method is known as \"asymptotic complexity analysis,\" or simply \"complexity analysis.\"

Complexity analysis reflects the relationship between the time and space resources required for algorithm execution and the size of the input data. It describes the trend of growth in the time and space required by the algorithm as the size of the input data increases. This definition might sound complex, but we can break it down into three key points to understand it better.

  • \"Time and space resources\" correspond to \"time complexity\" and \"space complexity,\" respectively.
  • \"As the size of input data increases\" means that complexity reflects the relationship between algorithm efficiency and the volume of input data.
  • \"The trend of growth in time and space\" indicates that complexity analysis focuses not on the specific values of runtime or space occupied but on the \"rate\" at which time or space grows.

Complexity analysis overcomes the disadvantages of actual testing methods, reflected in the following aspects:

  • It is independent of the testing environment and applicable to all operating platforms.
  • It can reflect algorithm efficiency under different data volumes, especially in the performance of algorithms with large data volumes.

Tip

If you're still confused about the concept of complexity, don't worry. We will introduce it in detail in subsequent chapters.

Complexity analysis provides us with a \"ruler\" to measure the time and space resources needed to execute an algorithm and compare the efficiency between different algorithms.

Complexity is a mathematical concept and may be abstract and challenging for beginners. From this perspective, complexity analysis might not be the best content to introduce first. However, when discussing the characteristics of a particular data structure or algorithm, it's hard to avoid analyzing its speed and space usage.

In summary, it's recommended that you establish a preliminary understanding of complexity analysis before diving deep into data structures and algorithms, so that you can carry out simple complexity analyses of algorithms.

"},{"location":"chapter_computational_complexity/space_complexity/","title":"2.4 \u00a0 Space Complexity","text":"

\"Space complexity\" is used to measure the growth trend of the memory space occupied by an algorithm as the amount of data increases. This concept is very similar to time complexity, except that \"running time\" is replaced with \"occupied memory space\".

"},{"location":"chapter_computational_complexity/space_complexity/#241-space-related-to-algorithms","title":"2.4.1 \u00a0 Space Related to Algorithms","text":"

The memory space used by an algorithm during its execution mainly includes the following types.

  • Input Space: Used to store the input data of the algorithm.
  • Temporary Space: Used to store variables, objects, function contexts, and other data during the algorithm's execution.
  • Output Space: Used to store the output data of the algorithm.

Generally, the scope of space complexity statistics includes both \"Temporary Space\" and \"Output Space\".

Temporary space can be further divided into three parts.

  • Temporary Data: Used to save various constants, variables, objects, etc., during the algorithm's execution.
  • Stack Frame Space: Used to save the context data of the called function. The system creates a stack frame at the top of the stack each time a function is called, and the stack frame space is released after the function returns.
  • Instruction Space: Used to store compiled program instructions, which are usually negligible in actual statistics.

When analyzing the space complexity of a program, we typically count the Temporary Data, Stack Frame Space, and Output Data, as shown in the Figure 2-15 .

Figure 2-15 \u00a0 Space Types Used in Algorithms

The relevant code is as follows:

PythonC++JavaC#GoSwiftJSTSDartRustCZig
class Node:\n    \"\"\"Classes\"\"\"\"\n    def __init__(self, x: int):\n        self.val: int = x               # node value\n        self.next: Node | None = None   # reference to the next node\n\ndef function() -> int:\n    \"\"\"\"Functions\"\"\"\"\"\n    # Perform certain operations...\n    return 0\n\ndef algorithm(n) -> int:    # input data\n    A = 0                   # temporary data (constant, usually in uppercase)\n    b = 0                   # temporary data (variable)\n    node = Node(0)          # temporary data (object)\n    c = function()          # Stack frame space (call function)\n    return A + b + c        # output data\n
/* Structures */\nstruct Node {\n    int val;\n    Node *next;\n    Node(int x) : val(x), next(nullptr) {}\n};\n\n/* Functions */\nint func() {\n    // Perform certain operations...\n    return 0;\n}\n\nint algorithm(int n) {          // input data\n    const int a = 0;            // temporary data (constant)\n    int b = 0;                  // temporary data (variable)\n    Node* node = new Node(0);   // temporary data (object)\n    int c = func();             // stack frame space (call function)\n    return a + b + c;           // output data\n}\n
/* Classes */\nclass Node {\n    int val;\n    Node next;\n    Node(int x) { val = x; }\n}\n\n/* Functions */\nint function() {\n    // Perform certain operations...\n    return 0;\n}\n\nint algorithm(int n) {          // input data\n    final int a = 0;            // temporary data (constant)\n    int b = 0;                  // temporary data (variable)\n    Node node = new Node(0);    // temporary data (object)\n    int c = function();         // stack frame space (call function)\n    return a + b + c;           // output data\n}\n
/* Classes */\nclass Node {\n    int val;\n    Node next;\n    Node(int x) { val = x; }\n}\n\n/* Functions */\nint Function() {\n    // Perform certain operations...\n    return 0;\n}\n\nint Algorithm(int n) {  // input data\n    const int a = 0;    // temporary data (constant)\n    int b = 0;          // temporary data (variable)\n    Node node = new(0); // temporary data (object)\n    int c = Function(); // stack frame space (call function)\n    return a + b + c;   // output data\n}\n
/* Structures */\ntype node struct {\n    val  int\n    next *node\n}\n\n/* Create node structure */\nfunc newNode(val int) *node {\n    return &node{val: val}\n}\n\n/* Functions */\nfunc function() int {\n    // Perform certain operations...\n    return 0\n}\n\nfunc algorithm(n int) int { // input data\n    const a = 0             // temporary data (constant)\n    b := 0                  // temporary storage of data (variable)\n    newNode(0)              // temporary data (object)\n    c := function()         // stack frame space (call function)\n    return a + b + c        // output data\n}\n
/* Classes */\nclass Node {\n    var val: Int\n    var next: Node?\n\n    init(x: Int) {\n        val = x\n    }\n}\n\n/* Functions */\nfunc function() -> Int {\n    // Perform certain operations...\n    return 0\n}\n\nfunc algorithm(n: Int) -> Int { // input data\n    let a = 0                   // temporary data (constant)\n    var b = 0                   // temporary data (variable)\n    let node = Node(x: 0)       // temporary data (object)\n    let c = function()          // stack frame space (call function)\n    return a + b + c            // output data\n}\n
/* Classes */\nclass Node {\n    val;\n    next;\n    constructor(val) {\n        this.val = val === undefined ? 0 : val; // node value\n        this.next = null;                       // reference to the next node\n    }\n}\n\n/* Functions */\nfunction constFunc() {\n    // Perform certain operations\n    return 0;\n}\n\nfunction algorithm(n) {         // input data\n    const a = 0;                // temporary data (constant)\n    let b = 0;                  // temporary data (variable)\n    const node = new Node(0);   // temporary data (object)\n    const c = constFunc();      // Stack frame space (calling function)\n    return a + b + c;           // output data\n}\n
/* Classes */\nclass Node {\n    val: number;\n    next: Node | null;\n    constructor(val?: number) {\n        this.val = val === undefined ? 0 : val; // node value\n        this.next = null;                       // reference to the next node\n    }\n}\n\n/* Functions */\nfunction constFunc(): number {\n    // Perform certain operations\n    return 0;\n}\n\nfunction algorithm(n: number): number { // input data\n    const a = 0;                        // temporary data (constant)\n    let b = 0;                          // temporary data (variable)\n    const node = new Node(0);           // temporary data (object)\n    const c = constFunc();              // Stack frame space (calling function)\n    return a + b + c;                   // output data\n}\n
/* Classes */\nclass Node {\n  int val;\n  Node next;\n  Node(this.val, [this.next]);\n}\n\n/* Functions */\nint function() {\n  // Perform certain operations...\n  return 0;\n}\n\nint algorithm(int n) {  // input data\n  const int a = 0;      // temporary data (constant)\n  int b = 0;            // temporary data (variable)\n  Node node = Node(0);  // temporary data (object)\n  int c = function();   // stack frame space (call function)\n  return a + b + c;     // output data\n}\n
use std::rc::Rc;\nuse std::cell::RefCell;\n\n/* Structures */\nstruct Node {\n    val: i32,\n    next: Option<Rc<RefCell<Node>>>,\n}\n\n/* Creating a Node structure */\nimpl Node {\n    fn new(val: i32) -> Self {\n        Self { val: val, next: None }\n    }\n}\n\n/* Functions */\nfn function() -> i32 {     \n    // Perform certain operations...\n    return 0;\n}\n\nfn algorithm(n: i32) -> i32 {   // input data\n    const a: i32 = 0;           // temporary data (constant)\n    let mut b = 0;              // temporary data (variable)\n    let node = Node::new(0);    // temporary data (object)\n    let c = function();         // stack frame space (call function)\n    return a + b + c;           // output data\n}\n
/* Functions */\nint func() {\n    // Perform certain operations...\n    return 0;\n}\n\nint algorithm(int n) {  // input data\n    const int a = 0;    // temporary data (constant)\n    int b = 0;          // temporary data (variable)\n    int c = func();     // stack frame space (call function)\n    return a + b + c;   // output data\n}\n
\n
"},{"location":"chapter_computational_complexity/space_complexity/#242-calculation-method","title":"2.4.2 \u00a0 Calculation Method","text":"

The method for calculating space complexity is roughly similar to that of time complexity, with the only change being the shift of the statistical object from \"number of operations\" to \"size of used space\".

However, unlike time complexity, we usually only focus on the worst-case space complexity. This is because memory space is a hard requirement, and we must ensure that there is enough memory space reserved under all input data.

Consider the following code, the term \"worst-case\" in worst-case space complexity has two meanings.

  1. Based on the worst input data: When \\(n < 10\\), the space complexity is \\(O(1)\\); but when \\(n > 10\\), the initialized array nums occupies \\(O(n)\\) space, thus the worst-case space complexity is \\(O(n)\\).
  2. Based on the peak memory used during the algorithm's execution: For example, before executing the last line, the program occupies \\(O(1)\\) space; when initializing the array nums, the program occupies \\(O(n)\\) space, hence the worst-case space complexity is \\(O(n)\\).
PythonC++JavaC#GoSwiftJSTSDartRustCZig
def algorithm(n: int):\n    a = 0               # O(1)\n    b = [0] * 10000     # O(1)\n    if n > 10:\n        nums = [0] * n  # O(n)\n
void algorithm(int n) {\n    int a = 0;               // O(1)\n    vector<int> b(10000);    // O(1)\n    if (n > 10)\n        vector<int> nums(n); // O(n)\n}\n
void algorithm(int n) {\n    int a = 0;                   // O(1)\n    int[] b = new int[10000];    // O(1)\n    if (n > 10)\n        int[] nums = new int[n]; // O(n)\n}\n
void Algorithm(int n) {\n    int a = 0;                   // O(1)\n    int[] b = new int[10000];    // O(1)\n    if (n > 10) {\n        int[] nums = new int[n]; // O(n)\n    }\n}\n
func algorithm(n int) {\n    a := 0                      // O(1)\n    b := make([]int, 10000)     // O(1)\n    var nums []int\n    if n > 10 {\n        nums := make([]int, n)  // O(n)\n    }\n    fmt.Println(a, b, nums)\n}\n
func algorithm(n: Int) {\n    let a = 0 // O(1)\n    let b = Array(repeating: 0, count: 10000) // O(1)\n    if n > 10 {\n        let nums = Array(repeating: 0, count: n) // O(n)\n    }\n}\n
function algorithm(n) {\n    const a = 0;                   // O(1)\n    const b = new Array(10000);    // O(1)\n    if (n > 10) {\n        const nums = new Array(n); // O(n)\n    }\n}\n
function algorithm(n: number): void {\n    const a = 0;                   // O(1)\n    const b = new Array(10000);    // O(1)\n    if (n > 10) {\n        const nums = new Array(n); // O(n)\n    }\n}\n
void algorithm(int n) {\n  int a = 0;                            // O(1)\n  List<int> b = List.filled(10000, 0);  // O(1)\n  if (n > 10) {\n    List<int> nums = List.filled(n, 0); // O(n)\n  }\n}\n
fn algorithm(n: i32) {\n    let a = 0;                              // O(1)\n    let b = [0; 10000];                     // O(1)\n    if n > 10 {\n        let nums = vec![0; n as usize];     // O(n)\n    }\n}\n
void algorithm(int n) {\n    int a = 0;               // O(1)\n    int b[10000];            // O(1)\n    if (n > 10)\n        int nums[n] = {0};   // O(n)\n}\n
\n

In recursive functions, stack frame space must be taken into count. Consider the following code:

PythonC++JavaC#GoSwiftJSTSDartRustCZig
def function() -> int:\n    # Perform certain operations\n    return 0\n\ndef loop(n: int):\n    \"\"\"Loop O(1)\"\"\"\"\"\n    for _ in range(n):\n        function()\n\ndef recur(n: int) -> int:\n    \"\"\"Recursion O(n)\"\"\"\"\"\n    if n == 1: return\n    return recur(n - 1)\n
int func() {\n    // Perform certain operations\n    return 0;\n}\n/* Cycle O(1) */\nvoid loop(int n) {\n    for (int i = 0; i < n; i++) {\n        func();\n    }\n}\n/* Recursion O(n) */\nvoid recur(int n) {\n    if (n == 1) return;\n    return recur(n - 1);\n}\n
int function() {\n    // Perform certain operations\n    return 0;\n}\n/* Cycle O(1) */\nvoid loop(int n) {\n    for (int i = 0; i < n; i++) {\n        function();\n    }\n}\n/* Recursion O(n) */\nvoid recur(int n) {\n    if (n == 1) return;\n    return recur(n - 1);\n}\n
int Function() {\n    // Perform certain operations\n    return 0;\n}\n/* Cycle O(1) */\nvoid Loop(int n) {\n    for (int i = 0; i < n; i++) {\n        Function();\n    }\n}\n/* Recursion O(n) */\nint Recur(int n) {\n    if (n == 1) return 1;\n    return Recur(n - 1);\n}\n
func function() int {\n    // Perform certain operations\n    return 0\n}\n\n/* Cycle O(1) */\nfunc loop(n int) {\n    for i := 0; i < n; i++ {\n        function()\n    }\n}\n\n/* Recursion O(n) */\nfunc recur(n int) {\n    if n == 1 {\n        return\n    }\n    recur(n - 1)\n}\n
@discardableResult\nfunc function() -> Int {\n    // Perform certain operations\n    return 0\n}\n\n/* Cycle O(1) */\nfunc loop(n: Int) {\n    for _ in 0 ..< n {\n        function()\n    }\n}\n\n/* Recursion O(n) */\nfunc recur(n: Int) {\n    if n == 1 {\n        return\n    }\n    recur(n: n - 1)\n}\n
function constFunc() {\n    // Perform certain operations\n    return 0;\n}\n/* Cycle O(1) */\nfunction loop(n) {\n    for (let i = 0; i < n; i++) {\n        constFunc();\n    }\n}\n/* Recursion O(n) */\nfunction recur(n) {\n    if (n === 1) return;\n    return recur(n - 1);\n}\n
function constFunc(): number {\n    // Perform certain operations\n    return 0;\n}\n/* Cycle O(1) */\nfunction loop(n: number): void {\n    for (let i = 0; i < n; i++) {\n        constFunc();\n    }\n}\n/* Recursion O(n) */\nfunction recur(n: number): void {\n    if (n === 1) return;\n    return recur(n - 1);\n}\n
int function() {\n  // Perform certain operations\n  return 0;\n}\n/* Cycle O(1) */\nvoid loop(int n) {\n  for (int i = 0; i < n; i++) {\n    function();\n  }\n}\n/* Recursion O(n) */\nvoid recur(int n) {\n  if (n == 1) return;\n  return recur(n - 1);\n}\n
fn function() -> i32 {\n    // Perform certain operations\n    return 0;\n}\n/* Cycle O(1) */\nfn loop(n: i32) {\n    for i in 0..n {\n        function();\n    }\n}\n/* Recursion O(n) */\nvoid recur(n: i32) {\n    if n == 1 {\n        return;\n    }\n    recur(n - 1);\n}\n
int func() {\n    // Perform certain operations\n    return 0;\n}\n/* Cycle O(1) */\nvoid loop(int n) {\n    for (int i = 0; i < n; i++) {\n        func();\n    }\n}\n/* Recursion O(n) */\nvoid recur(int n) {\n    if (n == 1) return;\n    return recur(n - 1);\n}\n
\n

The time complexity of both loop() and recur() functions is \\(O(n)\\), but their space complexities differ.

  • The loop() function calls function() \\(n\\) times in a loop, where each iteration's function() returns and releases its stack frame space, so the space complexity remains \\(O(1)\\).
  • The recursive function recur() will have \\(n\\) instances of unreturned recur() existing simultaneously during its execution, thus occupying \\(O(n)\\) stack frame space.
"},{"location":"chapter_computational_complexity/space_complexity/#243-common-types","title":"2.4.3 \u00a0 Common Types","text":"

Let the size of the input data be \\(n\\), the following chart displays common types of space complexities (arranged from low to high).

\\[ \\begin{aligned} O(1) < O(\\log n) < O(n) < O(n^2) < O(2^n) \\newline \\text{Constant Order} < \\text{Logarithmic Order} < \\text{Linear Order} < \\text{Quadratic Order} < \\text{Exponential Order} \\end{aligned} \\]

Figure 2-16 \u00a0 Common Types of Space Complexity

"},{"location":"chapter_computational_complexity/space_complexity/#1-constant-order-o1","title":"1. \u00a0 Constant Order \\(O(1)\\)","text":"

Constant order is common in constants, variables, objects that are independent of the size of input data \\(n\\).

Note that memory occupied by initializing variables or calling functions in a loop, which is released upon entering the next cycle, does not accumulate over space, thus the space complexity remains \\(O(1)\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig space_complexity.py
def function() -> int:\n    \"\"\"\u51fd\u6570\"\"\"\n    # \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0\n\ndef constant(n: int):\n    \"\"\"\u5e38\u6570\u9636\"\"\"\n    # \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    a = 0\n    nums = [0] * 10000\n    node = ListNode(0)\n    # \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for _ in range(n):\n        c = 0\n    # \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for _ in range(n):\n        function()\n
space_complexity.cpp
/* \u51fd\u6570 */\nint func() {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n/* \u5e38\u6570\u9636 */\nvoid constant(int n) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    const int a = 0;\n    int b = 0;\n    vector<int> nums(10000);\n    ListNode node(0);\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        int c = 0;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        func();\n    }\n}\n
space_complexity.java
/* \u51fd\u6570 */\nint function() {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n/* \u5e38\u6570\u9636 */\nvoid constant(int n) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    final int a = 0;\n    int b = 0;\n    int[] nums = new int[10000];\n    ListNode node = new ListNode(0);\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        int c = 0;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        function();\n    }\n}\n
space_complexity.cs
/* \u51fd\u6570 */\nint Function() {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n/* \u5e38\u6570\u9636 */\nvoid Constant(int n) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    int a = 0;\n    int b = 0;\n    int[] nums = new int[10000];\n    ListNode node = new(0);\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        int c = 0;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        Function();\n    }\n}\n
space_complexity.go
/* \u51fd\u6570 */\nfunc function() int {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c...\n    return 0\n}\n\n/* \u5e38\u6570\u9636 */\nfunc spaceConstant(n int) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    const a = 0\n    b := 0\n    nums := make([]int, 10000)\n    node := newNode(0)\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    var c int\n    for i := 0; i < n; i++ {\n        c = 0\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for i := 0; i < n; i++ {\n        function()\n    }\n    b += 0\n    c += 0\n    nums[0] = 0\n    node.val = 0\n}\n
space_complexity.swift
/* \u51fd\u6570 */\n@discardableResult\nfunc function() -> Int {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0\n}\n\n/* \u5e38\u6570\u9636 */\nfunc constant(n: Int) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    let a = 0\n    var b = 0\n    let nums = Array(repeating: 0, count: 10000)\n    let node = ListNode(x: 0)\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for _ in 0 ..< n {\n        let c = 0\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for _ in 0 ..< n {\n        function()\n    }\n}\n
space_complexity.js
/* \u51fd\u6570 */\nfunction constFunc() {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n/* \u5e38\u6570\u9636 */\nfunction constant(n) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    const a = 0;\n    const b = 0;\n    const nums = new Array(10000);\n    const node = new ListNode(0);\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for (let i = 0; i < n; i++) {\n        const c = 0;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for (let i = 0; i < n; i++) {\n        constFunc();\n    }\n}\n
space_complexity.ts
/* \u51fd\u6570 */\nfunction constFunc(): number {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n/* \u5e38\u6570\u9636 */\nfunction constant(n: number): void {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    const a = 0;\n    const b = 0;\n    const nums = new Array(10000);\n    const node = new ListNode(0);\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for (let i = 0; i < n; i++) {\n        const c = 0;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for (let i = 0; i < n; i++) {\n        constFunc();\n    }\n}\n
space_complexity.dart
/* \u51fd\u6570 */\nint function() {\n  // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n  return 0;\n}\n\n/* \u5e38\u6570\u9636 */\nvoid constant(int n) {\n  // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n  final int a = 0;\n  int b = 0;\n  List<int> nums = List.filled(10000, 0);\n  ListNode node = ListNode(0);\n  // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n  for (var i = 0; i < n; i++) {\n    int c = 0;\n  }\n  // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n  for (var i = 0; i < n; i++) {\n    function();\n  }\n}\n
space_complexity.rs
/* \u51fd\u6570 */\nfn function() ->i32 {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n/* \u5e38\u6570\u9636 */\n#[allow(unused)]\nfn constant(n: i32) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    const A: i32 = 0;\n    let b = 0;\n    let nums = vec![0; 10000];\n    let node = ListNode::new(0);\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for i in 0..n {\n        let c = 0;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for i in 0..n {\n        function();\n    }\n}\n
space_complexity.c
/* \u51fd\u6570 */\nint func() {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n/* \u5e38\u6570\u9636 */\nvoid constant(int n) {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    const int a = 0;\n    int b = 0;\n    int nums[1000];\n    ListNode *node = newListNode(0);\n    free(node);\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        int c = 0;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    for (int i = 0; i < n; i++) {\n        func();\n    }\n}\n
space_complexity.zig
// \u51fd\u6570\nfn function() i32 {\n    // \u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\n    return 0;\n}\n\n// \u5e38\u6570\u9636\nfn constant(n: i32) void {\n    // \u5e38\u91cf\u3001\u53d8\u91cf\u3001\u5bf9\u8c61\u5360\u7528 O(1) \u7a7a\u95f4\n    const a: i32 = 0;\n    var b: i32 = 0;\n    var nums = [_]i32{0}**10000;\n    var node = inc.ListNode(i32){.val = 0};\n    var i: i32 = 0;\n    // \u5faa\u73af\u4e2d\u7684\u53d8\u91cf\u5360\u7528 O(1) \u7a7a\u95f4\n    while (i < n) : (i += 1) {\n        var c: i32 = 0;\n        _ = c;\n    }\n    // \u5faa\u73af\u4e2d\u7684\u51fd\u6570\u5360\u7528 O(1) \u7a7a\u95f4\n    i = 0;\n    while (i < n) : (i += 1) {\n        _ = function();\n    }\n    _ = a;\n    _ = b;\n    _ = nums;\n    _ = node;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_computational_complexity/space_complexity/#2-linear-order-on","title":"2. \u00a0 Linear Order \\(O(n)\\)","text":"

Linear order is common in arrays, linked lists, stacks, queues, etc., where the number of elements is proportional to \\(n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig space_complexity.py
def linear(n: int):\n    \"\"\"\u7ebf\u6027\u9636\"\"\"\n    # \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    nums = [0] * n\n    # \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    hmap = dict[int, str]()\n    for i in range(n):\n        hmap[i] = str(i)\n
space_complexity.cpp
/* \u7ebf\u6027\u9636 */\nvoid linear(int n) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    vector<int> nums(n);\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    vector<ListNode> nodes;\n    for (int i = 0; i < n; i++) {\n        nodes.push_back(ListNode(i));\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    unordered_map<int, string> map;\n    for (int i = 0; i < n; i++) {\n        map[i] = to_string(i);\n    }\n}\n
space_complexity.java
/* \u7ebf\u6027\u9636 */\nvoid linear(int n) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    int[] nums = new int[n];\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    List<ListNode> nodes = new ArrayList<>();\n    for (int i = 0; i < n; i++) {\n        nodes.add(new ListNode(i));\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    Map<Integer, String> map = new HashMap<>();\n    for (int i = 0; i < n; i++) {\n        map.put(i, String.valueOf(i));\n    }\n}\n
space_complexity.cs
/* \u7ebf\u6027\u9636 */\nvoid Linear(int n) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    int[] nums = new int[n];\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    List<ListNode> nodes = [];\n    for (int i = 0; i < n; i++) {\n        nodes.Add(new ListNode(i));\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    Dictionary<int, string> map = [];\n    for (int i = 0; i < n; i++) {\n        map.Add(i, i.ToString());\n    }\n}\n
space_complexity.go
/* \u7ebf\u6027\u9636 */\nfunc spaceLinear(n int) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    _ = make([]int, n)\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    var nodes []*node\n    for i := 0; i < n; i++ {\n        nodes = append(nodes, newNode(i))\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    m := make(map[int]string, n)\n    for i := 0; i < n; i++ {\n        m[i] = strconv.Itoa(i)\n    }\n}\n
space_complexity.swift
/* \u7ebf\u6027\u9636 */\nfunc linear(n: Int) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    let nums = Array(repeating: 0, count: n)\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    let nodes = (0 ..< n).map { ListNode(x: $0) }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    let map = Dictionary(uniqueKeysWithValues: (0 ..< n).map { ($0, \"\\($0)\") })\n}\n
space_complexity.js
/* \u7ebf\u6027\u9636 */\nfunction linear(n) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    const nums = new Array(n);\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    const nodes = [];\n    for (let i = 0; i < n; i++) {\n        nodes.push(new ListNode(i));\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    const map = new Map();\n    for (let i = 0; i < n; i++) {\n        map.set(i, i.toString());\n    }\n}\n
space_complexity.ts
/* \u7ebf\u6027\u9636 */\nfunction linear(n: number): void {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    const nums = new Array(n);\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    const nodes: ListNode[] = [];\n    for (let i = 0; i < n; i++) {\n        nodes.push(new ListNode(i));\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    const map = new Map();\n    for (let i = 0; i < n; i++) {\n        map.set(i, i.toString());\n    }\n}\n
space_complexity.dart
/* \u7ebf\u6027\u9636 */\nvoid linear(int n) {\n  // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n  List<int> nums = List.filled(n, 0);\n  // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n  List<ListNode> nodes = [];\n  for (var i = 0; i < n; i++) {\n    nodes.add(ListNode(i));\n  }\n  // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n  Map<int, String> map = HashMap();\n  for (var i = 0; i < n; i++) {\n    map.putIfAbsent(i, () => i.toString());\n  }\n}\n
space_complexity.rs
/* \u7ebf\u6027\u9636 */\n#[allow(unused)]\nfn linear(n: i32) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    let mut nums = vec![0; n as usize];\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    let mut nodes = Vec::new();\n    for i in 0..n {\n        nodes.push(ListNode::new(i))\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    let mut map = HashMap::new();\n    for i in 0..n {\n        map.insert(i, i.to_string());\n    }\n}\n
space_complexity.c
/* \u54c8\u5e0c\u8868 */\ntypedef struct {\n    int key;\n    int val;\n    UT_hash_handle hh; // \u57fa\u4e8e uthash.h \u5b9e\u73b0\n} HashTable;\n\n/* \u7ebf\u6027\u9636 */\nvoid linear(int n) {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    int *nums = malloc(sizeof(int) * n);\n    free(nums);\n\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    ListNode **nodes = malloc(sizeof(ListNode *) * n);\n    for (int i = 0; i < n; i++) {\n        nodes[i] = newListNode(i);\n    }\n    // \u5185\u5b58\u91ca\u653e\n    for (int i = 0; i < n; i++) {\n        free(nodes[i]);\n    }\n    free(nodes);\n\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    HashTable *h = NULL;\n    for (int i = 0; i < n; i++) {\n        HashTable *tmp = malloc(sizeof(HashTable));\n        tmp->key = i;\n        tmp->val = i;\n        HASH_ADD_INT(h, key, tmp);\n    }\n\n    // \u5185\u5b58\u91ca\u653e\n    HashTable *curr, *tmp;\n    HASH_ITER(hh, h, curr, tmp) {\n        HASH_DEL(h, curr);\n        free(curr);\n    }\n}\n
space_complexity.zig
// \u7ebf\u6027\u9636\nfn linear(comptime n: i32) !void {\n    // \u957f\u5ea6\u4e3a n \u7684\u6570\u7ec4\u5360\u7528 O(n) \u7a7a\u95f4\n    var nums = [_]i32{0}**n;\n    // \u957f\u5ea6\u4e3a n \u7684\u5217\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    var nodes = std.ArrayList(i32).init(std.heap.page_allocator);\n    defer nodes.deinit();\n    var i: i32 = 0;\n    while (i < n) : (i += 1) {\n        try nodes.append(i);\n    }\n    // \u957f\u5ea6\u4e3a n \u7684\u54c8\u5e0c\u8868\u5360\u7528 O(n) \u7a7a\u95f4\n    var map = std.AutoArrayHashMap(i32, []const u8).init(std.heap.page_allocator);\n    defer map.deinit();\n    var j: i32 = 0;\n    while (j < n) : (j += 1) {\n        const string = try std.fmt.allocPrint(std.heap.page_allocator, \"{d}\", .{j});\n        defer std.heap.page_allocator.free(string);\n        try map.put(i, string);\n    }\n    _ = nums;\n}\n
Visualizing Code

Full Screen >

As shown below, this function's recursive depth is \\(n\\), meaning there are \\(n\\) instances of unreturned linear_recur() function, using \\(O(n)\\) size of stack frame space:

PythonC++JavaC#GoSwiftJSTSDartRustCZig space_complexity.py
def linear_recur(n: int):\n    \"\"\"\u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\"\"\"\n    print(\"\u9012\u5f52 n =\", n)\n    if n == 1:\n        return\n    linear_recur(n - 1)\n
space_complexity.cpp
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nvoid linearRecur(int n) {\n    cout << \"\u9012\u5f52 n = \" << n << endl;\n    if (n == 1)\n        return;\n    linearRecur(n - 1);\n}\n
space_complexity.java
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nvoid linearRecur(int n) {\n    System.out.println(\"\u9012\u5f52 n = \" + n);\n    if (n == 1)\n        return;\n    linearRecur(n - 1);\n}\n
space_complexity.cs
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nvoid LinearRecur(int n) {\n    Console.WriteLine(\"\u9012\u5f52 n = \" + n);\n    if (n == 1) return;\n    LinearRecur(n - 1);\n}\n
space_complexity.go
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunc spaceLinearRecur(n int) {\n    fmt.Println(\"\u9012\u5f52 n =\", n)\n    if n == 1 {\n        return\n    }\n    spaceLinearRecur(n - 1)\n}\n
space_complexity.swift
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunc linearRecur(n: Int) {\n    print(\"\u9012\u5f52 n = \\(n)\")\n    if n == 1 {\n        return\n    }\n    linearRecur(n: n - 1)\n}\n
space_complexity.js
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction linearRecur(n) {\n    console.log(`\u9012\u5f52 n = ${n}`);\n    if (n === 1) return;\n    linearRecur(n - 1);\n}\n
space_complexity.ts
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction linearRecur(n: number): void {\n    console.log(`\u9012\u5f52 n = ${n}`);\n    if (n === 1) return;\n    linearRecur(n - 1);\n}\n
space_complexity.dart
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nvoid linearRecur(int n) {\n  print('\u9012\u5f52 n = $n');\n  if (n == 1) return;\n  linearRecur(n - 1);\n}\n
space_complexity.rs
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfn linear_recur(n: i32) {\n    println!(\"\u9012\u5f52 n = {}\", n);\n    if n == 1 {return};\n    linear_recur(n - 1);\n}\n
space_complexity.c
/* \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nvoid linearRecur(int n) {\n    printf(\"\u9012\u5f52 n = %d\\r\\n\", n);\n    if (n == 1)\n        return;\n    linearRecur(n - 1);\n}\n
space_complexity.zig
// \u7ebf\u6027\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\nfn linearRecur(comptime n: i32) void {\n    std.debug.print(\"\u9012\u5f52 n = {}\\n\", .{n});\n    if (n == 1) return;\n    linearRecur(n - 1);\n}\n
Visualizing Code

Full Screen >

Figure 2-17 \u00a0 Recursive Function Generating Linear Order Space Complexity

"},{"location":"chapter_computational_complexity/space_complexity/#3-quadratic-order-on2","title":"3. \u00a0 Quadratic Order \\(O(n^2)\\)","text":"

Quadratic order is common in matrices and graphs, where the number of elements is quadratic to \\(n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig space_complexity.py
def quadratic(n: int):\n    \"\"\"\u5e73\u65b9\u9636\"\"\"\n    # \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    num_matrix = [[0] * n for _ in range(n)]\n
space_complexity.cpp
/* \u5e73\u65b9\u9636 */\nvoid quadratic(int n) {\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    vector<vector<int>> numMatrix;\n    for (int i = 0; i < n; i++) {\n        vector<int> tmp;\n        for (int j = 0; j < n; j++) {\n            tmp.push_back(0);\n        }\n        numMatrix.push_back(tmp);\n    }\n}\n
space_complexity.java
/* \u5e73\u65b9\u9636 */\nvoid quadratic(int n) {\n    // \u77e9\u9635\u5360\u7528 O(n^2) \u7a7a\u95f4\n    int[][] numMatrix = new int[n][n];\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    List<List<Integer>> numList = new ArrayList<>();\n    for (int i = 0; i < n; i++) {\n        List<Integer> tmp = new ArrayList<>();\n        for (int j = 0; j < n; j++) {\n            tmp.add(0);\n        }\n        numList.add(tmp);\n    }\n}\n
space_complexity.cs
/* \u5e73\u65b9\u9636 */\nvoid Quadratic(int n) {\n    // \u77e9\u9635\u5360\u7528 O(n^2) \u7a7a\u95f4\n    int[,] numMatrix = new int[n, n];\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    List<List<int>> numList = [];\n    for (int i = 0; i < n; i++) {\n        List<int> tmp = [];\n        for (int j = 0; j < n; j++) {\n            tmp.Add(0);\n        }\n        numList.Add(tmp);\n    }\n}\n
space_complexity.go
/* \u5e73\u65b9\u9636 */\nfunc spaceQuadratic(n int) {\n    // \u77e9\u9635\u5360\u7528 O(n^2) \u7a7a\u95f4\n    numMatrix := make([][]int, n)\n    for i := 0; i < n; i++ {\n        numMatrix[i] = make([]int, n)\n    }\n}\n
space_complexity.swift
/* \u5e73\u65b9\u9636 */\nfunc quadratic(n: Int) {\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    let numList = Array(repeating: Array(repeating: 0, count: n), count: n)\n}\n
space_complexity.js
/* \u5e73\u65b9\u9636 */\nfunction quadratic(n) {\n    // \u77e9\u9635\u5360\u7528 O(n^2) \u7a7a\u95f4\n    const numMatrix = Array(n)\n        .fill(null)\n        .map(() => Array(n).fill(null));\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    const numList = [];\n    for (let i = 0; i < n; i++) {\n        const tmp = [];\n        for (let j = 0; j < n; j++) {\n            tmp.push(0);\n        }\n        numList.push(tmp);\n    }\n}\n
space_complexity.ts
/* \u5e73\u65b9\u9636 */\nfunction quadratic(n: number): void {\n    // \u77e9\u9635\u5360\u7528 O(n^2) \u7a7a\u95f4\n    const numMatrix = Array(n)\n        .fill(null)\n        .map(() => Array(n).fill(null));\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    const numList = [];\n    for (let i = 0; i < n; i++) {\n        const tmp = [];\n        for (let j = 0; j < n; j++) {\n            tmp.push(0);\n        }\n        numList.push(tmp);\n    }\n}\n
space_complexity.dart
/* \u5e73\u65b9\u9636 */\nvoid quadratic(int n) {\n  // \u77e9\u9635\u5360\u7528 O(n^2) \u7a7a\u95f4\n  List<List<int>> numMatrix = List.generate(n, (_) => List.filled(n, 0));\n  // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n  List<List<int>> numList = [];\n  for (var i = 0; i < n; i++) {\n    List<int> tmp = [];\n    for (int j = 0; j < n; j++) {\n      tmp.add(0);\n    }\n    numList.add(tmp);\n  }\n}\n
space_complexity.rs
/* \u5e73\u65b9\u9636 */\n#[allow(unused)]\nfn quadratic(n: i32) {\n    // \u77e9\u9635\u5360\u7528 O(n^2) \u7a7a\u95f4\n    let num_matrix = vec![vec![0; n as usize]; n as usize];\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    let mut num_list = Vec::new();\n    for i in 0..n {\n        let mut tmp = Vec::new();\n        for j in 0..n {\n            tmp.push(0);\n        }\n        num_list.push(tmp);\n    }\n}\n
space_complexity.c
/* \u5e73\u65b9\u9636 */\nvoid quadratic(int n) {\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    int **numMatrix = malloc(sizeof(int *) * n);\n    for (int i = 0; i < n; i++) {\n        int *tmp = malloc(sizeof(int) * n);\n        for (int j = 0; j < n; j++) {\n            tmp[j] = 0;\n        }\n        numMatrix[i] = tmp;\n    }\n\n    // \u5185\u5b58\u91ca\u653e\n    for (int i = 0; i < n; i++) {\n        free(numMatrix[i]);\n    }\n    free(numMatrix);\n}\n
space_complexity.zig
// \u5e73\u65b9\u9636\nfn quadratic(n: i32) !void {\n    // \u4e8c\u7ef4\u5217\u8868\u5360\u7528 O(n^2) \u7a7a\u95f4\n    var nodes = std.ArrayList(std.ArrayList(i32)).init(std.heap.page_allocator);\n    defer nodes.deinit();\n    var i: i32 = 0;\n    while (i < n) : (i += 1) {\n        var tmp = std.ArrayList(i32).init(std.heap.page_allocator);\n        defer tmp.deinit();\n        var j: i32 = 0;\n        while (j < n) : (j += 1) {\n            try tmp.append(0);\n        }\n        try nodes.append(tmp);\n    }\n}\n
Visualizing Code

Full Screen >

As shown below, the recursive depth of this function is \\(n\\), and in each recursive call, an array is initialized with lengths \\(n\\), \\(n-1\\), \\(\\dots\\), \\(2\\), \\(1\\), averaging \\(n/2\\), thus overall occupying \\(O(n^2)\\) space:

PythonC++JavaC#GoSwiftJSTSDartRustCZig space_complexity.py
def quadratic_recur(n: int) -> int:\n    \"\"\"\u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\"\"\"\n    if n <= 0:\n        return 0\n    # \u6570\u7ec4 nums \u957f\u5ea6\u4e3a n, n-1, ..., 2, 1\n    nums = [0] * n\n    return quadratic_recur(n - 1)\n
space_complexity.cpp
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint quadraticRecur(int n) {\n    if (n <= 0)\n        return 0;\n    vector<int> nums(n);\n    cout << \"\u9012\u5f52 n = \" << n << \" \u4e2d\u7684 nums \u957f\u5ea6 = \" << nums.size() << endl;\n    return quadraticRecur(n - 1);\n}\n
space_complexity.java
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint quadraticRecur(int n) {\n    if (n <= 0)\n        return 0;\n    // \u6570\u7ec4 nums \u957f\u5ea6\u4e3a n, n-1, ..., 2, 1\n    int[] nums = new int[n];\n    System.out.println(\"\u9012\u5f52 n = \" + n + \" \u4e2d\u7684 nums \u957f\u5ea6 = \" + nums.length);\n    return quadraticRecur(n - 1);\n}\n
space_complexity.cs
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint QuadraticRecur(int n) {\n    if (n <= 0) return 0;\n    int[] nums = new int[n];\n    Console.WriteLine(\"\u9012\u5f52 n = \" + n + \" \u4e2d\u7684 nums \u957f\u5ea6 = \" + nums.Length);\n    return QuadraticRecur(n - 1);\n}\n
space_complexity.go
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunc spaceQuadraticRecur(n int) int {\n    if n <= 0 {\n        return 0\n    }\n    nums := make([]int, n)\n    fmt.Printf(\"\u9012\u5f52 n = %d \u4e2d\u7684 nums \u957f\u5ea6 = %d \\n\", n, len(nums))\n    return spaceQuadraticRecur(n - 1)\n}\n
space_complexity.swift
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\n@discardableResult\nfunc quadraticRecur(n: Int) -> Int {\n    if n <= 0 {\n        return 0\n    }\n    // \u6570\u7ec4 nums \u957f\u5ea6\u4e3a n, n-1, ..., 2, 1\n    let nums = Array(repeating: 0, count: n)\n    print(\"\u9012\u5f52 n = \\(n) \u4e2d\u7684 nums \u957f\u5ea6 = \\(nums.count)\")\n    return quadraticRecur(n: n - 1)\n}\n
space_complexity.js
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction quadraticRecur(n) {\n    if (n <= 0) return 0;\n    const nums = new Array(n);\n    console.log(`\u9012\u5f52 n = ${n} \u4e2d\u7684 nums \u957f\u5ea6 = ${nums.length}`);\n    return quadraticRecur(n - 1);\n}\n
space_complexity.ts
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction quadraticRecur(n: number): number {\n    if (n <= 0) return 0;\n    const nums = new Array(n);\n    console.log(`\u9012\u5f52 n = ${n} \u4e2d\u7684 nums \u957f\u5ea6 = ${nums.length}`);\n    return quadraticRecur(n - 1);\n}\n
space_complexity.dart
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint quadraticRecur(int n) {\n  if (n <= 0) return 0;\n  List<int> nums = List.filled(n, 0);\n  print('\u9012\u5f52 n = $n \u4e2d\u7684 nums \u957f\u5ea6 = ${nums.length}');\n  return quadraticRecur(n - 1);\n}\n
space_complexity.rs
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfn quadratic_recur(n: i32) -> i32 {\n    if n <= 0 {return 0};\n    // \u6570\u7ec4 nums \u957f\u5ea6\u4e3a n, n-1, ..., 2, 1\n    let nums = vec![0; n as usize];\n    println!(\"\u9012\u5f52 n = {} \u4e2d\u7684 nums \u957f\u5ea6 = {}\", n, nums.len());\n    return quadratic_recur(n - 1);\n}\n
space_complexity.c
/* \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint quadraticRecur(int n) {\n    if (n <= 0)\n        return 0;\n    int *nums = malloc(sizeof(int) * n);\n    printf(\"\u9012\u5f52 n = %d \u4e2d\u7684 nums \u957f\u5ea6 = %d\\r\\n\", n, n);\n    int res = quadraticRecur(n - 1);\n    free(nums);\n    return res;\n}\n
space_complexity.zig
// \u5e73\u65b9\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\nfn quadraticRecur(comptime n: i32) i32 {\n    if (n <= 0) return 0;\n    var nums = [_]i32{0}**n;\n    std.debug.print(\"\u9012\u5f52 n = {} \u4e2d\u7684 nums \u957f\u5ea6 = {}\\n\", .{n, nums.len});\n    return quadraticRecur(n - 1);\n}\n
Visualizing Code

Full Screen >

Figure 2-18 \u00a0 Recursive Function Generating Quadratic Order Space Complexity

"},{"location":"chapter_computational_complexity/space_complexity/#4-exponential-order-o2n","title":"4. \u00a0 Exponential Order \\(O(2^n)\\)","text":"

Exponential order is common in binary trees. Observe the below image, a \"full binary tree\" with \\(n\\) levels has \\(2^n - 1\\) nodes, occupying \\(O(2^n)\\) space:

PythonC++JavaC#GoSwiftJSTSDartRustCZig space_complexity.py
def build_tree(n: int) -> TreeNode | None:\n    \"\"\"\u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09\"\"\"\n    if n == 0:\n        return None\n    root = TreeNode(0)\n    root.left = build_tree(n - 1)\n    root.right = build_tree(n - 1)\n    return root\n
space_complexity.cpp
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nTreeNode *buildTree(int n) {\n    if (n == 0)\n        return nullptr;\n    TreeNode *root = new TreeNode(0);\n    root->left = buildTree(n - 1);\n    root->right = buildTree(n - 1);\n    return root;\n}\n
space_complexity.java
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nTreeNode buildTree(int n) {\n    if (n == 0)\n        return null;\n    TreeNode root = new TreeNode(0);\n    root.left = buildTree(n - 1);\n    root.right = buildTree(n - 1);\n    return root;\n}\n
space_complexity.cs
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nTreeNode? BuildTree(int n) {\n    if (n == 0) return null;\n    TreeNode root = new(0) {\n        left = BuildTree(n - 1),\n        right = BuildTree(n - 1)\n    };\n    return root;\n}\n
space_complexity.go
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nfunc buildTree(n int) *TreeNode {\n    if n == 0 {\n        return nil\n    }\n    root := NewTreeNode(0)\n    root.Left = buildTree(n - 1)\n    root.Right = buildTree(n - 1)\n    return root\n}\n
space_complexity.swift
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nfunc buildTree(n: Int) -> TreeNode? {\n    if n == 0 {\n        return nil\n    }\n    let root = TreeNode(x: 0)\n    root.left = buildTree(n: n - 1)\n    root.right = buildTree(n: n - 1)\n    return root\n}\n
space_complexity.js
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nfunction buildTree(n) {\n    if (n === 0) return null;\n    const root = new TreeNode(0);\n    root.left = buildTree(n - 1);\n    root.right = buildTree(n - 1);\n    return root;\n}\n
space_complexity.ts
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nfunction buildTree(n: number): TreeNode | null {\n    if (n === 0) return null;\n    const root = new TreeNode(0);\n    root.left = buildTree(n - 1);\n    root.right = buildTree(n - 1);\n    return root;\n}\n
space_complexity.dart
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nTreeNode? buildTree(int n) {\n  if (n == 0) return null;\n  TreeNode root = TreeNode(0);\n  root.left = buildTree(n - 1);\n  root.right = buildTree(n - 1);\n  return root;\n}\n
space_complexity.rs
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nfn build_tree(n: i32) -> Option<Rc<RefCell<TreeNode>>> {\n    if n == 0 {return None};\n    let root = TreeNode::new(0);\n    root.borrow_mut().left = build_tree(n - 1);\n    root.borrow_mut().right = build_tree(n - 1);\n    return Some(root);\n}\n
space_complexity.c
/* \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09 */\nTreeNode *buildTree(int n) {\n    if (n == 0)\n        return NULL;\n    TreeNode *root = newTreeNode(0);\n    root->left = buildTree(n - 1);\n    root->right = buildTree(n - 1);\n    return root;\n}\n
space_complexity.zig
// \u6307\u6570\u9636\uff08\u5efa\u7acb\u6ee1\u4e8c\u53c9\u6811\uff09\nfn buildTree(mem_allocator: std.mem.Allocator, n: i32) !?*inc.TreeNode(i32) {\n    if (n == 0) return null;\n    const root = try mem_allocator.create(inc.TreeNode(i32));\n    root.init(0);\n    root.left = try buildTree(mem_allocator, n - 1);\n    root.right = try buildTree(mem_allocator, n - 1);\n    return root;\n}\n
Visualizing Code

Full Screen >

Figure 2-19 \u00a0 Full Binary Tree Generating Exponential Order Space Complexity

"},{"location":"chapter_computational_complexity/space_complexity/#5-logarithmic-order-olog-n","title":"5. \u00a0 Logarithmic Order \\(O(\\log n)\\)","text":"

Logarithmic order is common in divide-and-conquer algorithms. For example, in merge sort, an array of length \\(n\\) is recursively divided in half each round, forming a recursion tree of height \\(\\log n\\), using \\(O(\\log n)\\) stack frame space.

Another example is converting a number to a string. Given a positive integer \\(n\\), its number of digits is \\(\\log_{10} n + 1\\), corresponding to the length of the string, thus the space complexity is \\(O(\\log_{10} n + 1) = O(\\log n)\\).

"},{"location":"chapter_computational_complexity/space_complexity/#244-balancing-time-and-space","title":"2.4.4 \u00a0 Balancing Time and Space","text":"

Ideally, we aim for both time complexity and space complexity to be optimal. However, in practice, optimizing both simultaneously is often difficult.

Lowering time complexity usually comes at the cost of increased space complexity, and vice versa. The approach of sacrificing memory space to improve algorithm speed is known as \"space-time tradeoff\"; the reverse is known as \"time-space tradeoff\".

The choice depends on which aspect we value more. In most cases, time is more precious than space, so \"space-time tradeoff\" is often the more common strategy. Of course, controlling space complexity is also very important when dealing with large volumes of data.

"},{"location":"chapter_computational_complexity/summary/","title":"2.5 \u00a0 Summary","text":""},{"location":"chapter_computational_complexity/summary/#1-key-review","title":"1. \u00a0 Key Review","text":"

Algorithm Efficiency Assessment

  • Time efficiency and space efficiency are the two main criteria for assessing the merits of an algorithm.
  • We can assess algorithm efficiency through actual testing, but it's challenging to eliminate the influence of the test environment, and it consumes substantial computational resources.
  • Complexity analysis can overcome the disadvantages of actual testing. Its results are applicable across all operating platforms and can reveal the efficiency of algorithms at different data scales.

Time Complexity

  • Time complexity measures the trend of an algorithm's running time with the increase in data volume, effectively assessing algorithm efficiency. However, it can fail in certain cases, such as with small input data volumes or when time complexities are the same, making it challenging to precisely compare the efficiency of algorithms.
  • Worst-case time complexity is denoted using big O notation, representing the asymptotic upper bound, reflecting the growth level of the number of operations \\(T(n)\\) as \\(n\\) approaches infinity.
  • Calculating time complexity involves two steps: first counting the number of operations, then determining the asymptotic upper bound.
  • Common time complexities, arranged from low to high, include \\(O(1)\\), \\(O(\\log n)\\), \\(O(n)\\), \\(O(n \\log n)\\), \\(O(n^2)\\), \\(O(2^n)\\), and \\(O(n!)\\), among others.
  • The time complexity of some algorithms is not fixed and depends on the distribution of input data. Time complexities are divided into worst, best, and average cases. The best case is rarely used because input data generally needs to meet strict conditions to achieve the best case.
  • Average time complexity reflects the efficiency of an algorithm under random data inputs, closely resembling the algorithm's performance in actual applications. Calculating average time complexity requires accounting for the distribution of input data and the subsequent mathematical expectation.

Space Complexity

  • Space complexity, similar to time complexity, measures the trend of memory space occupied by an algorithm with the increase in data volume.
  • The relevant memory space used during the algorithm's execution can be divided into input space, temporary space, and output space. Generally, input space is not included in space complexity calculations. Temporary space can be divided into temporary data, stack frame space, and instruction space, where stack frame space usually affects space complexity only in recursive functions.
  • We usually focus only on the worst-case space complexity, which means calculating the space complexity of the algorithm under the worst input data and at the worst moment of operation.
  • Common space complexities, arranged from low to high, include \\(O(1)\\), \\(O(\\log n)\\), \\(O(n)\\), \\(O(n^2)\\), and \\(O(2^n)\\), among others.
"},{"location":"chapter_computational_complexity/summary/#2-q-a","title":"2. \u00a0 Q & A","text":"

Q: Is the space complexity of tail recursion \\(O(1)\\)?

Theoretically, the space complexity of a tail-recursive function can be optimized to \\(O(1)\\). However, most programming languages (such as Java, Python, C++, Go, C#) do not support automatic optimization of tail recursion, so it's generally considered to have a space complexity of \\(O(n)\\).

Q: What is the difference between the terms \"function\" and \"method\"?

A \"function\" can be executed independently, with all parameters passed explicitly. A \"method\" is associated with an object and is implicitly passed to the object calling it, able to operate on the data contained within an instance of a class.

Here are some examples from common programming languages:

  • C is a procedural programming language without object-oriented concepts, so it only has functions. However, we can simulate object-oriented programming by creating structures (struct), and functions associated with these structures are equivalent to methods in other programming languages.
  • Java and C# are object-oriented programming languages where code blocks (methods) are typically part of a class. Static methods behave like functions because they are bound to the class and cannot access specific instance variables.
  • C++ and Python support both procedural programming (functions) and object-oriented programming (methods).

Q: Does the \"Common Types of Space Complexity\" figure reflect the absolute size of occupied space?

No, the figure shows space complexities, which reflect growth trends, not the absolute size of the occupied space.

If you take \\(n = 8\\), you might find that the values of each curve don't correspond to their functions. This is because each curve includes a constant term, intended to compress the value range into a visually comfortable range.

In practice, since we usually don't know the \"constant term\" complexity of each method, it's generally not possible to choose the best solution for \\(n = 8\\) based solely on complexity. However, for \\(n = 8^5\\), it's much easier to choose, as the growth trend becomes dominant.

"},{"location":"chapter_computational_complexity/time_complexity/","title":"2.3 \u00a0 Time Complexity","text":"

Time complexity is a concept used to measure how the run time of an algorithm increases with the size of the input data. Understanding time complexity is crucial for accurately assessing the efficiency of an algorithm.

  1. Determining the Running Platform: This includes hardware configuration, programming language, system environment, etc., all of which can affect the efficiency of code execution.
  2. Evaluating the Run Time for Various Computational Operations: For instance, an addition operation + might take 1 ns, a multiplication operation * might take 10 ns, a print operation print() might take 5 ns, etc.
  3. Counting All the Computational Operations in the Code: Summing the execution times of all these operations gives the total run time.

For example, consider the following code with an input size of \\(n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig
# Under an operating platform\ndef algorithm(n: int):\n    a = 2      # 1 ns\n    a = a + 1  # 1 ns\n    a = a * 2  # 10 ns\n    # Cycle n times\n    for _ in range(n):  # 1 ns\n        print(0)        # 5 ns\n
// Under a particular operating platform\nvoid algorithm(int n) {\n    int a = 2;  // 1 ns\n    a = a + 1;  // 1 ns\n    a = a * 2;  // 10 ns\n    // Loop n times\n    for (int i = 0; i < n; i++) {  // 1 ns , every round i++ is executed\n        cout << 0 << endl;         // 5 ns\n    }\n}\n
// Under a particular operating platform\nvoid algorithm(int n) {\n    int a = 2;  // 1 ns\n    a = a + 1;  // 1 ns\n    a = a * 2;  // 10 ns\n    // Loop n times\n    for (int i = 0; i < n; i++) {  // 1 ns , every round i++ is executed\n        System.out.println(0);     // 5 ns\n    }\n}\n
// Under a particular operating platform\nvoid Algorithm(int n) {\n    int a = 2;  // 1 ns\n    a = a + 1;  // 1 ns\n    a = a * 2;  // 10 ns\n    // Loop n times\n    for (int i = 0; i < n; i++) {  // 1 ns , every round i++ is executed\n        Console.WriteLine(0);      // 5 ns\n    }\n}\n
// Under a particular operating platform\nfunc algorithm(n int) {\n    a := 2     // 1 ns\n    a = a + 1  // 1 ns\n    a = a * 2  // 10 ns\n    // Loop n times\n    for i := 0; i < n; i++ {  // 1 ns\n        fmt.Println(a)        // 5 ns\n    }\n}\n
// Under a particular operating platform\nfunc algorithm(n: Int) {\n    var a = 2 // 1 ns\n    a = a + 1 // 1 ns\n    a = a * 2 // 10 ns\n    // Loop n times\n    for _ in 0 ..< n { // 1 ns\n        print(0) // 5 ns\n    }\n}\n
// Under a particular operating platform\nfunction algorithm(n) {\n    var a = 2; // 1 ns\n    a = a + 1; // 1 ns\n    a = a * 2; // 10 ns\n    // Loop n times\n    for(let i = 0; i < n; i++) { // 1 ns , every round i++ is executed\n        console.log(0); // 5 ns\n    }\n}\n
// Under a particular operating platform\nfunction algorithm(n: number): void {\n    var a: number = 2; // 1 ns\n    a = a + 1; // 1 ns\n    a = a * 2; // 10 ns\n    // Loop n times\n    for(let i = 0; i < n; i++) { // 1 ns , every round i++ is executed\n        console.log(0); // 5 ns\n    }\n}\n
// Under a particular operating platform\nvoid algorithm(int n) {\n  int a = 2; // 1 ns\n  a = a + 1; // 1 ns\n  a = a * 2; // 10 ns\n  // Loop n times\n  for (int i = 0; i < n; i++) { // 1 ns , every round i++ is executed\n    print(0); // 5 ns\n  }\n}\n
// Under a particular operating platform\nfn algorithm(n: i32) {\n    let mut a = 2;      // 1 ns\n    a = a + 1;          // 1 ns\n    a = a * 2;          // 10 ns\n    // Loop n times\n    for _ in 0..n {     // 1 ns for each round i++\n        println!(\"{}\", 0);  // 5 ns\n    }\n}\n
// Under a particular operating platform\nvoid algorithm(int n) {\n    int a = 2;  // 1 ns\n    a = a + 1;  // 1 ns\n    a = a * 2;  // 10 ns\n    // Loop n times\n    for (int i = 0; i < n; i++) {   // 1 ns , every round i++ is executed\n        printf(\"%d\", 0);            // 5 ns\n    }\n}\n
// Under a particular operating platform\nfn algorithm(n: usize) void {\n    var a: i32 = 2; // 1 ns\n    a += 1; // 1 ns\n    a *= 2; // 10 ns\n    // Loop n times\n    for (0..n) |_| { // 1 ns\n        std.debug.print(\"{}\\n\", .{0}); // 5 ns\n    }\n}\n

Using the above method, the run time of the algorithm can be calculated as \\((6n + 12)\\) ns:

\\[ 1 + 1 + 10 + (1 + 5) \\times n = 6n + 12 \\]

However, in practice, counting the run time of an algorithm is neither practical nor reasonable. First, we don't want to tie the estimated time to the running platform, as algorithms need to run on various platforms. Second, it's challenging to know the run time for each type of operation, making the estimation process difficult.

"},{"location":"chapter_computational_complexity/time_complexity/#231-assessing-time-growth-trend","title":"2.3.1 \u00a0 Assessing Time Growth Trend","text":"

Time complexity analysis does not count the algorithm's run time, but rather the growth trend of the run time as the data volume increases.

Let's understand this concept of \"time growth trend\" with an example. Assume the input data size is \\(n\\), and consider three algorithms A, B, and C:

PythonC++JavaC#GoSwiftJSTSDartRustCZig
# Time complexity of algorithm A: constant order\ndef algorithm_A(n: int):\n    print(0)\n# Time complexity of algorithm B: linear order\ndef algorithm_B(n: int):\n    for _ in range(n):\n        print(0)\n# Time complexity of algorithm C: constant order\ndef algorithm_C(n: int):\n    for _ in range(1000000):\n        print(0)\n
// Time complexity of algorithm A: constant order\nvoid algorithm_A(int n) {\n    cout << 0 << endl;\n}\n// Time complexity of algorithm B: linear order\nvoid algorithm_B(int n) {\n    for (int i = 0; i < n; i++) {\n        cout << 0 << endl;\n    }\n}\n// Time complexity of algorithm C: constant order\nvoid algorithm_C(int n) {\n    for (int i = 0; i < 1000000; i++) {\n        cout << 0 << endl;\n    }\n}\n
// Time complexity of algorithm A: constant order\nvoid algorithm_A(int n) {\n    System.out.println(0);\n}\n// Time complexity of algorithm B: linear order\nvoid algorithm_B(int n) {\n    for (int i = 0; i < n; i++) {\n        System.out.println(0);\n    }\n}\n// Time complexity of algorithm C: constant order\nvoid algorithm_C(int n) {\n    for (int i = 0; i < 1000000; i++) {\n        System.out.println(0);\n    }\n}\n
// Time complexity of algorithm A: constant order\nvoid AlgorithmA(int n) {\n    Console.WriteLine(0);\n}\n// Time complexity of algorithm B: linear order\nvoid AlgorithmB(int n) {\n    for (int i = 0; i < n; i++) {\n        Console.WriteLine(0);\n    }\n}\n// Time complexity of algorithm C: constant order\nvoid AlgorithmC(int n) {\n    for (int i = 0; i < 1000000; i++) {\n        Console.WriteLine(0);\n    }\n}\n
// Time complexity of algorithm A: constant order\nfunc algorithm_A(n int) {\n    fmt.Println(0)\n}\n// Time complexity of algorithm B: linear order\nfunc algorithm_B(n int) {\n    for i := 0; i < n; i++ {\n        fmt.Println(0)\n    }\n}\n// Time complexity of algorithm C: constant order\nfunc algorithm_C(n int) {\n    for i := 0; i < 1000000; i++ {\n        fmt.Println(0)\n    }\n}\n
// Time complexity of algorithm A: constant order\nfunc algorithmA(n: Int) {\n    print(0)\n}\n\n// Time complexity of algorithm B: linear order\nfunc algorithmB(n: Int) {\n    for _ in 0 ..< n {\n        print(0)\n    }\n}\n\n// Time complexity of algorithm C: constant order\nfunc algorithmC(n: Int) {\n    for _ in 0 ..< 1000000 {\n        print(0)\n    }\n}\n
// Time complexity of algorithm A: constant order\nfunction algorithm_A(n) {\n    console.log(0);\n}\n// Time complexity of algorithm B: linear order\nfunction algorithm_B(n) {\n    for (let i = 0; i < n; i++) {\n        console.log(0);\n    }\n}\n// Time complexity of algorithm C: constant order\nfunction algorithm_C(n) {\n    for (let i = 0; i < 1000000; i++) {\n        console.log(0);\n    }\n}\n
// Time complexity of algorithm A: constant order\nfunction algorithm_A(n: number): void {\n    console.log(0);\n}\n// Time complexity of algorithm B: linear order\nfunction algorithm_B(n: number): void {\n    for (let i = 0; i < n; i++) {\n        console.log(0);\n    }\n}\n// Time complexity of algorithm C: constant order\nfunction algorithm_C(n: number): void {\n    for (let i = 0; i < 1000000; i++) {\n        console.log(0);\n    }\n}\n
// Time complexity of algorithm A: constant order\nvoid algorithmA(int n) {\n  print(0);\n}\n// Time complexity of algorithm B: linear order\nvoid algorithmB(int n) {\n  for (int i = 0; i < n; i++) {\n    print(0);\n  }\n}\n// Time complexity of algorithm C: constant order\nvoid algorithmC(int n) {\n  for (int i = 0; i < 1000000; i++) {\n    print(0);\n  }\n}\n
// Time complexity of algorithm A: constant order\nfn algorithm_A(n: i32) {\n    println!(\"{}\", 0);\n}\n// Time complexity of algorithm B: linear order\nfn algorithm_B(n: i32) {\n    for _ in 0..n {\n        println!(\"{}\", 0);\n    }\n}\n// Time complexity of algorithm C: constant order\nfn algorithm_C(n: i32) {\n    for _ in 0..1000000 {\n        println!(\"{}\", 0);\n    }\n}\n
// Time complexity of algorithm A: constant order\nvoid algorithm_A(int n) {\n    printf(\"%d\", 0);\n}\n// Time complexity of algorithm B: linear order\nvoid algorithm_B(int n) {\n    for (int i = 0; i < n; i++) {\n        printf(\"%d\", 0);\n    }\n}\n// Time complexity of algorithm C: constant order\nvoid algorithm_C(int n) {\n    for (int i = 0; i < 1000000; i++) {\n        printf(\"%d\", 0);\n    }\n}\n
// Time complexity of algorithm A: constant order\nfn algorithm_A(n: usize) void {\n    _ = n;\n    std.debug.print(\"{}\\n\", .{0});\n}\n// Time complexity of algorithm B: linear order\nfn algorithm_B(n: i32) void {\n    for (0..n) |_| {\n        std.debug.print(\"{}\\n\", .{0});\n    }\n}\n// Time complexity of algorithm C: constant order\nfn algorithm_C(n: i32) void {\n    _ = n;\n    for (0..1000000) |_| {\n        std.debug.print(\"{}\\n\", .{0});\n    }\n}\n

The following figure shows the time complexities of these three algorithms.

  • Algorithm A has just one print operation, and its run time does not grow with \\(n\\). Its time complexity is considered \"constant order.\"
  • Algorithm B involves a print operation looping \\(n\\) times, and its run time grows linearly with \\(n\\). Its time complexity is \"linear order.\"
  • Algorithm C has a print operation looping 1,000,000 times. Although it takes a long time, it is independent of the input data size \\(n\\). Therefore, the time complexity of C is the same as A, which is \"constant order.\"

Figure 2-7 \u00a0 Time Growth Trend of Algorithms A, B, and C

Compared to directly counting the run time of an algorithm, what are the characteristics of time complexity analysis?

  • Time complexity effectively assesses algorithm efficiency. For instance, algorithm B has linearly growing run time, which is slower than algorithm A when \\(n > 1\\) and slower than C when \\(n > 1,000,000\\). In fact, as long as the input data size \\(n\\) is sufficiently large, a \"constant order\" complexity algorithm will always be better than a \"linear order\" one, demonstrating the essence of time growth trend.
  • Time complexity analysis is more straightforward. Obviously, the running platform and the types of computational operations are irrelevant to the trend of run time growth. Therefore, in time complexity analysis, we can simply treat the execution time of all computational operations as the same \"unit time,\" simplifying the \"computational operation run time count\" to a \"computational operation count.\" This significantly reduces the complexity of estimation.
  • Time complexity has its limitations. For example, although algorithms A and C have the same time complexity, their actual run times can be quite different. Similarly, even though algorithm B has a higher time complexity than C, it is clearly superior when the input data size \\(n\\) is small. In these cases, it's difficult to judge the efficiency of algorithms based solely on time complexity. Nonetheless, despite these issues, complexity analysis remains the most effective and commonly used method for evaluating algorithm efficiency.
"},{"location":"chapter_computational_complexity/time_complexity/#232-asymptotic-upper-bound","title":"2.3.2 \u00a0 Asymptotic Upper Bound","text":"

Consider a function with an input size of \\(n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig
def algorithm(n: int):\n    a = 1      # +1\n    a = a + 1  # +1\n    a = a * 2  # +1\n    # Cycle n times\n    for i in range(n):  # +1\n        print(0)        # +1\n
void algorithm(int n) {\n    int a = 1;  // +1\n    a = a + 1;  // +1\n    a = a * 2;  // +1\n    // Loop n times\n    for (int i = 0; i < n; i++) { // +1 (execute i ++ every round)\n        cout << 0 << endl;    // +1\n    }\n}\n
void algorithm(int n) {\n    int a = 1;  // +1\n    a = a + 1;  // +1\n    a = a * 2;  // +1\n    // Loop n times\n    for (int i = 0; i < n; i++) { // +1 (execute i ++ every round)\n        System.out.println(0);    // +1\n    }\n}\n
void Algorithm(int n) {\n    int a = 1;  // +1\n    a = a + 1;  // +1\n    a = a * 2;  // +1\n    // Loop n times\n    for (int i = 0; i < n; i++) {   // +1 (execute i ++ every round)\n        Console.WriteLine(0);   // +1\n    }\n}\n
func algorithm(n int) {\n    a := 1      // +1\n    a = a + 1   // +1\n    a = a * 2   // +1\n    // Loop n times\n    for i := 0; i < n; i++ {   // +1\n        fmt.Println(a)         // +1\n    }\n}\n
func algorithm(n: Int) {\n    var a = 1 // +1\n    a = a + 1 // +1\n    a = a * 2 // +1\n    // Loop n times\n    for _ in 0 ..< n { // +1\n        print(0) // +1\n    }\n}\n
function algorithm(n) {\n    var a = 1; // +1\n    a += 1; // +1\n    a *= 2; // +1\n    // Loop n times\n    for(let i = 0; i < n; i++){ // +1 (execute i ++ every round)\n        console.log(0); // +1\n    }\n}\n
function algorithm(n: number): void{\n    var a: number = 1; // +1\n    a += 1; // +1\n    a *= 2; // +1\n    // Loop n times\n    for(let i = 0; i < n; i++){ // +1 (execute i ++ every round)\n        console.log(0); // +1\n    }\n}\n
void algorithm(int n) {\n  int a = 1; // +1\n  a = a + 1; // +1\n  a = a * 2; // +1\n  // Loop n times\n  for (int i = 0; i < n; i++) { // +1 (execute i ++ every round)\n    print(0); // +1\n  }\n}\n
fn algorithm(n: i32) {\n    let mut a = 1;   // +1\n    a = a + 1;      // +1\n    a = a * 2;      // +1\n\n    // Loop n times\n    for _ in 0..n { // +1 (execute i ++ every round)\n        println!(\"{}\", 0); // +1\n    }\n}\n
void algorithm(int n) {\n    int a = 1;  // +1\n    a = a + 1;  // +1\n    a = a * 2;  // +1\n    // Loop n times\n    for (int i = 0; i < n; i++) {   // +1 (execute i ++ every round)\n        printf(\"%d\", 0);            // +1\n    }\n} \n
fn algorithm(n: usize) void {\n    var a: i32 = 1; // +1\n    a += 1; // +1\n    a *= 2; // +1\n    // Loop n times\n    for (0..n) |_| { // +1 (execute i ++ every round)\n        std.debug.print(\"{}\\n\", .{0}); // +1\n    }\n}\n

Given a function that represents the number of operations of an algorithm as a function of the input size \\(n\\), denoted as \\(T(n)\\), consider the following example:

\\[ T(n) = 3 + 2n \\]

Since \\(T(n)\\) is a linear function, its growth trend is linear, and therefore, its time complexity is of linear order, denoted as \\(O(n)\\). This mathematical notation, known as \"big-O notation,\" represents the \"asymptotic upper bound\" of the function \\(T(n)\\).

In essence, time complexity analysis is about finding the asymptotic upper bound of the \"number of operations \\(T(n)\\)\". It has a precise mathematical definition.

Asymptotic Upper Bound

If there exist positive real numbers \\(c\\) and \\(n_0\\) such that for all \\(n > n_0\\), \\(T(n) \\leq c \\cdot f(n)\\), then \\(f(n)\\) is considered an asymptotic upper bound of \\(T(n)\\), denoted as \\(T(n) = O(f(n))\\).

As illustrated below, calculating the asymptotic upper bound involves finding a function \\(f(n)\\) such that, as \\(n\\) approaches infinity, \\(T(n)\\) and \\(f(n)\\) have the same growth order, differing only by a constant factor \\(c\\).

Figure 2-8 \u00a0 Asymptotic Upper Bound of a Function

"},{"location":"chapter_computational_complexity/time_complexity/#233-calculation-method","title":"2.3.3 \u00a0 Calculation Method","text":"

While the concept of asymptotic upper bound might seem mathematically dense, you don't need to fully grasp it right away. Let's first understand the method of calculation, which can be practiced and comprehended over time.

Once \\(f(n)\\) is determined, we obtain the time complexity \\(O(f(n))\\). But how do we determine the asymptotic upper bound \\(f(n)\\)? This process generally involves two steps: counting the number of operations and determining the asymptotic upper bound.

"},{"location":"chapter_computational_complexity/time_complexity/#1-step-1-counting-the-number-of-operations","title":"1. \u00a0 Step 1: Counting the Number of Operations","text":"

This step involves going through the code line by line. However, due to the presence of the constant \\(c\\) in \\(c \\cdot f(n)\\), all coefficients and constant terms in \\(T(n)\\) can be ignored. This principle allows for simplification techniques in counting operations.

  1. Ignore constant terms in \\(T(n)\\), as they do not affect the time complexity being independent of \\(n\\).
  2. Omit all coefficients. For example, looping \\(2n\\), \\(5n + 1\\) times, etc., can be simplified to \\(n\\) times since the coefficient before \\(n\\) does not impact the time complexity.
  3. Use multiplication for nested loops. The total number of operations equals the product of the number of operations in each loop, applying the simplification techniques from points 1 and 2 for each loop level.

Given a function, we can use these techniques to count operations:

PythonC++JavaC#GoSwiftJSTSDartRustCZig
def algorithm(n: int):\n    a = 1      # +0 (trick 1)\n    a = a + n  # +0 (trick 1)\n    # +n (technique 2)\n    for i in range(5 * n + 1):\n        print(0)\n    # +n*n (technique 3)\n    for i in range(2 * n):\n        for j in range(n + 1):\n            print(0)\n
void algorithm(int n) {\n    int a = 1;  // +0 (trick 1)\n    a = a + n;  // +0 (trick 1)\n    // +n (technique 2)\n    for (int i = 0; i < 5 * n + 1; i++) {\n        cout << 0 << endl;\n    }\n    // +n*n (technique 3)\n    for (int i = 0; i < 2 * n; i++) {\n        for (int j = 0; j < n + 1; j++) {\n            cout << 0 << endl;\n        }\n    }\n}\n
void algorithm(int n) {\n    int a = 1;  // +0 (trick 1)\n    a = a + n;  // +0 (trick 1)\n    // +n (technique 2)\n    for (int i = 0; i < 5 * n + 1; i++) {\n        System.out.println(0);\n    }\n    // +n*n (technique 3)\n    for (int i = 0; i < 2 * n; i++) {\n        for (int j = 0; j < n + 1; j++) {\n            System.out.println(0);\n        }\n    }\n}\n
void Algorithm(int n) {\n    int a = 1;  // +0 (trick 1)\n    a = a + n;  // +0 (trick 1)\n    // +n (technique 2)\n    for (int i = 0; i < 5 * n + 1; i++) {\n        Console.WriteLine(0);\n    }\n    // +n*n (technique 3)\n    for (int i = 0; i < 2 * n; i++) {\n        for (int j = 0; j < n + 1; j++) {\n            Console.WriteLine(0);\n        }\n    }\n}\n
func algorithm(n int) {\n    a := 1     // +0 (trick 1)\n    a = a + n  // +0 (trick 1)\n    // +n (technique 2)\n    for i := 0; i < 5 * n + 1; i++ {\n        fmt.Println(0)\n    }\n    // +n*n (technique 3)\n    for i := 0; i < 2 * n; i++ {\n        for j := 0; j < n + 1; j++ {\n            fmt.Println(0)\n        }\n    }\n}\n
func algorithm(n: Int) {\n    var a = 1 // +0 (trick 1)\n    a = a + n // +0 (trick 1)\n    // +n (technique 2)\n    for _ in 0 ..< (5 * n + 1) {\n        print(0)\n    }\n    // +n*n (technique 3)\n    for _ in 0 ..< (2 * n) {\n        for _ in 0 ..< (n + 1) {\n            print(0)\n        }\n    }\n}\n
function algorithm(n) {\n    let a = 1;  // +0 (trick 1)\n    a = a + n;  // +0 (trick 1)\n    // +n (technique 2)\n    for (let i = 0; i < 5 * n + 1; i++) {\n        console.log(0);\n    }\n    // +n*n (technique 3)\n    for (let i = 0; i < 2 * n; i++) {\n        for (let j = 0; j < n + 1; j++) {\n            console.log(0);\n        }\n    }\n}\n
function algorithm(n: number): void {\n    let a = 1;  // +0 (trick 1)\n    a = a + n;  // +0 (trick 1)\n    // +n (technique 2)\n    for (let i = 0; i < 5 * n + 1; i++) {\n        console.log(0);\n    }\n    // +n*n (technique 3)\n    for (let i = 0; i < 2 * n; i++) {\n        for (let j = 0; j < n + 1; j++) {\n            console.log(0);\n        }\n    }\n}\n
void algorithm(int n) {\n  int a = 1; // +0 (trick 1)\n  a = a + n; // +0 (trick 1)\n  // +n (technique 2)\n  for (int i = 0; i < 5 * n + 1; i++) {\n    print(0);\n  }\n  // +n*n (technique 3)\n  for (int i = 0; i < 2 * n; i++) {\n    for (int j = 0; j < n + 1; j++) {\n      print(0);\n    }\n  }\n}\n
fn algorithm(n: i32) {\n    let mut a = 1;     // +0 (trick 1)\n    a = a + n;        // +0 (trick 1)\n\n    // +n (technique 2)\n    for i in 0..(5 * n + 1) {\n        println!(\"{}\", 0);\n    }\n\n    // +n*n (technique 3)\n    for i in 0..(2 * n) {\n        for j in 0..(n + 1) {\n            println!(\"{}\", 0);\n        }\n    }\n}\n
void algorithm(int n) {\n    int a = 1;  // +0 (trick 1)\n    a = a + n;  // +0 (trick 1)\n    // +n (technique 2)\n    for (int i = 0; i < 5 * n + 1; i++) {\n        printf(\"%d\", 0);\n    }\n    // +n*n (technique 3)\n    for (int i = 0; i < 2 * n; i++) {\n        for (int j = 0; j < n + 1; j++) {\n            printf(\"%d\", 0);\n        }\n    }\n}\n
fn algorithm(n: usize) void {\n    var a: i32 = 1;     // +0 (trick 1)\n    a = a + @as(i32, @intCast(n));        // +0 (trick 1)\n\n    // +n (technique 2)\n    for(0..(5 * n + 1)) |_| {\n        std.debug.print(\"{}\\n\", .{0});\n    }\n\n    // +n*n (technique 3)\n    for(0..(2 * n)) |_| {\n        for(0..(n + 1)) |_| {\n            std.debug.print(\"{}\\n\", .{0});\n        }\n    }\n}\n

The formula below shows the counting results before and after simplification, both leading to a time complexity of \\(O(n^2)\\):

\\[ \\begin{aligned} T(n) & = 2n(n + 1) + (5n + 1) + 2 & \\text{Complete Count (-.-|||)} \\newline & = 2n^2 + 7n + 3 \\newline T(n) & = n^2 + n & \\text{Simplified Count (o.O)} \\end{aligned} \\]"},{"location":"chapter_computational_complexity/time_complexity/#2-step-2-determining-the-asymptotic-upper-bound","title":"2. \u00a0 Step 2: Determining the Asymptotic Upper Bound","text":"

The time complexity is determined by the highest order term in \\(T(n)\\). This is because, as \\(n\\) approaches infinity, the highest order term dominates, rendering the influence of other terms negligible.

The following table illustrates examples of different operation counts and their corresponding time complexities. Some exaggerated values are used to emphasize that coefficients cannot alter the order of growth. When \\(n\\) becomes very large, these constants become insignificant.

Table: Time Complexity for Different Operation Counts

Operation Count \\(T(n)\\) Time Complexity \\(O(f(n))\\) \\(100000\\) \\(O(1)\\) \\(3n + 2\\) \\(O(n)\\) \\(2n^2 + 3n + 2\\) \\(O(n^2)\\) \\(n^3 + 10000n^2\\) \\(O(n^3)\\) \\(2^n + 10000n^{10000}\\) \\(O(2^n)\\)"},{"location":"chapter_computational_complexity/time_complexity/#234-common-types-of-time-complexity","title":"2.3.4 \u00a0 Common Types of Time Complexity","text":"

Let's consider the input data size as \\(n\\). The common types of time complexities are illustrated below, arranged from lowest to highest:

\\[ \\begin{aligned} O(1) < O(\\log n) < O(n) < O(n \\log n) < O(n^2) < O(2^n) < O(n!) \\newline \\text{Constant Order} < \\text{Logarithmic Order} < \\text{Linear Order} < \\text{Linear-Logarithmic Order} < \\text{Quadratic Order} < \\text{Exponential Order} < \\text{Factorial Order} \\end{aligned} \\]

Figure 2-9 \u00a0 Common Types of Time Complexity

"},{"location":"chapter_computational_complexity/time_complexity/#1-constant-order-o1","title":"1. \u00a0 Constant Order \\(O(1)\\)","text":"

Constant order means the number of operations is independent of the input data size \\(n\\). In the following function, although the number of operations size might be large, the time complexity remains \\(O(1)\\) as it's unrelated to \\(n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def constant(n: int) -> int:\n    \"\"\"\u5e38\u6570\u9636\"\"\"\n    count = 0\n    size = 100000\n    for _ in range(size):\n        count += 1\n    return count\n
time_complexity.cpp
/* \u5e38\u6570\u9636 */\nint constant(int n) {\n    int count = 0;\n    int size = 100000;\n    for (int i = 0; i < size; i++)\n        count++;\n    return count;\n}\n
time_complexity.java
/* \u5e38\u6570\u9636 */\nint constant(int n) {\n    int count = 0;\n    int size = 100000;\n    for (int i = 0; i < size; i++)\n        count++;\n    return count;\n}\n
time_complexity.cs
/* \u5e38\u6570\u9636 */\nint Constant(int n) {\n    int count = 0;\n    int size = 100000;\n    for (int i = 0; i < size; i++)\n        count++;\n    return count;\n}\n
time_complexity.go
/* \u5e38\u6570\u9636 */\nfunc constant(n int) int {\n    count := 0\n    size := 100000\n    for i := 0; i < size; i++ {\n        count++\n    }\n    return count\n}\n
time_complexity.swift
/* \u5e38\u6570\u9636 */\nfunc constant(n: Int) -> Int {\n    var count = 0\n    let size = 100_000\n    for _ in 0 ..< size {\n        count += 1\n    }\n    return count\n}\n
time_complexity.js
/* \u5e38\u6570\u9636 */\nfunction constant(n) {\n    let count = 0;\n    const size = 100000;\n    for (let i = 0; i < size; i++) count++;\n    return count;\n}\n
time_complexity.ts
/* \u5e38\u6570\u9636 */\nfunction constant(n: number): number {\n    let count = 0;\n    const size = 100000;\n    for (let i = 0; i < size; i++) count++;\n    return count;\n}\n
time_complexity.dart
/* \u5e38\u6570\u9636 */\nint constant(int n) {\n  int count = 0;\n  int size = 100000;\n  for (var i = 0; i < size; i++) {\n    count++;\n  }\n  return count;\n}\n
time_complexity.rs
/* \u5e38\u6570\u9636 */\nfn constant(n: i32) -> i32 {\n    _ = n;\n    let mut count = 0;\n    let size = 100_000;\n    for _ in 0..size {\n        count += 1;\n    }\n    count\n}\n
time_complexity.c
/* \u5e38\u6570\u9636 */\nint constant(int n) {\n    int count = 0;\n    int size = 100000;\n    int i = 0;\n    for (int i = 0; i < size; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.zig
// \u5e38\u6570\u9636\nfn constant(n: i32) i32 {\n    _ = n;\n    var count: i32 = 0;\n    const size: i32 = 100_000;\n    var i: i32 = 0;\n    while(i<size) : (i += 1) {\n        count += 1;\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_computational_complexity/time_complexity/#2-linear-order-on","title":"2. \u00a0 Linear Order \\(O(n)\\)","text":"

Linear order indicates the number of operations grows linearly with the input data size \\(n\\). Linear order commonly appears in single-loop structures:

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def linear(n: int) -> int:\n    \"\"\"\u7ebf\u6027\u9636\"\"\"\n    count = 0\n    for _ in range(n):\n        count += 1\n    return count\n
time_complexity.cpp
/* \u7ebf\u6027\u9636 */\nint linear(int n) {\n    int count = 0;\n    for (int i = 0; i < n; i++)\n        count++;\n    return count;\n}\n
time_complexity.java
/* \u7ebf\u6027\u9636 */\nint linear(int n) {\n    int count = 0;\n    for (int i = 0; i < n; i++)\n        count++;\n    return count;\n}\n
time_complexity.cs
/* \u7ebf\u6027\u9636 */\nint Linear(int n) {\n    int count = 0;\n    for (int i = 0; i < n; i++)\n        count++;\n    return count;\n}\n
time_complexity.go
/* \u7ebf\u6027\u9636 */\nfunc linear(n int) int {\n    count := 0\n    for i := 0; i < n; i++ {\n        count++\n    }\n    return count\n}\n
time_complexity.swift
/* \u7ebf\u6027\u9636 */\nfunc linear(n: Int) -> Int {\n    var count = 0\n    for _ in 0 ..< n {\n        count += 1\n    }\n    return count\n}\n
time_complexity.js
/* \u7ebf\u6027\u9636 */\nfunction linear(n) {\n    let count = 0;\n    for (let i = 0; i < n; i++) count++;\n    return count;\n}\n
time_complexity.ts
/* \u7ebf\u6027\u9636 */\nfunction linear(n: number): number {\n    let count = 0;\n    for (let i = 0; i < n; i++) count++;\n    return count;\n}\n
time_complexity.dart
/* \u7ebf\u6027\u9636 */\nint linear(int n) {\n  int count = 0;\n  for (var i = 0; i < n; i++) {\n    count++;\n  }\n  return count;\n}\n
time_complexity.rs
/* \u7ebf\u6027\u9636 */\nfn linear(n: i32) -> i32 {\n    let mut count = 0;\n    for _ in 0..n {\n        count += 1;\n    }\n    count\n}\n
time_complexity.c
/* \u7ebf\u6027\u9636 */\nint linear(int n) {\n    int count = 0;\n    for (int i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.zig
// \u7ebf\u6027\u9636\nfn linear(n: i32) i32 {\n    var count: i32 = 0;\n    var i: i32 = 0;\n    while (i < n) : (i += 1) {\n        count += 1;\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

Operations like array traversal and linked list traversal have a time complexity of \\(O(n)\\), where \\(n\\) is the length of the array or list:

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def array_traversal(nums: list[int]) -> int:\n    \"\"\"\u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09\"\"\"\n    count = 0\n    # \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for num in nums:\n        count += 1\n    return count\n
time_complexity.cpp
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nint arrayTraversal(vector<int> &nums) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for (int num : nums) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.java
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nint arrayTraversal(int[] nums) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for (int num : nums) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.cs
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nint ArrayTraversal(int[] nums) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    foreach (int num in nums) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.go
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nfunc arrayTraversal(nums []int) int {\n    count := 0\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for range nums {\n        count++\n    }\n    return count\n}\n
time_complexity.swift
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nfunc arrayTraversal(nums: [Int]) -> Int {\n    var count = 0\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for _ in nums {\n        count += 1\n    }\n    return count\n}\n
time_complexity.js
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nfunction arrayTraversal(nums) {\n    let count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for (let i = 0; i < nums.length; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.ts
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nfunction arrayTraversal(nums: number[]): number {\n    let count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for (let i = 0; i < nums.length; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.dart
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nint arrayTraversal(List<int> nums) {\n  int count = 0;\n  // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n  for (var _num in nums) {\n    count++;\n  }\n  return count;\n}\n
time_complexity.rs
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nfn array_traversal(nums: &[i32]) -> i32 {\n    let mut count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for _ in nums {\n        count += 1;\n    }\n    count\n}\n
time_complexity.c
/* \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09 */\nint arrayTraversal(int *nums, int n) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for (int i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.zig
// \u7ebf\u6027\u9636\uff08\u904d\u5386\u6570\u7ec4\uff09\nfn arrayTraversal(nums: []i32) i32 {\n    var count: i32 = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u6b63\u6bd4\n    for (nums) |_| {\n        count += 1;\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

It's important to note that the input data size \\(n\\) should be determined based on the type of input data. For example, in the first example, \\(n\\) represents the input data size, while in the second example, the length of the array \\(n\\) is the data size.

"},{"location":"chapter_computational_complexity/time_complexity/#3-quadratic-order-on2","title":"3. \u00a0 Quadratic Order \\(O(n^2)\\)","text":"

Quadratic order means the number of operations grows quadratically with the input data size \\(n\\). Quadratic order typically appears in nested loops, where both the outer and inner loops have a time complexity of \\(O(n)\\), resulting in an overall complexity of \\(O(n^2)\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def quadratic(n: int) -> int:\n    \"\"\"\u5e73\u65b9\u9636\"\"\"\n    count = 0\n    # \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for i in range(n):\n        for j in range(n):\n            count += 1\n    return count\n
time_complexity.cpp
/* \u5e73\u65b9\u9636 */\nint quadratic(int n) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            count++;\n        }\n    }\n    return count;\n}\n
time_complexity.java
/* \u5e73\u65b9\u9636 */\nint quadratic(int n) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            count++;\n        }\n    }\n    return count;\n}\n
time_complexity.cs
/* \u5e73\u65b9\u9636 */\nint Quadratic(int n) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            count++;\n        }\n    }\n    return count;\n}\n
time_complexity.go
/* \u5e73\u65b9\u9636 */\nfunc quadratic(n int) int {\n    count := 0\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for i := 0; i < n; i++ {\n        for j := 0; j < n; j++ {\n            count++\n        }\n    }\n    return count\n}\n
time_complexity.swift
/* \u5e73\u65b9\u9636 */\nfunc quadratic(n: Int) -> Int {\n    var count = 0\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for _ in 0 ..< n {\n        for _ in 0 ..< n {\n            count += 1\n        }\n    }\n    return count\n}\n
time_complexity.js
/* \u5e73\u65b9\u9636 */\nfunction quadratic(n) {\n    let count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for (let i = 0; i < n; i++) {\n        for (let j = 0; j < n; j++) {\n            count++;\n        }\n    }\n    return count;\n}\n
time_complexity.ts
/* \u5e73\u65b9\u9636 */\nfunction quadratic(n: number): number {\n    let count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for (let i = 0; i < n; i++) {\n        for (let j = 0; j < n; j++) {\n            count++;\n        }\n    }\n    return count;\n}\n
time_complexity.dart
/* \u5e73\u65b9\u9636 */\nint quadratic(int n) {\n  int count = 0;\n  // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n  for (int i = 0; i < n; i++) {\n    for (int j = 0; j < n; j++) {\n      count++;\n    }\n  }\n  return count;\n}\n
time_complexity.rs
/* \u5e73\u65b9\u9636 */\nfn quadratic(n: i32) -> i32 {\n    let mut count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for _ in 0..n {\n        for _ in 0..n {\n            count += 1;\n        }\n    }\n    count\n}\n
time_complexity.c
/* \u5e73\u65b9\u9636 */\nint quadratic(int n) {\n    int count = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < n; j++) {\n            count++;\n        }\n    }\n    return count;\n}\n
time_complexity.zig
// \u5e73\u65b9\u9636\nfn quadratic(n: i32) i32 {\n    var count: i32 = 0;\n    var i: i32 = 0;\n    // \u5faa\u73af\u6b21\u6570\u4e0e\u6570\u7ec4\u957f\u5ea6\u6210\u5e73\u65b9\u5173\u7cfb\n    while (i < n) : (i += 1) {\n        var j: i32 = 0;\n        while (j < n) : (j += 1) {\n            count += 1;\n        }\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

The following image compares constant order, linear order, and quadratic order time complexities.

Figure 2-10 \u00a0 Constant, Linear, and Quadratic Order Time Complexities

For instance, in bubble sort, the outer loop runs \\(n - 1\\) times, and the inner loop runs \\(n-1\\), \\(n-2\\), ..., \\(2\\), \\(1\\) times, averaging \\(n / 2\\) times, resulting in a time complexity of \\(O((n - 1) n / 2) = O(n^2)\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def bubble_sort(nums: list[int]) -> int:\n    \"\"\"\u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09\"\"\"\n    count = 0  # \u8ba1\u6570\u5668\n    # \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for i in range(len(nums) - 1, 0, -1):\n        # \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n        for j in range(i):\n            if nums[j] > nums[j + 1]:\n                # \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                tmp: int = nums[j]\n                nums[j] = nums[j + 1]\n                nums[j + 1] = tmp\n                count += 3  # \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n    return count\n
time_complexity.cpp
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nint bubbleSort(vector<int> &nums) {\n    int count = 0; // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for (int i = nums.size() - 1; i > 0; i--) {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n        for (int j = 0; j < i; j++) {\n            if (nums[j] > nums[j + 1]) {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                int tmp = nums[j];\n                nums[j] = nums[j + 1];\n                nums[j + 1] = tmp;\n                count += 3; // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count;\n}\n
time_complexity.java
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nint bubbleSort(int[] nums) {\n    int count = 0; // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for (int i = nums.length - 1; i > 0; i--) {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n        for (int j = 0; j < i; j++) {\n            if (nums[j] > nums[j + 1]) {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                int tmp = nums[j];\n                nums[j] = nums[j + 1];\n                nums[j + 1] = tmp;\n                count += 3; // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count;\n}\n
time_complexity.cs
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nint BubbleSort(int[] nums) {\n    int count = 0;  // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for (int i = nums.Length - 1; i > 0; i--) {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef \n        for (int j = 0; j < i; j++) {\n            if (nums[j] > nums[j + 1]) {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                (nums[j + 1], nums[j]) = (nums[j], nums[j + 1]);\n                count += 3;  // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count;\n}\n
time_complexity.go
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nfunc bubbleSort(nums []int) int {\n    count := 0 // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for i := len(nums) - 1; i > 0; i-- {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n        for j := 0; j < i; j++ {\n            if nums[j] > nums[j+1] {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                tmp := nums[j]\n                nums[j] = nums[j+1]\n                nums[j+1] = tmp\n                count += 3 // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count\n}\n
time_complexity.swift
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nfunc bubbleSort(nums: inout [Int]) -> Int {\n    var count = 0 // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for i in stride(from: nums.count - 1, to: 0, by: -1) {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef \n        for j in 0 ..< i {\n            if nums[j] > nums[j + 1] {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                let tmp = nums[j]\n                nums[j] = nums[j + 1]\n                nums[j + 1] = tmp\n                count += 3 // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count\n}\n
time_complexity.js
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nfunction bubbleSort(nums) {\n    let count = 0; // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for (let i = nums.length - 1; i > 0; i--) {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n        for (let j = 0; j < i; j++) {\n            if (nums[j] > nums[j + 1]) {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                let tmp = nums[j];\n                nums[j] = nums[j + 1];\n                nums[j + 1] = tmp;\n                count += 3; // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count;\n}\n
time_complexity.ts
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nfunction bubbleSort(nums: number[]): number {\n    let count = 0; // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for (let i = nums.length - 1; i > 0; i--) {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n        for (let j = 0; j < i; j++) {\n            if (nums[j] > nums[j + 1]) {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                let tmp = nums[j];\n                nums[j] = nums[j + 1];\n                nums[j + 1] = tmp;\n                count += 3; // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count;\n}\n
time_complexity.dart
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nint bubbleSort(List<int> nums) {\n  int count = 0; // \u8ba1\u6570\u5668\n  // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n  for (var i = nums.length - 1; i > 0; i--) {\n    // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n    for (var j = 0; j < i; j++) {\n      if (nums[j] > nums[j + 1]) {\n        // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n        int tmp = nums[j];\n        nums[j] = nums[j + 1];\n        nums[j + 1] = tmp;\n        count += 3; // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n      }\n    }\n  }\n  return count;\n}\n
time_complexity.rs
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nfn bubble_sort(nums: &mut [i32]) -> i32 {\n    let mut count = 0; // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for i in (1..nums.len()).rev() {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef \n        for j in 0..i {\n            if nums[j] > nums[j + 1] {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                let tmp = nums[j];\n                nums[j] = nums[j + 1];\n                nums[j + 1] = tmp;\n                count += 3; // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    count\n}\n
time_complexity.c
/* \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09 */\nint bubbleSort(int *nums, int n) {\n    int count = 0; // \u8ba1\u6570\u5668\n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    for (int i = n - 1; i > 0; i--) {\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef\n        for (int j = 0; j < i; j++) {\n            if (nums[j] > nums[j + 1]) {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                int tmp = nums[j];\n                nums[j] = nums[j + 1];\n                nums[j + 1] = tmp;\n                count += 3; // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count;\n}\n
time_complexity.zig
// \u5e73\u65b9\u9636\uff08\u5192\u6ce1\u6392\u5e8f\uff09\nfn bubbleSort(nums: []i32) i32 {\n    var count: i32 = 0;  // \u8ba1\u6570\u5668 \n    // \u5916\u5faa\u73af\uff1a\u672a\u6392\u5e8f\u533a\u95f4\u4e3a [0, i]\n    var i: i32 = @as(i32, @intCast(nums.len)) - 1;\n    while (i > 0) : (i -= 1) {\n        var j: usize = 0;\n        // \u5185\u5faa\u73af\uff1a\u5c06\u672a\u6392\u5e8f\u533a\u95f4 [0, i] \u4e2d\u7684\u6700\u5927\u5143\u7d20\u4ea4\u6362\u81f3\u8be5\u533a\u95f4\u7684\u6700\u53f3\u7aef \n        while (j < i) : (j += 1) {\n            if (nums[j] > nums[j + 1]) {\n                // \u4ea4\u6362 nums[j] \u4e0e nums[j + 1]\n                var tmp = nums[j];\n                nums[j] = nums[j + 1];\n                nums[j + 1] = tmp;\n                count += 3;  // \u5143\u7d20\u4ea4\u6362\u5305\u542b 3 \u4e2a\u5355\u5143\u64cd\u4f5c\n            }\n        }\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_computational_complexity/time_complexity/#4-exponential-order-o2n","title":"4. \u00a0 Exponential Order \\(O(2^n)\\)","text":"

Biological \"cell division\" is a classic example of exponential order growth: starting with one cell, it becomes two after one division, four after two divisions, and so on, resulting in \\(2^n\\) cells after \\(n\\) divisions.

The following image and code simulate the cell division process, with a time complexity of \\(O(2^n)\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def exponential(n: int) -> int:\n    \"\"\"\u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09\"\"\"\n    count = 0\n    base = 1\n    # \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for _ in range(n):\n        for _ in range(base):\n            count += 1\n        base *= 2\n    # count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count\n
time_complexity.cpp
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint exponential(int n) {\n    int count = 0, base = 1;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < base; j++) {\n            count++;\n        }\n        base *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count;\n}\n
time_complexity.java
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint exponential(int n) {\n    int count = 0, base = 1;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < base; j++) {\n            count++;\n        }\n        base *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count;\n}\n
time_complexity.cs
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint Exponential(int n) {\n    int count = 0, bas = 1;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < bas; j++) {\n            count++;\n        }\n        bas *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count;\n}\n
time_complexity.go
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09*/\nfunc exponential(n int) int {\n    count, base := 0, 1\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for i := 0; i < n; i++ {\n        for j := 0; j < base; j++ {\n            count++\n        }\n        base *= 2\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count\n}\n
time_complexity.swift
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfunc exponential(n: Int) -> Int {\n    var count = 0\n    var base = 1\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for _ in 0 ..< n {\n        for _ in 0 ..< base {\n            count += 1\n        }\n        base *= 2\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count\n}\n
time_complexity.js
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfunction exponential(n) {\n    let count = 0,\n        base = 1;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for (let i = 0; i < n; i++) {\n        for (let j = 0; j < base; j++) {\n            count++;\n        }\n        base *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count;\n}\n
time_complexity.ts
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfunction exponential(n: number): number {\n    let count = 0,\n        base = 1;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for (let i = 0; i < n; i++) {\n        for (let j = 0; j < base; j++) {\n            count++;\n        }\n        base *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count;\n}\n
time_complexity.dart
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint exponential(int n) {\n  int count = 0, base = 1;\n  // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n  for (var i = 0; i < n; i++) {\n    for (var j = 0; j < base; j++) {\n      count++;\n    }\n    base *= 2;\n  }\n  // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n  return count;\n}\n
time_complexity.rs
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfn exponential(n: i32) -> i32 {\n    let mut count = 0;\n    let mut base = 1;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for _ in 0..n {\n        for _ in 0..base {\n            count += 1\n        }\n        base *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    count\n}\n
time_complexity.c
/* \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint exponential(int n) {\n    int count = 0;\n    int bas = 1;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    for (int i = 0; i < n; i++) {\n        for (int j = 0; j < bas; j++) {\n            count++;\n        }\n        bas *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count;\n}\n
time_complexity.zig
// \u6307\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09\nfn exponential(n: i32) i32 {\n    var count: i32 = 0;\n    var bas: i32 = 1;\n    var i: i32 = 0;\n    // \u7ec6\u80de\u6bcf\u8f6e\u4e00\u5206\u4e3a\u4e8c\uff0c\u5f62\u6210\u6570\u5217 1, 2, 4, 8, ..., 2^(n-1)\n    while (i < n) : (i += 1) {\n        var j: i32 = 0;\n        while (j < bas) : (j += 1) {\n            count += 1;\n        }\n        bas *= 2;\n    }\n    // count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1\n    return count;\n}\n
Visualizing Code

Full Screen >

Figure 2-11 \u00a0 Exponential Order Time Complexity

In practice, exponential order often appears in recursive functions. For example, in the code below, it recursively splits into two halves, stopping after \\(n\\) divisions:

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def exp_recur(n: int) -> int:\n    \"\"\"\u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\"\"\"\n    if n == 1:\n        return 1\n    return exp_recur(n - 1) + exp_recur(n - 1) + 1\n
time_complexity.cpp
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint expRecur(int n) {\n    if (n == 1)\n        return 1;\n    return expRecur(n - 1) + expRecur(n - 1) + 1;\n}\n
time_complexity.java
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint expRecur(int n) {\n    if (n == 1)\n        return 1;\n    return expRecur(n - 1) + expRecur(n - 1) + 1;\n}\n
time_complexity.cs
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint ExpRecur(int n) {\n    if (n == 1) return 1;\n    return ExpRecur(n - 1) + ExpRecur(n - 1) + 1;\n}\n
time_complexity.go
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09*/\nfunc expRecur(n int) int {\n    if n == 1 {\n        return 1\n    }\n    return expRecur(n-1) + expRecur(n-1) + 1\n}\n
time_complexity.swift
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunc expRecur(n: Int) -> Int {\n    if n == 1 {\n        return 1\n    }\n    return expRecur(n: n - 1) + expRecur(n: n - 1) + 1\n}\n
time_complexity.js
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction expRecur(n) {\n    if (n === 1) return 1;\n    return expRecur(n - 1) + expRecur(n - 1) + 1;\n}\n
time_complexity.ts
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction expRecur(n: number): number {\n    if (n === 1) return 1;\n    return expRecur(n - 1) + expRecur(n - 1) + 1;\n}\n
time_complexity.dart
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint expRecur(int n) {\n  if (n == 1) return 1;\n  return expRecur(n - 1) + expRecur(n - 1) + 1;\n}\n
time_complexity.rs
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfn exp_recur(n: i32) -> i32 {\n    if n == 1 {\n        return 1;\n    }\n    exp_recur(n - 1) + exp_recur(n - 1) + 1\n}\n
time_complexity.c
/* \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint expRecur(int n) {\n    if (n == 1)\n        return 1;\n    return expRecur(n - 1) + expRecur(n - 1) + 1;\n}\n
time_complexity.zig
// \u6307\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\nfn expRecur(n: i32) i32 {\n    if (n == 1) return 1;\n    return expRecur(n - 1) + expRecur(n - 1) + 1;\n}\n
Visualizing Code

Full Screen >

Exponential order growth is extremely rapid and is commonly seen in exhaustive search methods (brute force, backtracking, etc.). For large-scale problems, exponential order is unacceptable, often requiring dynamic programming or greedy algorithms as solutions.

"},{"location":"chapter_computational_complexity/time_complexity/#5-logarithmic-order-olog-n","title":"5. \u00a0 Logarithmic Order \\(O(\\log n)\\)","text":"

In contrast to exponential order, logarithmic order reflects situations where \"the size is halved each round.\" Given an input data size \\(n\\), since the size is halved each round, the number of iterations is \\(\\log_2 n\\), the inverse function of \\(2^n\\).

The following image and code simulate the \"halving each round\" process, with a time complexity of \\(O(\\log_2 n)\\), commonly abbreviated as \\(O(\\log n)\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def logarithmic(n: float) -> int:\n    \"\"\"\u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09\"\"\"\n    count = 0\n    while n > 1:\n        n = n / 2\n        count += 1\n    return count\n
time_complexity.cpp
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint logarithmic(float n) {\n    int count = 0;\n    while (n > 1) {\n        n = n / 2;\n        count++;\n    }\n    return count;\n}\n
time_complexity.java
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint logarithmic(float n) {\n    int count = 0;\n    while (n > 1) {\n        n = n / 2;\n        count++;\n    }\n    return count;\n}\n
time_complexity.cs
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint Logarithmic(float n) {\n    int count = 0;\n    while (n > 1) {\n        n /= 2;\n        count++;\n    }\n    return count;\n}\n
time_complexity.go
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09*/\nfunc logarithmic(n float64) int {\n    count := 0\n    for n > 1 {\n        n = n / 2\n        count++\n    }\n    return count\n}\n
time_complexity.swift
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfunc logarithmic(n: Double) -> Int {\n    var count = 0\n    var n = n\n    while n > 1 {\n        n = n / 2\n        count += 1\n    }\n    return count\n}\n
time_complexity.js
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfunction logarithmic(n) {\n    let count = 0;\n    while (n > 1) {\n        n = n / 2;\n        count++;\n    }\n    return count;\n}\n
time_complexity.ts
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfunction logarithmic(n: number): number {\n    let count = 0;\n    while (n > 1) {\n        n = n / 2;\n        count++;\n    }\n    return count;\n}\n
time_complexity.dart
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint logarithmic(num n) {\n  int count = 0;\n  while (n > 1) {\n    n = n / 2;\n    count++;\n  }\n  return count;\n}\n
time_complexity.rs
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nfn logarithmic(mut n: f32) -> i32 {\n    let mut count = 0;\n    while n > 1.0 {\n        n = n / 2.0;\n        count += 1;\n    }\n    count\n}\n
time_complexity.c
/* \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09 */\nint logarithmic(float n) {\n    int count = 0;\n    while (n > 1) {\n        n = n / 2;\n        count++;\n    }\n    return count;\n}\n
time_complexity.zig
// \u5bf9\u6570\u9636\uff08\u5faa\u73af\u5b9e\u73b0\uff09\nfn logarithmic(n: f32) i32 {\n    var count: i32 = 0;\n    var n_var = n;\n    while (n_var > 1)\n    {\n        n_var = n_var / 2;\n        count +=1;\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

Figure 2-12 \u00a0 Logarithmic Order Time Complexity

Like exponential order, logarithmic order also frequently appears in recursive functions. The code below forms a recursive tree of height \\(\\log_2 n\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def log_recur(n: float) -> int:\n    \"\"\"\u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\"\"\"\n    if n <= 1:\n        return 0\n    return log_recur(n / 2) + 1\n
time_complexity.cpp
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint logRecur(float n) {\n    if (n <= 1)\n        return 0;\n    return logRecur(n / 2) + 1;\n}\n
time_complexity.java
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint logRecur(float n) {\n    if (n <= 1)\n        return 0;\n    return logRecur(n / 2) + 1;\n}\n
time_complexity.cs
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint LogRecur(float n) {\n    if (n <= 1) return 0;\n    return LogRecur(n / 2) + 1;\n}\n
time_complexity.go
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09*/\nfunc logRecur(n float64) int {\n    if n <= 1 {\n        return 0\n    }\n    return logRecur(n/2) + 1\n}\n
time_complexity.swift
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunc logRecur(n: Double) -> Int {\n    if n <= 1 {\n        return 0\n    }\n    return logRecur(n: n / 2) + 1\n}\n
time_complexity.js
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction logRecur(n) {\n    if (n <= 1) return 0;\n    return logRecur(n / 2) + 1;\n}\n
time_complexity.ts
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction logRecur(n: number): number {\n    if (n <= 1) return 0;\n    return logRecur(n / 2) + 1;\n}\n
time_complexity.dart
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint logRecur(num n) {\n  if (n <= 1) return 0;\n  return logRecur(n / 2) + 1;\n}\n
time_complexity.rs
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfn log_recur(n: f32) -> i32 {\n    if n <= 1.0 {\n        return 0;\n    }\n    log_recur(n / 2.0) + 1\n}\n
time_complexity.c
/* \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint logRecur(float n) {\n    if (n <= 1)\n        return 0;\n    return logRecur(n / 2) + 1;\n}\n
time_complexity.zig
// \u5bf9\u6570\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\nfn logRecur(n: f32) i32 {\n    if (n <= 1) return 0;\n    return logRecur(n / 2) + 1;\n}\n
Visualizing Code

Full Screen >

Logarithmic order is typical in algorithms based on the divide-and-conquer strategy, embodying the \"split into many\" and \"simplify complex problems\" approach. It's slow-growing and is the most ideal time complexity after constant order.

What is the base of \\(O(\\log n)\\)?

Technically, \"splitting into \\(m\\)\" corresponds to a time complexity of \\(O(\\log_m n)\\). Using the logarithm base change formula, we can equate different logarithmic complexities:

\\[ O(\\log_m n) = O(\\log_k n / \\log_k m) = O(\\log_k n) \\]

This means the base \\(m\\) can be changed without affecting the complexity. Therefore, we often omit the base \\(m\\) and simply denote logarithmic order as \\(O(\\log n)\\).

"},{"location":"chapter_computational_complexity/time_complexity/#6-linear-logarithmic-order-on-log-n","title":"6. \u00a0 Linear-Logarithmic Order \\(O(n \\log n)\\)","text":"

Linear-logarithmic order often appears in nested loops, with the complexities of the two loops being \\(O(\\log n)\\) and \\(O(n)\\) respectively. The related code is as follows:

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def linear_log_recur(n: float) -> int:\n    \"\"\"\u7ebf\u6027\u5bf9\u6570\u9636\"\"\"\n    if n <= 1:\n        return 1\n    count: int = linear_log_recur(n // 2) + linear_log_recur(n // 2)\n    for _ in range(n):\n        count += 1\n    return count\n
time_complexity.cpp
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nint linearLogRecur(float n) {\n    if (n <= 1)\n        return 1;\n    int count = linearLogRecur(n / 2) + linearLogRecur(n / 2);\n    for (int i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.java
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nint linearLogRecur(float n) {\n    if (n <= 1)\n        return 1;\n    int count = linearLogRecur(n / 2) + linearLogRecur(n / 2);\n    for (int i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.cs
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nint LinearLogRecur(float n) {\n    if (n <= 1) return 1;\n    int count = LinearLogRecur(n / 2) + LinearLogRecur(n / 2);\n    for (int i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.go
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nfunc linearLogRecur(n float64) int {\n    if n <= 1 {\n        return 1\n    }\n    count := linearLogRecur(n/2) + linearLogRecur(n/2)\n    for i := 0.0; i < n; i++ {\n        count++\n    }\n    return count\n}\n
time_complexity.swift
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nfunc linearLogRecur(n: Double) -> Int {\n    if n <= 1 {\n        return 1\n    }\n    var count = linearLogRecur(n: n / 2) + linearLogRecur(n: n / 2)\n    for _ in stride(from: 0, to: n, by: 1) {\n        count += 1\n    }\n    return count\n}\n
time_complexity.js
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nfunction linearLogRecur(n) {\n    if (n <= 1) return 1;\n    let count = linearLogRecur(n / 2) + linearLogRecur(n / 2);\n    for (let i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.ts
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nfunction linearLogRecur(n: number): number {\n    if (n <= 1) return 1;\n    let count = linearLogRecur(n / 2) + linearLogRecur(n / 2);\n    for (let i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.dart
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nint linearLogRecur(num n) {\n  if (n <= 1) return 1;\n  int count = linearLogRecur(n / 2) + linearLogRecur(n / 2);\n  for (var i = 0; i < n; i++) {\n    count++;\n  }\n  return count;\n}\n
time_complexity.rs
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nfn linear_log_recur(n: f32) -> i32 {\n    if n <= 1.0 {\n        return 1;\n    }\n    let mut count = linear_log_recur(n / 2.0) + linear_log_recur(n / 2.0);\n    for _ in 0 ..n as i32 {\n        count += 1;\n    }\n    return count\n}\n
time_complexity.c
/* \u7ebf\u6027\u5bf9\u6570\u9636 */\nint linearLogRecur(float n) {\n    if (n <= 1)\n        return 1;\n    int count = linearLogRecur(n / 2) + linearLogRecur(n / 2);\n    for (int i = 0; i < n; i++) {\n        count++;\n    }\n    return count;\n}\n
time_complexity.zig
// \u7ebf\u6027\u5bf9\u6570\u9636\nfn linearLogRecur(n: f32) i32 {\n    if (n <= 1) return 1;\n    var count: i32 = linearLogRecur(n / 2) + linearLogRecur(n / 2);\n    var i: f32 = 0;\n    while (i < n) : (i += 1) {\n        count += 1;\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

The image below demonstrates how linear-logarithmic order is generated. Each level of a binary tree has \\(n\\) operations, and the tree has \\(\\log_2 n + 1\\) levels, resulting in a time complexity of \\(O(n \\log n)\\).

Figure 2-13 \u00a0 Linear-Logarithmic Order Time Complexity

Mainstream sorting algorithms typically have a time complexity of \\(O(n \\log n)\\), such as quicksort, mergesort, and heapsort.

"},{"location":"chapter_computational_complexity/time_complexity/#7-factorial-order-on","title":"7. \u00a0 Factorial Order \\(O(n!)\\)","text":"

Factorial order corresponds to the mathematical problem of \"full permutation.\" Given \\(n\\) distinct elements, the total number of possible permutations is:

\\[ n! = n \\times (n - 1) \\times (n - 2) \\times \\dots \\times 2 \\times 1 \\]

Factorials are typically implemented using recursion. As shown in the image and code below, the first level splits into \\(n\\) branches, the second level into \\(n - 1\\) branches, and so on, stopping after the \\(n\\)th level:

PythonC++JavaC#GoSwiftJSTSDartRustCZig time_complexity.py
def factorial_recur(n: int) -> int:\n    \"\"\"\u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\"\"\"\n    if n == 0:\n        return 1\n    count = 0\n    # \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for _ in range(n):\n        count += factorial_recur(n - 1)\n    return count\n
time_complexity.cpp
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint factorialRecur(int n) {\n    if (n == 0)\n        return 1;\n    int count = 0;\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for (int i = 0; i < n; i++) {\n        count += factorialRecur(n - 1);\n    }\n    return count;\n}\n
time_complexity.java
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint factorialRecur(int n) {\n    if (n == 0)\n        return 1;\n    int count = 0;\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for (int i = 0; i < n; i++) {\n        count += factorialRecur(n - 1);\n    }\n    return count;\n}\n
time_complexity.cs
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint FactorialRecur(int n) {\n    if (n == 0) return 1;\n    int count = 0;\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for (int i = 0; i < n; i++) {\n        count += FactorialRecur(n - 1);\n    }\n    return count;\n}\n
time_complexity.go
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunc factorialRecur(n int) int {\n    if n == 0 {\n        return 1\n    }\n    count := 0\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for i := 0; i < n; i++ {\n        count += factorialRecur(n - 1)\n    }\n    return count\n}\n
time_complexity.swift
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunc factorialRecur(n: Int) -> Int {\n    if n == 0 {\n        return 1\n    }\n    var count = 0\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for _ in 0 ..< n {\n        count += factorialRecur(n: n - 1)\n    }\n    return count\n}\n
time_complexity.js
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction factorialRecur(n) {\n    if (n === 0) return 1;\n    let count = 0;\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for (let i = 0; i < n; i++) {\n        count += factorialRecur(n - 1);\n    }\n    return count;\n}\n
time_complexity.ts
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfunction factorialRecur(n: number): number {\n    if (n === 0) return 1;\n    let count = 0;\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for (let i = 0; i < n; i++) {\n        count += factorialRecur(n - 1);\n    }\n    return count;\n}\n
time_complexity.dart
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint factorialRecur(int n) {\n  if (n == 0) return 1;\n  int count = 0;\n  // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n  for (var i = 0; i < n; i++) {\n    count += factorialRecur(n - 1);\n  }\n  return count;\n}\n
time_complexity.rs
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nfn factorial_recur(n: i32) -> i32 {\n    if n == 0 {\n        return 1;\n    }\n    let mut count = 0;\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    for _ in 0..n {\n        count += factorial_recur(n - 1);\n    }\n    count\n}\n
time_complexity.c
/* \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09 */\nint factorialRecur(int n) {\n    if (n == 0)\n        return 1;\n    int count = 0;\n    for (int i = 0; i < n; i++) {\n        count += factorialRecur(n - 1);\n    }\n    return count;\n}\n
time_complexity.zig
// \u9636\u4e58\u9636\uff08\u9012\u5f52\u5b9e\u73b0\uff09\nfn factorialRecur(n: i32) i32 {\n    if (n == 0) return 1;\n    var count: i32 = 0;\n    var i: i32 = 0;\n    // \u4ece 1 \u4e2a\u5206\u88c2\u51fa n \u4e2a\n    while (i < n) : (i += 1) {\n        count += factorialRecur(n - 1);\n    }\n    return count;\n}\n
Visualizing Code

Full Screen >

Figure 2-14 \u00a0 Factorial Order Time Complexity

Note that factorial order grows even faster than exponential order; it's unacceptable for larger \\(n\\) values.

"},{"location":"chapter_computational_complexity/time_complexity/#235-worst-best-and-average-time-complexities","title":"2.3.5 \u00a0 Worst, Best, and Average Time Complexities","text":"

The time efficiency of an algorithm is often not fixed but depends on the distribution of the input data. Assume we have an array nums of length \\(n\\), consisting of numbers from \\(1\\) to \\(n\\), each appearing only once, but in a randomly shuffled order. The task is to return the index of the element \\(1\\). We can draw the following conclusions:

  • When nums = [?, ?, ..., 1], that is, when the last element is \\(1\\), it requires a complete traversal of the array, achieving the worst-case time complexity of \\(O(n)\\).
  • When nums = [1, ?, ?, ...], that is, when the first element is \\(1\\), no matter the length of the array, no further traversal is needed, achieving the best-case time complexity of \\(\\Omega(1)\\).

The \"worst-case time complexity\" corresponds to the asymptotic upper bound, denoted by the big \\(O\\) notation. Correspondingly, the \"best-case time complexity\" corresponds to the asymptotic lower bound, denoted by \\(\\Omega\\):

PythonC++JavaC#GoSwiftJSTSDartRustCZig worst_best_time_complexity.py
def random_numbers(n: int) -> list[int]:\n    \"\"\"\u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a: 1, 2, ..., n \uff0c\u987a\u5e8f\u88ab\u6253\u4e71\"\"\"\n    # \u751f\u6210\u6570\u7ec4 nums =: 1, 2, 3, ..., n\n    nums = [i for i in range(1, n + 1)]\n    # \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    random.shuffle(nums)\n    return nums\n\ndef find_one(nums: list[int]) -> int:\n    \"\"\"\u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15\"\"\"\n    for i in range(len(nums)):\n        # \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        # \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if nums[i] == 1:\n            return i\n    return -1\n
worst_best_time_complexity.cpp
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nvector<int> randomNumbers(int n) {\n    vector<int> nums(n);\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for (int i = 0; i < n; i++) {\n        nums[i] = i + 1;\n    }\n    // \u4f7f\u7528\u7cfb\u7edf\u65f6\u95f4\u751f\u6210\u968f\u673a\u79cd\u5b50\n    unsigned seed = chrono::system_clock::now().time_since_epoch().count();\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    shuffle(nums.begin(), nums.end(), default_random_engine(seed));\n    return nums;\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nint findOne(vector<int> &nums) {\n    for (int i = 0; i < nums.size(); i++) {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if (nums[i] == 1)\n            return i;\n    }\n    return -1;\n}\n
worst_best_time_complexity.java
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nint[] randomNumbers(int n) {\n    Integer[] nums = new Integer[n];\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for (int i = 0; i < n; i++) {\n        nums[i] = i + 1;\n    }\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    Collections.shuffle(Arrays.asList(nums));\n    // Integer[] -> int[]\n    int[] res = new int[n];\n    for (int i = 0; i < n; i++) {\n        res[i] = nums[i];\n    }\n    return res;\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nint findOne(int[] nums) {\n    for (int i = 0; i < nums.length; i++) {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if (nums[i] == 1)\n            return i;\n    }\n    return -1;\n}\n
worst_best_time_complexity.cs
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nint[] RandomNumbers(int n) {\n    int[] nums = new int[n];\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for (int i = 0; i < n; i++) {\n        nums[i] = i + 1;\n    }\n\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    for (int i = 0; i < nums.Length; i++) {\n        int index = new Random().Next(i, nums.Length);\n        (nums[i], nums[index]) = (nums[index], nums[i]);\n    }\n    return nums;\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nint FindOne(int[] nums) {\n    for (int i = 0; i < nums.Length; i++) {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if (nums[i] == 1)\n            return i;\n    }\n    return -1;\n}\n
worst_best_time_complexity.go
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nfunc randomNumbers(n int) []int {\n    nums := make([]int, n)\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for i := 0; i < n; i++ {\n        nums[i] = i + 1\n    }\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    rand.Shuffle(len(nums), func(i, j int) {\n        nums[i], nums[j] = nums[j], nums[i]\n    })\n    return nums\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nfunc findOne(nums []int) int {\n    for i := 0; i < len(nums); i++ {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if nums[i] == 1 {\n            return i\n        }\n    }\n    return -1\n}\n
worst_best_time_complexity.swift
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nfunc randomNumbers(n: Int) -> [Int] {\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    var nums = Array(1 ... n)\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    nums.shuffle()\n    return nums\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nfunc findOne(nums: [Int]) -> Int {\n    for i in nums.indices {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if nums[i] == 1 {\n            return i\n        }\n    }\n    return -1\n}\n
worst_best_time_complexity.js
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nfunction randomNumbers(n) {\n    const nums = Array(n);\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for (let i = 0; i < n; i++) {\n        nums[i] = i + 1;\n    }\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    for (let i = 0; i < n; i++) {\n        const r = Math.floor(Math.random() * (i + 1));\n        const temp = nums[i];\n        nums[i] = nums[r];\n        nums[r] = temp;\n    }\n    return nums;\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nfunction findOne(nums) {\n    for (let i = 0; i < nums.length; i++) {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if (nums[i] === 1) {\n            return i;\n        }\n    }\n    return -1;\n}\n
worst_best_time_complexity.ts
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nfunction randomNumbers(n: number): number[] {\n    const nums = Array(n);\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for (let i = 0; i < n; i++) {\n        nums[i] = i + 1;\n    }\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    for (let i = 0; i < n; i++) {\n        const r = Math.floor(Math.random() * (i + 1));\n        const temp = nums[i];\n        nums[i] = nums[r];\n        nums[r] = temp;\n    }\n    return nums;\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nfunction findOne(nums: number[]): number {\n    for (let i = 0; i < nums.length; i++) {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if (nums[i] === 1) {\n            return i;\n        }\n    }\n    return -1;\n}\n
worst_best_time_complexity.dart
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nList<int> randomNumbers(int n) {\n  final nums = List.filled(n, 0);\n  // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n  for (var i = 0; i < n; i++) {\n    nums[i] = i + 1;\n  }\n  // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n  nums.shuffle();\n\n  return nums;\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nint findOne(List<int> nums) {\n  for (var i = 0; i < nums.length; i++) {\n    // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n    // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n    if (nums[i] == 1) return i;\n  }\n\n  return -1;\n}\n
worst_best_time_complexity.rs
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nfn random_numbers(n: i32) -> Vec<i32> {\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    let mut nums = (1..=n).collect::<Vec<i32>>();\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    nums.shuffle(&mut thread_rng());\n    nums\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nfn find_one(nums: &[i32]) -> Option<usize> {\n    for i in 0..nums.len() {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if nums[i] == 1 {\n            return Some(i);\n        }\n    }\n    None\n}\n
worst_best_time_complexity.c
/* \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71 */\nint *randomNumbers(int n) {\n    // \u5206\u914d\u5806\u533a\u5185\u5b58\uff08\u521b\u5efa\u4e00\u7ef4\u53ef\u53d8\u957f\u6570\u7ec4\uff1a\u6570\u7ec4\u4e2d\u5143\u7d20\u6570\u91cf\u4e3a n \uff0c\u5143\u7d20\u7c7b\u578b\u4e3a int \uff09\n    int *nums = (int *)malloc(n * sizeof(int));\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for (int i = 0; i < n; i++) {\n        nums[i] = i + 1;\n    }\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    for (int i = n - 1; i > 0; i--) {\n        int j = rand() % (i + 1);\n        int temp = nums[i];\n        nums[i] = nums[j];\n        nums[j] = temp;\n    }\n    return nums;\n}\n\n/* \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15 */\nint findOne(int *nums, int n) {\n    for (int i = 0; i < n; i++) {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if (nums[i] == 1)\n            return i;\n    }\n    return -1;\n}\n
worst_best_time_complexity.zig
// \u751f\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u5143\u7d20\u4e3a { 1, 2, ..., n }\uff0c\u987a\u5e8f\u88ab\u6253\u4e71\nfn randomNumbers(comptime n: usize) [n]i32 {\n    var nums: [n]i32 = undefined;\n    // \u751f\u6210\u6570\u7ec4 nums = { 1, 2, 3, ..., n }\n    for (&nums, 0..) |*num, i| {\n        num.* = @as(i32, @intCast(i)) + 1;\n    }\n    // \u968f\u673a\u6253\u4e71\u6570\u7ec4\u5143\u7d20\n    const rand = std.crypto.random;\n    rand.shuffle(i32, &nums);\n    return nums;\n}\n\n// \u67e5\u627e\u6570\u7ec4 nums \u4e2d\u6570\u5b57 1 \u6240\u5728\u7d22\u5f15\nfn findOne(nums: []i32) i32 {\n    for (nums, 0..) |num, i| {\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5934\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u4f73\u65f6\u95f4\u590d\u6742\u5ea6 O(1)\n        // \u5f53\u5143\u7d20 1 \u5728\u6570\u7ec4\u5c3e\u90e8\u65f6\uff0c\u8fbe\u5230\u6700\u5dee\u65f6\u95f4\u590d\u6742\u5ea6 O(n)\n        if (num == 1) return @intCast(i);\n    }\n    return -1;\n}\n
Visualizing Code

Full Screen >

It's important to note that the best-case time complexity is rarely used in practice, as it is usually only achievable under very low probabilities and might be misleading. The worst-case time complexity is more practical as it provides a safety value for efficiency, allowing us to confidently use the algorithm.

From the above example, it's clear that both the worst-case and best-case time complexities only occur under \"special data distributions,\" which may have a small probability of occurrence and may not accurately reflect the algorithm's run efficiency. In contrast, the average time complexity can reflect the algorithm's efficiency under random input data, denoted by the \\(\\Theta\\) notation.

For some algorithms, we can simply estimate the average case under a random data distribution. For example, in the aforementioned example, since the input array is shuffled, the probability of element \\(1\\) appearing at any index is equal. Therefore, the average number of loops for the algorithm is half the length of the array \\(n / 2\\), giving an average time complexity of \\(\\Theta(n / 2) = \\Theta(n)\\).

However, calculating the average time complexity for more complex algorithms can be quite difficult, as it's challenging to analyze the overall mathematical expectation under the data distribution. In such cases, we usually use the worst-case time complexity as the standard for judging the efficiency of the algorithm.

Why is the \\(\\Theta\\) symbol rarely seen?

Possibly because the \\(O\\) notation is more commonly spoken, it is often used to represent the average time complexity. However, strictly speaking, this practice is not accurate. In this book and other materials, if you encounter statements like \"average time complexity \\(O(n)\\)\", please understand it directly as \\(\\Theta(n)\\).

"},{"location":"chapter_data_structure/","title":"Chapter 3. \u00a0 Data Structures","text":"

Abstract

Data structures serve as a robust and diverse framework.

They offer a blueprint for the orderly organization of data, upon which algorithms come to life.

"},{"location":"chapter_data_structure/#chapter-contents","title":"Chapter Contents","text":"
  • 3.1 \u00a0 Classification of Data Structures
  • 3.2 \u00a0 Fundamental Data Types
  • 3.3 \u00a0 Number Encoding *
  • 3.4 \u00a0 Character Encoding *
  • 3.5 \u00a0 Summary
"},{"location":"chapter_data_structure/basic_data_types/","title":"3.2 \u00a0 Basic Data Types","text":"

When discussing data in computers, various forms like text, images, videos, voice and 3D models comes to mind. Despite their different organizational forms, they are all composed of various basic data types.

Basic data types are those that the CPU can directly operate on and are directly used in algorithms, mainly including the following.

  • Integer types: byte, short, int, long.
  • Floating-point types: float, double, used to represent decimals.
  • Character type: char, used to represent letters, punctuation, and even emojis in various languages.
  • Boolean type: bool, used to represent \"yes\" or \"no\" decisions.

Basic data types are stored in computers in binary form. One binary digit is 1 bit. In most modern operating systems, 1 byte consists of 8 bits.

The range of values for basic data types depends on the size of the space they occupy. Below, we take Java as an example.

  • The integer type byte occupies 1 byte = 8 bits and can represent \\(2^8\\) numbers.
  • The integer type int occupies 4 bytes = 32 bits and can represent \\(2^{32}\\) numbers.

The following table lists the space occupied, value range, and default values of various basic data types in Java. While memorizing this table isn't necessary, having a general understanding of it and referencing it when required is recommended.

Table 3-1 \u00a0 Space Occupied and Value Range of Basic Data Types

Type Symbol Space Occupied Minimum Value Maximum Value Default Value Integer byte 1 byte \\(-2^7\\) (\\(-128\\)) \\(2^7 - 1\\) (\\(127\\)) 0 short 2 bytes \\(-2^{15}\\) \\(2^{15} - 1\\) 0 int 4 bytes \\(-2^{31}\\) \\(2^{31} - 1\\) 0 long 8 bytes \\(-2^{63}\\) \\(2^{63} - 1\\) 0 Float float 4 bytes \\(1.175 \\times 10^{-38}\\) \\(3.403 \\times 10^{38}\\) \\(0.0\\text{f}\\) double 8 bytes \\(2.225 \\times 10^{-308}\\) \\(1.798 \\times 10^{308}\\) 0.0 Char char 2 bytes 0 \\(2^{16} - 1\\) 0 Boolean bool 1 byte \\(\\text{false}\\) \\(\\text{true}\\) \\(\\text{false}\\)

Please note that the above table is specific to Java's basic data types. Every programming language has its own data type definitions, which might differ in space occupied, value ranges, and default values.

  • In Python, the integer type int can be of any size, limited only by available memory; the floating-point float is double precision 64-bit; there is no char type, as a single character is actually a string str of length 1.
  • C and C++ do not specify the size of basic data types, it varies with implementation and platform. The above table follows the LP64 data model, used for Unix 64-bit operating systems including Linux and macOS.
  • The size of char in C and C++ is 1 byte, while in most programming languages, it depends on the specific character encoding method, as detailed in the \"Character Encoding\" chapter.
  • Even though representing a boolean only requires 1 bit (0 or 1), it is usually stored in memory as 1 byte. This is because modern computer CPUs typically use 1 byte as the smallest addressable memory unit.

So, what is the connection between basic data types and data structures? We know that data structures are ways to organize and store data in computers. The focus here is on \"structure\" rather than \"data\".

If we want to represent \"a row of numbers\", we naturally think of using an array. This is because the linear structure of an array can represent the adjacency and the ordering of the numbers, but whether the stored content is an integer int, a decimal float, or a character char, is irrelevant to the \"data structure\".

In other words, basic data types provide the \"content type\" of data, while data structures provide the \"way of organizing\" data. For example, in the following code, we use the same data structure (array) to store and represent different basic data types, including int, float, char, bool, etc.

PythonC++JavaC#GoSwiftJSTSDartRustCZig
# Using various basic data types to initialize arrays\nnumbers: list[int] = [0] * 5\ndecimals: list[float] = [0.0] * 5\n# Python's characters are actually strings of length 1\ncharacters: list[str] = ['0'] * 5\nbools: list[bool] = [False] * 5\n# Python's lists can freely store various basic data types and object references\ndata = [0, 0.0, 'a', False, ListNode(0)]\n
// Using various basic data types to initialize arrays\nint numbers[5];\nfloat decimals[5];\nchar characters[5];\nbool bools[5];\n
// Using various basic data types to initialize arrays\nint[] numbers = new int[5];\nfloat[] decimals = new float[5];\nchar[] characters = new char[5];\nboolean[] bools = new boolean[5];\n
// Using various basic data types to initialize arrays\nint[] numbers = new int[5];\nfloat[] decimals = new float[5];\nchar[] characters = new char[5];\nbool[] bools = new bool[5];\n
// Using various basic data types to initialize arrays\nvar numbers = [5]int{}\nvar decimals = [5]float64{}\nvar characters = [5]byte{}\nvar bools = [5]bool{}\n
// Using various basic data types to initialize arrays\nlet numbers = Array(repeating: Int(), count: 5)\nlet decimals = Array(repeating: Double(), count: 5)\nlet characters = Array(repeating: Character(\"a\"), count: 5)\nlet bools = Array(repeating: Bool(), count: 5)\n
// JavaScript's arrays can freely store various basic data types and objects\nconst array = [0, 0.0, 'a', false];\n
// Using various basic data types to initialize arrays\nconst numbers: number[] = [];\nconst characters: string[] = [];\nconst bools: boolean[] = [];\n
// Using various basic data types to initialize arrays\nList<int> numbers = List.filled(5, 0);\nList<double> decimals = List.filled(5, 0.0);\nList<String> characters = List.filled(5, 'a');\nList<bool> bools = List.filled(5, false);\n
// Using various basic data types to initialize arrays\nlet numbers: Vec<i32> = vec![0; 5];\nlet decimals: Vec<f32> = vec![0.0, 5];\nlet characters: Vec<char> = vec!['0'; 5];\nlet bools: Vec<bool> = vec![false; 5];\n
// Using various basic data types to initialize arrays\nint numbers[10];\nfloat decimals[10];\nchar characters[10];\nbool bools[10];\n
// Using various basic data types to initialize arrays\nvar numbers: [5]i32 = undefined;\nvar decimals: [5]f32 = undefined;\nvar characters: [5]u8 = undefined;\nvar bools: [5]bool = undefined;\n
"},{"location":"chapter_data_structure/character_encoding/","title":"3.4 \u00a0 Character Encoding *","text":"

In computers, all data is stored in binary form, and the character char is no exception. To represent characters, we need to establish a \"character set\" that defines a one-to-one correspondence between each character and binary numbers. With a character set, computers can convert binary numbers to characters by looking up a table.

"},{"location":"chapter_data_structure/character_encoding/#341-ascii-character-set","title":"3.4.1 \u00a0 ASCII Character Set","text":"

The \"ASCII code\" is one of the earliest character sets, officially known as the American Standard Code for Information Interchange. It uses 7 binary digits (the lower 7 bits of a byte) to represent a character, allowing for a maximum of 128 different characters. As shown in the Figure 3-6 , ASCII includes uppercase and lowercase English letters, numbers 0 ~ 9, some punctuation marks, and some control characters (such as newline and tab).

Figure 3-6 \u00a0 ASCII Code

However, ASCII can only represent English characters. With the globalization of computers, a character set called \"EASCII\" was developed to represent more languages. It expands on the 7-bit basis of ASCII to 8 bits, enabling the representation of 256 different characters.

Globally, a series of EASCII character sets for different regions emerged. The first 128 characters of these sets are uniformly ASCII, while the remaining 128 characters are defined differently to cater to various language requirements.

"},{"location":"chapter_data_structure/character_encoding/#342-gbk-character-set","title":"3.4.2 \u00a0 GBK Character Set","text":"

Later, it was found that EASCII still could not meet the character requirements of many languages. For instance, there are nearly a hundred thousand Chinese characters, with several thousand used in everyday life. In 1980, China's National Standards Bureau released the \"GB2312\" character set, which included 6763 Chinese characters, essentially meeting the computer processing needs for Chinese.

However, GB2312 could not handle some rare and traditional characters. The \"GBK\" character set, an expansion of GB2312, includes a total of 21886 Chinese characters. In the GBK encoding scheme, ASCII characters are represented with one byte, while Chinese characters use two bytes.

"},{"location":"chapter_data_structure/character_encoding/#343-unicode-character-set","title":"3.4.3 \u00a0 Unicode Character Set","text":"

With the rapid development of computer technology and a plethora of character sets and encoding standards, numerous problems arose. On one hand, these character sets generally only defined characters for specific languages and could not function properly in multilingual environments. On the other hand, the existence of multiple character set standards for the same language caused garbled text when information was exchanged between computers using different encoding standards.

Researchers of that era thought: What if we introduced a comprehensive character set that included all languages and symbols worldwide, wouldn't that solve the problems of cross-language environments and garbled text? Driven by this idea, the extensive character set, Unicode, was born.

The Chinese name for \"Unicode\" is \"\u7edf\u4e00\u7801\" (Unified Code), theoretically capable of accommodating over a million characters. It aims to incorporate characters from all over the world into a single set, providing a universal character set for processing and displaying various languages and reducing the issues of garbled text due to different encoding standards.

Since its release in 1991, Unicode has continually expanded to include new languages and characters. As of September 2022, Unicode contains 149,186 characters, including characters, symbols, and even emojis from various languages. In the vast Unicode character set, commonly used characters occupy 2 bytes, while some rare characters take up 3 or even 4 bytes.

Unicode is a universal character set that assigns a number (called a \"code point\") to each character, but it does not specify how these character code points should be stored in a computer. One might ask: When Unicode code points of varying lengths appear in a text, how does the system parse the characters? For example, given a 2-byte code, how does the system determine if it represents a single 2-byte character or two 1-byte characters?

A straightforward solution to this problem is to store all characters as equal-length encodings. As shown in the Figure 3-7 , each character in \"Hello\" occupies 1 byte, while each character in \"\u7b97\u6cd5\" (algorithm) occupies 2 bytes. We could encode all characters in \"Hello \u7b97\u6cd5\" as 2 bytes by padding the higher bits with zeros. This way, the system can parse a character every 2 bytes, recovering the content of the phrase.

Figure 3-7 \u00a0 Unicode Encoding Example

However, as ASCII has shown us, encoding English only requires 1 byte. Using the above approach would double the space occupied by English text compared to ASCII encoding, which is a waste of memory space. Therefore, a more efficient Unicode encoding method is needed.

"},{"location":"chapter_data_structure/character_encoding/#344-utf-8-encoding","title":"3.4.4 \u00a0 UTF-8 Encoding","text":"

Currently, UTF-8 has become the most widely used Unicode encoding method internationally. It is a variable-length encoding, using 1 to 4 bytes to represent a character, depending on the complexity of the character. ASCII characters need only 1 byte, Latin and Greek letters require 2 bytes, commonly used Chinese characters need 3 bytes, and some other rare characters need 4 bytes.

The encoding rules for UTF-8 are not complex and can be divided into two cases:

  • For 1-byte characters, set the highest bit to \\(0\\), and the remaining 7 bits to the Unicode code point. Notably, ASCII characters occupy the first 128 code points in the Unicode set. This means that UTF-8 encoding is backward compatible with ASCII. This implies that UTF-8 can be used to parse ancient ASCII text.
  • For characters of length \\(n\\) bytes (where \\(n > 1\\)), set the highest \\(n\\) bits of the first byte to \\(1\\), and the \\((n + 1)^{\\text{th}}\\) bit to \\(0\\); starting from the second byte, set the highest 2 bits of each byte to \\(10\\); the rest of the bits are used to fill the Unicode code point.

The Figure 3-8 shows the UTF-8 encoding for \"Hello\u7b97\u6cd5\". It can be observed that since the highest \\(n\\) bits are set to \\(1\\), the system can determine the length of the character as \\(n\\) by counting the number of highest bits set to \\(1\\).

But why set the highest 2 bits of the remaining bytes to \\(10\\)? Actually, this \\(10\\) serves as a kind of checksum. If the system starts parsing text from an incorrect byte, the \\(10\\) at the beginning of the byte can help the system quickly detect an anomaly.

The reason for using \\(10\\) as a checksum is that, under UTF-8 encoding rules, it's impossible for the highest two bits of a character to be \\(10\\). This can be proven by contradiction: If the highest two bits of a character are \\(10\\), it indicates that the character's length is \\(1\\), corresponding to ASCII. However, the highest bit of an ASCII character should be \\(0\\), contradicting the assumption.

Figure 3-8 \u00a0 UTF-8 Encoding Example

Apart from UTF-8, other common encoding methods include:

  • UTF-16 Encoding: Uses 2 or 4 bytes to represent a character. All ASCII characters and commonly used non-English characters are represented with 2 bytes; a few characters require 4 bytes. For 2-byte characters, the UTF-16 encoding is equal to the Unicode code point.
  • UTF-32 Encoding: Every character uses 4 bytes. This means UTF-32 occupies more space than UTF-8 and UTF-16, especially for texts with a high proportion of ASCII characters.

From the perspective of storage space, UTF-8 is highly efficient for representing English characters, requiring only 1 byte; UTF-16 might be more efficient for encoding some non-English characters (like Chinese), as it requires only 2 bytes, while UTF-8 might need 3 bytes.

From a compatibility standpoint, UTF-8 is the most versatile, with many tools and libraries supporting UTF-8 as a priority.

"},{"location":"chapter_data_structure/character_encoding/#345-character-encoding-in-programming-languages","title":"3.4.5 \u00a0 Character Encoding in Programming Languages","text":"

In many classic programming languages, strings during program execution are encoded using fixed-length encodings like UTF-16 or UTF-32. This allows strings to be treated as arrays, offering several advantages:

  • Random Access: Strings encoded in UTF-16 can be accessed randomly with ease. For UTF-8, which is a variable-length encoding, locating the \\(i^{th}\\) character requires traversing the string from the start to the \\(i^{th}\\) position, taking \\(O(n)\\) time.
  • Character Counting: Similar to random access, counting the number of characters in a UTF-16 encoded string is an \\(O(1)\\) operation. However, counting characters in a UTF-8 encoded string requires traversing the entire string.
  • String Operations: Many string operations like splitting, concatenating, inserting, and deleting are easier on UTF-16 encoded strings. These operations generally require additional computation on UTF-8 encoded strings to ensure the validity of the UTF-8 encoding.

The design of character encoding schemes in programming languages is an interesting topic involving various factors:

  • Java\u2019s String type uses UTF-16 encoding, with each character occupying 2 bytes. This was based on the initial belief that 16 bits were sufficient to represent all possible characters, a judgment later proven incorrect. As the Unicode standard expanded beyond 16 bits, characters in Java may now be represented by a pair of 16-bit values, known as \u201csurrogate pairs.\u201d
  • JavaScript and TypeScript use UTF-16 encoding for similar reasons as Java. When JavaScript was first introduced by Netscape in 1995, Unicode was still in its early stages, and 16-bit encoding was sufficient to represent all Unicode characters.
  • C# uses UTF-16 encoding, largely because the .NET platform, designed by Microsoft, and many Microsoft technologies, including the Windows operating system, extensively use UTF-16 encoding.

Due to the underestimation of character counts, these languages had to resort to using \"surrogate pairs\" to represent Unicode characters exceeding 16 bits. This approach has its drawbacks: strings containing surrogate pairs may have characters occupying 2 or 4 bytes, losing the advantage of fixed-length encoding, and handling surrogate pairs adds to the complexity and debugging difficulty of programming.

Owing to these reasons, some programming languages have adopted different encoding schemes:

  • Python\u2019s str type uses Unicode encoding with a flexible representation where the storage length of characters depends on the largest Unicode code point in the string. If all characters are ASCII, each character occupies 1 byte; if characters exceed ASCII but are within the Basic Multilingual Plane (BMP), each occupies 2 bytes; if characters exceed the BMP, each occupies 4 bytes.
  • Go\u2019s string type internally uses UTF-8 encoding. Go also provides the rune type for representing individual Unicode code points.
  • Rust\u2019s str and String types use UTF-8 encoding internally. Rust also offers the char type for individual Unicode code points.

It\u2019s important to note that the above discussion pertains to how strings are stored in programming languages, which is a different issue from how strings are stored in files or transmitted over networks. For file storage or network transmission, strings are usually encoded in UTF-8 format for optimal compatibility and space efficiency.

"},{"location":"chapter_data_structure/classification_of_data_structure/","title":"3.1 \u00a0 Classification of Data Structures","text":"

Common data structures include arrays, linked lists, stacks, queues, hash tables, trees, heaps, and graphs. They can be classified into \"logical structure\" and \"physical structure\".

"},{"location":"chapter_data_structure/classification_of_data_structure/#311-logical-structure-linear-and-non-linear","title":"3.1.1 \u00a0 Logical Structure: Linear and Non-Linear","text":"

The logical structures reveal the logical relationships between data elements. In arrays and linked lists, data are arranged in a specific sequence, demonstrating the linear relationship between data; while in trees, data are arranged hierarchically from the top down, showing the derived relationship between \"ancestors\" and \"descendants\"; and graphs are composed of nodes and edges, reflecting the intricate network relationship.

As shown in the Figure 3-1 , logical structures can be divided into two major categories: \"linear\" and \"non-linear\". Linear structures are more intuitive, indicating data is arranged linearly in logical relationships; non-linear structures, conversely, are arranged non-linearly.

  • Linear Data Structures: Arrays, Linked Lists, Stacks, Queues, Hash Tables.
  • Non-Linear Data Structures: Trees, Heaps, Graphs, Hash Tables.

Figure 3-1 \u00a0 Linear and Non-Linear Data Structures

Non-linear data structures can be further divided into tree structures and network structures.

  • Linear Structures: Arrays, linked lists, queues, stacks, and hash tables, where elements have a one-to-one sequential relationship.
  • Tree Structures: Trees, Heaps, Hash Tables, where elements have a one-to-many relationship.
  • Network Structures: Graphs, where elements have a many-to-many relationships.
"},{"location":"chapter_data_structure/classification_of_data_structure/#312-physical-structure-contiguous-and-dispersed","title":"3.1.2 \u00a0 Physical Structure: Contiguous and Dispersed","text":"

During the execution of an algorithm, the data being processed is stored in memory. The Figure 3-2 shows a computer memory stick where each black square is a physical memory space. We can think of memory as a vast Excel spreadsheet, with each cell capable of storing a certain amount of data.

The system accesses the data at the target location by means of a memory address. As shown in the Figure 3-2 , the computer assigns a unique identifier to each cell in the table according to specific rules, ensuring that each memory space has a unique memory address. With these addresses, the program can access the data stored in memory.

Figure 3-2 \u00a0 Memory Stick, Memory Spaces, Memory Addresses

Tip

It's worth noting that comparing memory to an Excel spreadsheet is a simplified analogy. The actual working mechanism of memory is more complex, involving concepts like address space, memory management, cache mechanisms, virtual memory, and physical memory.

Memory is a shared resource for all programs. When a block of memory is occupied by one program, it cannot be simultaneously used by other programs. Therefore, considering memory resources is crucial in designing data structures and algorithms. For instance, the algorithm's peak memory usage should not exceed the remaining free memory of the system; if there is a lack of contiguous memory blocks, then the data structure chosen must be able to be stored in non-contiguous memory blocks.

As illustrated in the Figure 3-3 , the physical structure reflects the way data is stored in computer memory and it can be divided into contiguous space storage (arrays) and non-contiguous space storage (linked lists). The two types of physical structures exhibit complementary characteristics in terms of time efficiency and space efficiency.

Figure 3-3 \u00a0 Contiguous Space Storage and Dispersed Space Storage

It is worth noting that all data structures are implemented based on arrays, linked lists, or a combination of both. For example, stacks and queues can be implemented using either arrays or linked lists; while implementations of hash tables may involve both arrays and linked lists. - Array-based implementations: Stacks, Queues, Hash Tables, Trees, Heaps, Graphs, Matrices, Tensors (arrays with dimensions \\(\\geq 3\\)). - Linked-list-based implementations: Stacks, Queues, Hash Tables, Trees, Heaps, Graphs, etc.

Data structures implemented based on arrays are also called \u201cStatic Data Structures,\u201d meaning their length cannot be changed after initialization. Conversely, those based on linked lists are called \u201cDynamic Data Structures,\u201d which can still adjust their size during program execution.

Tip

If you find it challenging to comprehend the physical structure, it is recommended that you read the next chapter, \"Arrays and Linked Lists,\" and revisit this section later.

"},{"location":"chapter_data_structure/number_encoding/","title":"3.3 \u00a0 Number Encoding *","text":"

Note

In this book, chapters marked with an asterisk '*' are optional readings. If you are short on time or find them challenging, you may skip these initially and return to them after completing the essential chapters.

"},{"location":"chapter_data_structure/number_encoding/#331-integer-encoding","title":"3.3.1 \u00a0 Integer Encoding","text":"

In the table from the previous section, we observed that all integer types can represent one more negative number than positive numbers, such as the byte range of \\([-128, 127]\\). This phenomenon seems counterintuitive, and its underlying reason involves knowledge of sign-magnitude, one's complement, and two's complement encoding.

Firstly, it's important to note that numbers are stored in computers using the two's complement form. Before analyzing why this is the case, let's define these three encoding methods:

  • Sign-magnitude: The highest bit of a binary representation of a number is considered the sign bit, where \\(0\\) represents a positive number and \\(1\\) represents a negative number. The remaining bits represent the value of the number.
  • One's complement: The one's complement of a positive number is the same as its sign-magnitude. For negative numbers, it's obtained by inverting all bits except the sign bit.
  • Two's complement: The two's complement of a positive number is the same as its sign-magnitude. For negative numbers, it's obtained by adding \\(1\\) to their one's complement.

The following diagram illustrates the conversions among sign-magnitude, one's complement, and two's complement:

Figure 3-4 \u00a0 Conversions between Sign-Magnitude, One's Complement, and Two's Complement

Although sign-magnitude is the most intuitive, it has limitations. For one, negative numbers in sign-magnitude cannot be directly used in calculations. For example, in sign-magnitude, calculating \\(1 + (-2)\\) results in \\(-3\\), which is incorrect.

\\[ \\begin{aligned} & 1 + (-2) \\newline & \\rightarrow 0000 \\; 0001 + 1000 \\; 0010 \\newline & = 1000 \\; 0011 \\newline & \\rightarrow -3 \\end{aligned} \\]

To address this, computers introduced the one's complement. If we convert to one's complement and calculate \\(1 + (-2)\\), then convert the result back to sign-magnitude, we get the correct result of \\(-1\\).

\\[ \\begin{aligned} & 1 + (-2) \\newline & \\rightarrow 0000 \\; 0001 \\; \\text{(Sign-magnitude)} + 1000 \\; 0010 \\; \\text{(Sign-magnitude)} \\newline & = 0000 \\; 0001 \\; \\text{(One's complement)} + 1111 \\; 1101 \\; \\text{(One's complement)} \\newline & = 1111 \\; 1110 \\; \\text{(One's complement)} \\newline & = 1000 \\; 0001 \\; \\text{(Sign-magnitude)} \\newline & \\rightarrow -1 \\end{aligned} \\]

Additionally, there are two representations of zero in sign-magnitude: \\(+0\\) and \\(-0\\). This means two different binary encodings for zero, which could lead to ambiguity. For example, in conditional checks, not differentiating between positive and negative zero might result in incorrect outcomes. Addressing this ambiguity would require additional checks, potentially reducing computational efficiency.

\\[ \\begin{aligned} +0 & \\rightarrow 0000 \\; 0000 \\newline -0 & \\rightarrow 1000 \\; 0000 \\end{aligned} \\]

Like sign-magnitude, one's complement also suffers from the positive and negative zero ambiguity. Therefore, computers further introduced the two's complement. Let's observe the conversion process for negative zero in sign-magnitude, one's complement, and two's complement:

\\[ \\begin{aligned} -0 \\rightarrow \\; & 1000 \\; 0000 \\; \\text{(Sign-magnitude)} \\newline = \\; & 1111 \\; 1111 \\; \\text{(One's complement)} \\newline = 1 \\; & 0000 \\; 0000 \\; \\text{(Two's complement)} \\newline \\end{aligned} \\]

Adding \\(1\\) to the one's complement of negative zero produces a carry, but with byte length being only 8 bits, the carried-over \\(1\\) to the 9th bit is discarded. Therefore, the two's complement of negative zero is \\(0000 \\; 0000\\), the same as positive zero, thus resolving the ambiguity.

One last puzzle is the \\([-128, 127]\\) range for byte, with an additional negative number, \\(-128\\). We observe that for the interval \\([-127, +127]\\), all integers have corresponding sign-magnitude, one's complement, and two's complement, allowing for mutual conversion between them.

However, the two's complement \\(1000 \\; 0000\\) is an exception without a corresponding sign-magnitude. According to the conversion method, its sign-magnitude would be \\(0000 \\; 0000\\), indicating zero. This presents a contradiction because its two's complement should represent itself. Computers designate this special two's complement \\(1000 \\; 0000\\) as representing \\(-128\\). In fact, the calculation of \\((-1) + (-127)\\) in two's complement results in \\(-128\\).

\\[ \\begin{aligned} & (-127) + (-1) \\newline & \\rightarrow 1111 \\; 1111 \\; \\text{(Sign-magnitude)} + 1000 \\; 0001 \\; \\text{(Sign-magnitude)} \\newline & = 1000 \\; 0000 \\; \\text{(One's complement)} + 1111 \\; 1110 \\; \\text{(One's complement)} \\newline & = 1000 \\; 0001 \\; \\text{(Two's complement)} + 1111 \\; 1111 \\; \\text{(Two's complement)} \\newline & = 1000 \\; 0000 \\; \\text{(Two's complement)} \\newline & \\rightarrow -128 \\end{aligned} \\]

As you might have noticed, all these calculations are additions, hinting at an important fact: computers' internal hardware circuits are primarily designed around addition operations. This is because addition is simpler to implement in hardware compared to other operations like multiplication, division, and subtraction, allowing for easier parallelization and faster computation.

It's important to note that this doesn't mean computers can only perform addition. By combining addition with basic logical operations, computers can execute a variety of other mathematical operations. For example, the subtraction \\(a - b\\) can be translated into \\(a + (-b)\\); multiplication and division can be translated into multiple additions or subtractions.

We can now summarize the reason for using two's complement in computers: with two's complement representation, computers can use the same circuits and operations to handle both positive and negative number addition, eliminating the need for special hardware circuits for subtraction and avoiding the ambiguity of positive and negative zero. This greatly simplifies hardware design and enhances computational efficiency.

The design of two's complement is quite ingenious, and due to space constraints, we'll stop here. Interested readers are encouraged to explore further.

"},{"location":"chapter_data_structure/number_encoding/#332-floating-point-number-encoding","title":"3.3.2 \u00a0 Floating-Point Number Encoding","text":"

You might have noticed something intriguing: despite having the same length of 4 bytes, why does a float have a much larger range of values compared to an int? This seems counterintuitive, as one would expect the range to shrink for float since it needs to represent fractions.

In fact, this is due to the different representation method used by floating-point numbers (float). Let's consider a 32-bit binary number as:

\\[ b_{31} b_{30} b_{29} \\ldots b_2 b_1 b_0 \\]

According to the IEEE 754 standard, a 32-bit float consists of the following three parts:

  • Sign bit \\(\\mathrm{S}\\): Occupies 1 bit, corresponding to \\(b_{31}\\).
  • Exponent bit \\(\\mathrm{E}\\): Occupies 8 bits, corresponding to \\(b_{30} b_{29} \\ldots b_{23}\\).
  • Fraction bit \\(\\mathrm{N}\\): Occupies 23 bits, corresponding to \\(b_{22} b_{21} \\ldots b_0\\).

The value of a binary float number is calculated as:

\\[ \\text{val} = (-1)^{b_{31}} \\times 2^{\\left(b_{30} b_{29} \\ldots b_{23}\\right)_2 - 127} \\times \\left(1 . b_{22} b_{21} \\ldots b_0\\right)_2 \\]

Converted to a decimal formula, this becomes:

\\[ \\text{val} = (-1)^{\\mathrm{S}} \\times 2^{\\mathrm{E} - 127} \\times (1 + \\mathrm{N}) \\]

The range of each component is:

\\[ \\begin{aligned} \\mathrm{S} \\in & \\{ 0, 1\\}, \\quad \\mathrm{E} \\in \\{ 1, 2, \\dots, 254 \\} \\newline (1 + \\mathrm{N}) = & (1 + \\sum_{i=1}^{23} b_{23-i} \\times 2^{-i}) \\subset [1, 2 - 2^{-23}] \\end{aligned} \\]

Figure 3-5 \u00a0 Example Calculation of a float in IEEE 754 Standard

Observing the diagram, given an example data \\(\\mathrm{S} = 0\\), \\(\\mathrm{E} = 124\\), \\(\\mathrm{N} = 2^{-2} + 2^{-3} = 0.375\\), we have:

\\[ \\text{val} = (-1)^0 \\times 2^{124 - 127} \\times (1 + 0.375) = 0.171875 \\]

Now we can answer the initial question: The representation of float includes an exponent bit, leading to a much larger range than int. Based on the above calculation, the maximum positive number representable by float is approximately \\(2^{254 - 127} \\times (2 - 2^{-23}) \\approx 3.4 \\times 10^{38}\\), and the minimum negative number is obtained by switching the sign bit.

However, the trade-off for float's expanded range is a sacrifice in precision. The integer type int uses all 32 bits to represent the number, with values evenly distributed; but due to the exponent bit, the larger the value of a float, the greater the difference between adjacent numbers.

As shown in the Table 3-2 , exponent bits \\(E = 0\\) and \\(E = 255\\) have special meanings, used to represent zero, infinity, \\(\\mathrm{NaN}\\), etc.

Table 3-2 \u00a0 Meaning of Exponent Bits

Exponent Bit E Fraction Bit \\(\\mathrm{N} = 0\\) Fraction Bit \\(\\mathrm{N} \\ne 0\\) Calculation Formula \\(0\\) \\(\\pm 0\\) Subnormal Numbers \\((-1)^{\\mathrm{S}} \\times 2^{-126} \\times (0.\\mathrm{N})\\) \\(1, 2, \\dots, 254\\) Normal Numbers Normal Numbers \\((-1)^{\\mathrm{S}} \\times 2^{(\\mathrm{E} -127)} \\times (1.\\mathrm{N})\\) \\(255\\) \\(\\pm \\infty\\) \\(\\mathrm{NaN}\\)

It's worth noting that subnormal numbers significantly improve the precision of floating-point numbers. The smallest positive normal number is \\(2^{-126}\\), and the smallest positive subnormal number is \\(2^{-126} \\times 2^{-23}\\).

Double-precision double also uses a similar representation method to float, which is not elaborated here for brevity.

"},{"location":"chapter_data_structure/summary/","title":"3.5 \u00a0 Summary","text":""},{"location":"chapter_data_structure/summary/#1-key-review","title":"1. \u00a0 Key Review","text":"
  • Data structures can be categorized from two perspectives: logical structure and physical structure. Logical structure describes the logical relationships between data elements, while physical structure describes how data is stored in computer memory.
  • Common logical structures include linear, tree-like, and network structures. We generally classify data structures into linear (arrays, linked lists, stacks, queues) and non-linear (trees, graphs, heaps) based on their logical structure. The implementation of hash tables may involve both linear and non-linear data structures.
  • When a program runs, data is stored in computer memory. Each memory space has a corresponding memory address, and the program accesses data through these addresses.
  • Physical structures are primarily divided into contiguous space storage (arrays) and dispersed space storage (linked lists). All data structures are implemented using arrays, linked lists, or a combination of both.
  • Basic data types in computers include integers (byte, short, int, long), floating-point numbers (float, double), characters (char), and booleans (boolean). Their range depends on the size of the space occupied and the representation method.
  • Original code, complement code, and two's complement code are three methods of encoding numbers in computers, and they can be converted into each other. The highest bit of the original code of an integer is the sign bit, and the remaining bits represent the value of the number.
  • Integers are stored in computers in the form of two's complement. In this representation, the computer can treat the addition of positive and negative numbers uniformly, without the need for special hardware circuits for subtraction, and there is no ambiguity of positive and negative zero.
  • The encoding of floating-point numbers consists of 1 sign bit, 8 exponent bits, and 23 fraction bits. Due to the presence of the exponent bit, the range of floating-point numbers is much greater than that of integers, but at the cost of sacrificing precision.
  • ASCII is the earliest English character set, 1 byte in length, and includes 127 characters. The GBK character set is a commonly used Chinese character set, including more than 20,000 Chinese characters. Unicode strives to provide a complete character set standard, including characters from various languages worldwide, thus solving the problem of garbled characters caused by inconsistent character encoding methods.
  • UTF-8 is the most popular Unicode encoding method, with excellent universality. It is a variable-length encoding method with good scalability and effectively improves the efficiency of space usage. UTF-16 and UTF-32 are fixed-length encoding methods. When encoding Chinese characters, UTF-16 occupies less space than UTF-8. Programming languages like Java and C# use UTF-16 encoding by default.
"},{"location":"chapter_data_structure/summary/#2-q-a","title":"2. \u00a0 Q & A","text":"

Q: Why does a hash table contain both linear and non-linear data structures?

The underlying structure of a hash table is an array. To resolve hash collisions, we may use \"chaining\": each bucket in the array points to a linked list, which, when exceeding a certain threshold, might be transformed into a tree (usually a red-black tree). From a storage perspective, the foundation of a hash table is an array, where each bucket slot might contain a value, a linked list, or a tree. Therefore, hash tables may contain both linear data structures (arrays, linked lists) and non-linear data structures (trees).

Q: Is the length of the char type 1 byte?

The length of the char type is determined by the encoding method used by the programming language. For example, Java, JavaScript, TypeScript, and C# all use UTF-16 encoding (to save Unicode code points), so the length of the char type is 2 bytes.

Q: Is there ambiguity in calling data structures based on arrays \"static data structures\"? Because operations like push and pop on stacks are \"dynamic\".

While stacks indeed allow for dynamic data operations, the data structure itself remains \"static\" (with unchangeable length). Even though data structures based on arrays can dynamically add or remove elements, their capacity is fixed. If the data volume exceeds the pre-allocated size, a new, larger array needs to be created, and the contents of the old array copied into it.

Q: When building stacks (queues) without specifying their size, why are they considered \"static data structures\"?

In high-level programming languages, we don't need to manually specify the initial capacity of stacks (queues); this task is automatically handled internally by the class. For example, the initial capacity of Java's ArrayList is usually 10. Furthermore, the expansion operation is also implemented automatically. See the subsequent \"List\" chapter for details.

"},{"location":"chapter_introduction/","title":"Chapter 1. \u00a0 Introduction to Algorithms","text":"

Abstract

A graceful maiden dances, intertwined with the data, her skirt swaying to the melody of algorithms.

She invites you to a dance, follow her steps, and enter the world of algorithms full of logic and beauty.

"},{"location":"chapter_introduction/#chapter-contents","title":"Chapter Contents","text":"
  • 1.1 \u00a0 Algorithms are Everywhere
  • 1.2 \u00a0 What is an Algorithm
  • 1.3 \u00a0 Summary
"},{"location":"chapter_introduction/algorithms_are_everywhere/","title":"1.1 \u00a0 Algorithms are Everywhere","text":"

When we hear the word \"algorithm,\" we naturally think of mathematics. However, many algorithms do not involve complex mathematics but rely more on basic logic, which can be seen everywhere in our daily lives.

Before formally discussing algorithms, there's an interesting fact worth sharing: you have already unconsciously learned many algorithms and have become accustomed to applying them in your daily life. Here, I will give a few specific examples to prove this point.

Example 1: Looking Up a Dictionary. In an English dictionary, words are listed alphabetically. Suppose we're searching for a word that starts with the letter \\(r\\). This is typically done in the following way:

  1. Open the dictionary to about halfway and check the first letter on the page, let's say the letter is \\(m\\).
  2. Since \\(r\\) comes after \\(m\\) in the alphabet, we can ignore the first half of the dictionary and focus on the latter half.
  3. Repeat steps 1. and 2. until you find the page where the word starts with \\(r\\).
<1><2><3><4><5>

Figure 1-1 \u00a0 Process of Looking Up a Dictionary

This essential skill for elementary students, looking up a dictionary, is actually the famous \"Binary Search\" algorithm. From a data structure perspective, we can consider the dictionary as a sorted \"array\"; from an algorithmic perspective, the series of actions taken to look up a word in the dictionary can be viewed as \"Binary Search.\"

Example 2: Organizing Playing Cards. When playing cards, we need to arrange the cards in our hand in ascending order, as shown in the following process.

  1. Divide the playing cards into \"ordered\" and \"unordered\" sections, assuming initially the leftmost card is already in order.
  2. Take out a card from the unordered section and insert it into the correct position in the ordered section; after this, the leftmost two cards are in order.
  3. Continue to repeat step 2. until all cards are in order.

Figure 1-2 \u00a0 Playing Cards Sorting Process

The above method of organizing playing cards is essentially the \"Insertion Sort\" algorithm, which is very efficient for small datasets. Many programming languages' sorting functions include the insertion sort.

Example 3: Making Change. Suppose we buy goods worth \\(69\\) yuan at a supermarket and give the cashier \\(100\\) yuan, then the cashier needs to give us \\(31\\) yuan in change. They would naturally complete the thought process as shown below.

  1. The options are currencies smaller than \\(31\\), including \\(1\\), \\(5\\), \\(10\\), and \\(20\\).
  2. Take out the largest \\(20\\) from the options, leaving \\(31 - 20 = 11\\).
  3. Take out the largest \\(10\\) from the remaining options, leaving \\(11 - 10 = 1\\).
  4. Take out the largest \\(1\\) from the remaining options, leaving \\(1 - 1 = 0\\).
  5. Complete the change-making, with the solution being \\(20 + 10 + 1 = 31\\).

Figure 1-3 \u00a0 Change making process

In the above steps, we make the best choice at each step (using the largest denomination possible), ultimately resulting in a feasible change-making plan. From the perspective of data structures and algorithms, this method is essentially a \"Greedy\" algorithm.

From cooking a meal to interstellar travel, almost all problem-solving involves algorithms. The advent of computers allows us to store data structures in memory and write code to call the CPU and GPU to execute algorithms. In this way, we can transfer real-life problems to computers, solving various complex issues more efficiently.

Tip

If concepts such as data structures, algorithms, arrays, and binary search still seem somewhat obsecure, I encourage you to continue reading. This book will gently guide you into the realm of understanding data structures and algorithms.

"},{"location":"chapter_introduction/summary/","title":"1.3 \u00a0 Summary","text":"
  • Algorithms are ubiquitous in daily life and are not as inaccessible and complex as they might seem. In fact, we have already unconsciously learned many algorithms to solve various problems in life.
  • The principle of looking up a word in a dictionary is consistent with the binary search algorithm. The binary search algorithm embodies the important algorithmic concept of divide and conquer.
  • The process of organizing playing cards is very similar to the insertion sort algorithm. The insertion sort algorithm is suitable for sorting small datasets.
  • The steps of making change in currency essentially follow the greedy algorithm, where each step involves making the best possible choice at the moment.
  • An algorithm is a set of instructions or steps used to solve a specific problem within a finite amount of time, while a data structure is the way data is organized and stored in a computer.
  • Data structures and algorithms are closely linked. Data structures are the foundation of algorithms, and algorithms are the stage to utilize the functions of data structures.
  • We can liken data structures and algorithms to building blocks. The blocks represent data, the shape and connection method of the blocks represent data structures, and the steps of assembling the blocks correspond to algorithms.
"},{"location":"chapter_introduction/what_is_dsa/","title":"1.2 \u00a0 What is an Algorithm","text":""},{"location":"chapter_introduction/what_is_dsa/#121-definition-of-an-algorithm","title":"1.2.1 \u00a0 Definition of an Algorithm","text":"

An \"algorithm\" is a set of instructions or steps to solve a specific problem within a finite amount of time. It has the following characteristics:

  • The problem is clearly defined, including unambiguous definitions of input and output.
  • The algorithm is feasible, meaning it can be completed within a finite number of steps, time, and memory space.
  • Each step has a definitive meaning. The output is consistently the same under the same inputs and conditions.
"},{"location":"chapter_introduction/what_is_dsa/#122-definition-of-a-data-structure","title":"1.2.2 \u00a0 Definition of a Data Structure","text":"

A \"data structure\" is a way of organizing and storing data in a computer, with the following design goals:

  • Minimize space occupancy to save computer memory.
  • Make data operations as fast as possible, covering data access, addition, deletion, updating, etc.
  • Provide concise data representation and logical information to enable efficient algorithm execution.

Designing data structures is a balancing act, often requiring trade-offs. If you want to improve in one aspect, you often need to compromise in another. Here are two examples:

  • Compared to arrays, linked lists offer more convenience in data addition and deletion but sacrifice data access speed.
  • Graphs, compared to linked lists, provide richer logical information but require more memory space.
"},{"location":"chapter_introduction/what_is_dsa/#123-relationship-between-data-structures-and-algorithms","title":"1.2.3 \u00a0 Relationship Between Data Structures and Algorithms","text":"

As shown in the Figure 1-4 , data structures and algorithms are highly related and closely integrated, specifically in the following three aspects:

  • Data structures are the foundation of algorithms. They provide structured data storage and methods for manipulating data for algorithms.
  • Algorithms are the stage where data structures come into play. The data structure alone only stores data information; it is through the application of algorithms that specific problems can be solved.
  • Algorithms can often be implemented based on different data structures, but their execution efficiency can vary greatly. Choosing the right data structure is key.

Figure 1-4 \u00a0 Relationship between data structures and algorithms

Data structures and algorithms can be likened to a set of building blocks, as illustrated in the Figure 1-5 . A building block set includes numerous pieces, accompanied by detailed assembly instructions. Following these instructions step by step allows us to construct an intricate block model.

Figure 1-5 \u00a0 Assembling blocks

The detailed correspondence between the two is shown in the Table 1-1 .

Table 1-1 \u00a0 Comparing Data Structures and Algorithms to Building Blocks

Data Structures and Algorithms Building Blocks Input data Unassembled blocks Data structure Organization of blocks, including shape, size, connections, etc Algorithm A series of steps to assemble the blocks into the desired shape Output data Completed Block model

It's worth noting that data structures and algorithms are independent of programming languages. For this reason, this book is able to provide implementations in multiple programming languages.

Conventional Abbreviation

In real-life discussions, we often refer to \"Data Structures and Algorithms\" simply as \"Algorithms\". For example, the well-known LeetCode algorithm problems actually test both data structure and algorithm knowledge.

"},{"location":"chapter_preface/","title":"Chapter 0. \u00a0 Preface","text":"

Abstract

Algorithms are like a beautiful symphony, with each line of code flowing like a rhythm.

May this book ring softly in your mind, leaving a unique and profound melody.

"},{"location":"chapter_preface/#chapter-contents","title":"Chapter Contents","text":"
  • 0.1 \u00a0 About This Book
  • 0.2 \u00a0 How to Read
  • 0.3 \u00a0 Summary
"},{"location":"chapter_preface/about_the_book/","title":"0.1 \u00a0 About This Book","text":"

This open-source project aims to create a free, and beginner-friendly crash course on data structures and algorithms.

  • Using animated illustrations, it delivers structured insights into data structures and algorithmic concepts, ensuring comprehensibility and a smooth learning curve.
  • Run code with just one click, supporting Java, C++, Python, Go, JS, TS, C#, Swift, Rust, Dart, Zig and other languages.
  • Readers are encouraged to engage with each other in the discussion area for each section, questions and comments are usually answered within two days.
"},{"location":"chapter_preface/about_the_book/#011-target-audience","title":"0.1.1 \u00a0 Target Audience","text":"

If you are new to algorithms with limited exposure, or you have accumulated some experience in algorithms, but you only have a vague understanding of data structures and algorithms, and you are constantly jumping between \"yep\" and \"hmm\", then this book is for you!

If you have already accumulated a certain amount of problem-solving experience, and are familiar with most types of problems, then this book can help you review and organize your algorithm knowledge system. The repository's source code can be used as a \"problem-solving toolkit\" or an \"algorithm cheat sheet\".

If you are an algorithm expert, we look forward to receiving your valuable suggestions, or join us and collaborate.

Prerequisites

You should know how to write and read simple code in at least one programming language.

"},{"location":"chapter_preface/about_the_book/#012-content-structure","title":"0.1.2 \u00a0 Content Structure","text":"

The main content of the book is shown in the following figure.

  • Complexity Analysis: explores aspects and methods for evaluating data structures and algorithms. Covers methods of deriving time complexity and space complexity, along with common types and examples.
  • Data Structures: focuses on fundamental data types, classification methods, definitions, pros and cons, common operations, types, applications, and implementation methods of data structures such as array, linked list, stack, queue, hash table, tree, heap, graph, etc.
  • Algorithms: defines algorithms, discusses their pros and cons, efficiency, application scenarios, problem-solving steps, and includes sample questions for various algorithms such as search, sorting, divide and conquer, backtracking, dynamic programming, greedy algorithms, and more.

Figure 0-1 \u00a0 Main Content of the Book

"},{"location":"chapter_preface/about_the_book/#013-acknowledgements","title":"0.1.3 \u00a0 Acknowledgements","text":"

This book is continuously improved with the joint efforts of many contributors from the open-source community. Thanks to each writer who invested their time and energy, listed in the order generated by GitHub: krahets, codingonion, nuomi1, Gonglja, Reanon, justin-tse, danielsss, hpstory, S-N-O-R-L-A-X, night-cruise, msk397, gvenusleo, RiverTwilight, gyt95, zhuoqinyue, Zuoxun, Xia-Sang, mingXta, FangYuan33, GN-Yu, IsChristina, xBLACKICEx, guowei-gong, Cathay-Chen, mgisr, JoseHung, qualifier1024, pengchzn, Guanngxu, longsizhuo, L-Super, what-is-me, yuan0221, lhxsm, Slone123c, WSL0809, longranger2, theNefelibatas, xiongsp, JeffersonHuang, hongyun-robot, K3v123, yuelinxin, a16su, gaofer, malone6, Wonderdch, xjr7670, DullSword, Horbin-Magician, NI-SW, reeswell, XC-Zero, XiaChuerwu, yd-j, iron-irax, huawuque404, MolDuM, Nigh, KorsChen, foursevenlove, 52coder, bubble9um, youshaoXG, curly210102, gltianwen, fanchenggang, Transmigration-zhou, FloranceYeh, FreddieLi, ShiMaRing, lipusheng, Javesun99, JackYang-hellobobo, shanghai-Jerry, 0130w, Keynman, psychelzh, logan-qiu, ZnYang2018, MwumLi, 1ch0, Phoenix0415, qingpeng9802, Richard-Zhang1019, QiLOL, Suremotoo, Turing-1024-Lee, Evilrabbit520, GaochaoZhu, ZJKung, linzeyan, hezhizhen, ZongYangL, beintentional, czruby, coderlef, dshlstarr, szu17dmy, fbigm, gledfish, hts0000, boloboloda, iStig, jiaxianhua, wenjianmin, keshida, kilikilikid, lclc6, lwbaptx, liuxjerry, lucaswangdev, lyl625760, chadyi, noobcodemaker, selear, siqyka, syd168, 4yDX3906, tao363, wangwang105, weibk, yabo083, yi427, yishangzhang, zhouLion, baagod, ElaBosak233, xb534, luluxia, yanedie, thomasq0, YangXuanyi and th1nk3r-ing.

The code review work for this book was completed by codingonion, Gonglja, gvenusleo, hpstory, justin\u2010tse, krahets, night-cruise, nuomi1, and Reanon (listed in alphabetical order). Thanks to them for their time and effort, ensuring the standardization and uniformity of the code in various languages.

Throughout the creation of this book, numerous individuals provided invaluable assistance, including but not limited to:

  • Thanks to my mentor at the company, Dr. Xi Li, who encouraged me in a conversation to \"get moving fast,\" which solidified my determination to write this book;
  • Thanks to my girlfriend Bubble, as the first reader of this book, for offering many valuable suggestions from the perspective of a beginner in algorithms, making this book more suitable for newbies;
  • Thanks to Tengbao, Qibao, and Feibao for coming up with a creative name for this book, evoking everyone's fond memories of writing their first line of code \"Hello World!\";
  • Thanks to Xiaoquan for providing professional help in intellectual property, which has played a significant role in the development of this open-source book;
  • Thanks to Sutong for designing a beautiful cover and logo for this book, and for patiently making multiple revisions under my insistence;
  • Thanks to @squidfunk for providing writing and typesetting suggestions, as well as his developed open-source documentation theme Material-for-MkDocs.

Throughout the writing journey, I delved into numerous textbooks and articles on data structures and algorithms. These works served as exemplary models, ensuring the accuracy and quality of this book's content. I extend my gratitude to all who preceded me for their invaluable contributions!

This book advocates a combination of hands-on and minds-on learning, inspired in this regard by \"Dive into Deep Learning\". I highly recommend this excellent book to all readers.

Heartfelt thanks to my parents, whose ongoing support and encouragement have allowed me to do this interesting work.

"},{"location":"chapter_preface/suggestions/","title":"0.2 \u00a0 How to Read","text":"

Tip

For the best reading experience, it is recommended that you read through this section.

"},{"location":"chapter_preface/suggestions/#021-writing-conventions","title":"0.2.1 \u00a0 Writing Conventions","text":"
  • Chapters marked with '*' after the title are optional and contain relatively challenging content. If you are short on time, it is advisable to skip them.
  • Key technical terms and their English equivalents are enclosed in Bold + italics brackets, for example, array. It's advisable to familiarize yourself with these for better comprehension of technical texts.
  • Proprietary terms and words with specific meanings are indicated with \u201cquotation marks\u201d to avoid ambiguity.
  • Bolded text indicates key content or summary statements, which deserve special attention.
  • When it comes to terms that are inconsistent between programming languages, this book follows Python, for example using \\(\\text{None}\\) to mean \"null\".
  • This book partially ignores the comment conventions for programming languages in exchange for a more compact layout of the content. The comments primarily consist of three types: title comments, content comments, and multi-line comments.
PythonC++JavaC#GoSwiftJSTSDartRustCZig
\"\"\"Header comments for labeling functions, classes, test samples, etc\"\"\"\"\n\n# Comments for explaining details\n\n\"\"\"\nMultiline\ncomments\n\"\"\"\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
/* Header comments for labeling functions, classes, test samples, etc */\n\n// Comments for explaining details.\n\n/**\n * Multiline\n * comments\n */\n
// Header comments for labeling functions, classes, test samples, etc\n\n// Comments for explaining details.\n\n// Multiline\n// comments\n
"},{"location":"chapter_preface/suggestions/#022-efficient-learning-via-animated-illustrations","title":"0.2.2 \u00a0 Efficient Learning via Animated Illustrations","text":"

Compared with text, videos and pictures have a higher density of information and are more structured, making them easier to understand. In this book, key and difficult concepts are mainly presented through animations and illustrations, with text serving as explanations and supplements.

When encountering content with animations or illustrations as shown in the Figure 0-2 , prioritize understanding the figure, with text as supplementary, integrating both for a comprehensive understanding.

Figure 0-2 \u00a0 Animated Illustration Example

"},{"location":"chapter_preface/suggestions/#023-deepen-understanding-through-coding-practice","title":"0.2.3 \u00a0 Deepen Understanding through Coding Practice","text":"

The source code of this book is hosted on the GitHub Repository. As shown in the Figure 0-3 , the source code comes with test examples and can be executed with just a single click.

If time permits, it's recommended to type out the code yourself. If pressed for time, at least read and run all the codes.

Compared to just reading code, writing code often yields more learning. Learning by doing is the real way to learn.

Figure 0-3 \u00a0 Running Code Example

Setting up to run the code involves three main steps.

Step 1: Install a local programming environment. Follow the tutorial in the appendix for installation, or skip this step if already installed.

Step 2: Clone or download the code repository. Visit the GitHub Repository.

If Git is installed, use the following command to clone the repository:

git clone https://github.com/krahets/hello-algo.git\n

Alternatively, you can also click the \"Download ZIP\" button at the location shown in the Figure 0-4 to directly download the code as a compressed ZIP file. Then, you can simply extract it locally.

Figure 0-4 \u00a0 Cloning Repository and Downloading Code

Step 3: Run the source code. As shown in the Figure 0-5 , for the code block labeled with the file name at the top, we can find the corresponding source code file in the codes folder of the repository. These files can be executed with a single click, which will help you save unnecessary debugging time and allow you to focus on learning.

Figure 0-5 \u00a0 Code Block and Corresponding Source Code File

"},{"location":"chapter_preface/suggestions/#024-learning-together-in-discussion","title":"0.2.4 \u00a0 Learning Together in Discussion","text":"

While reading this book, please don't skip over the points that you didn't learn. Feel free to post your questions in the comment section. We will be happy to answer them and can usually respond within two days.

As illustrated in the Figure 0-6 , each chapter features a comment section at the bottom. I encourage you to pay attention to these comments. They not only expose you to others' encountered problems, aiding in identifying knowledge gaps and sparking deeper contemplation, but also invite you to generously contribute by answering fellow readers' inquiries, sharing insights, and fostering mutual improvement.

Figure 0-6 \u00a0 Comment Section Example

"},{"location":"chapter_preface/suggestions/#025-algorithm-learning-path","title":"0.2.5 \u00a0 Algorithm Learning Path","text":"

Overall, the journey of mastering data structures and algorithms can be divided into three stages:

  1. Stage 1: Introduction to algorithms. We need to familiarize ourselves with the characteristics and usage of various data structures and learn about the principles, processes, uses, and efficiency of different algorithms.
  2. Stage 2: Practicing algorithm problems. It is recommended to start from popular problems, such as Sword for Offer and LeetCode Hot 100, and accumulate at least 100 questions to familiarize yourself with mainstream algorithmic problems. Forgetfulness can be a challenge when you start practicing, but rest assured that this is normal. We can follow the \"Ebbinghaus Forgetting Curve\" to review the questions, and usually after 3~5 rounds of repetitions, we will be able to memorize them.
  3. Stage 3: Building the knowledge system. In terms of learning, we can read algorithm column articles, solution frameworks, and algorithm textbooks to continuously enrich the knowledge system. In terms of practicing, we can try advanced strategies, such as categorizing by topic, multiple solutions for a single problem, and one solution for multiple problems, etc. Insights on these strategies can be found in various communities.

As shown in the Figure 0-7 , this book mainly covers \u201cStage 1,\u201d aiming to help you more efficiently embark on Stages 2 and 3.

Figure 0-7 \u00a0 Algorithm Learning Path

"},{"location":"chapter_preface/summary/","title":"0.3 \u00a0 Summary","text":"
  • The main audience of this book is beginners in algorithm. If you already have some basic knowledge, this book can help you systematically review your algorithm knowledge, and the source code in this book can also be used as a \"Coding Toolkit\".
  • The book consists of three main sections, Complexity Analysis, Data Structures, and Algorithms, covering most of the topics in the field.
  • For newcomers to algorithms, it is crucial to read an introductory book in the beginning stages to avoid many detours or common pitfalls.
  • Animations and figures within the book are usually used to introduce key points and difficult knowledge. These should be given more attention when reading the book.
  • Practice is the best way to learn programming. It is highly recommended that you run the source code and type in the code yourself.
  • Each chapter in the web version of this book features a discussion section, and you are welcome to share your questions and insights at any time.
"},{"location":"chapter_stack_and_queue/","title":"Chapter 5. \u00a0 Stack and Queue","text":"

Abstract

Stacks are like stacking cats, while queues are like cats lining up.

They respectively represent the logical relationships of Last-In-First-Out (LIFO) and First-In-First-Out (FIFO).

"},{"location":"chapter_stack_and_queue/#chapter-contents","title":"Chapter Contents","text":"
  • 5.1 \u00a0 Stack
  • 5.2 \u00a0 Queue
  • 5.3 \u00a0 Double-ended Queue
  • 5.4 \u00a0 Summary
"},{"location":"chapter_stack_and_queue/deque/","title":"5.3 \u00a0 Double-Ended Queue","text":"

In a regular queue, we can only delete elements from the head or add elements to the tail. As shown in the Figure 5-7 , a \"double-ended queue (deque)\" offers more flexibility, allowing the addition or removal of elements at both the head and the tail.

Figure 5-7 \u00a0 Operations in Double-Ended Queue

"},{"location":"chapter_stack_and_queue/deque/#531-common-operations-in-double-ended-queue","title":"5.3.1 \u00a0 Common Operations in Double-Ended Queue","text":"

The common operations in a double-ended queue are listed below, and the specific method names depend on the programming language used.

Table 5-3 \u00a0 Efficiency of Double-Ended Queue Operations

Method Name Description Time Complexity pushFirst() Add an element to the front \\(O(1)\\) pushLast() Add an element to the rear \\(O(1)\\) popFirst() Remove the front element \\(O(1)\\) popLast() Remove the rear element \\(O(1)\\) peekFirst() Access the front element \\(O(1)\\) peekLast() Access the rear element \\(O(1)\\)

Similarly, we can directly use the double-ended queue classes implemented in programming languages:

PythonC++JavaC#GoSwiftJSTSDartRustCZig deque.py
from collections import deque\n\n# Initialize the deque\ndeque: deque[int] = deque()\n\n# Enqueue elements\ndeque.append(2)      # Add to the rear\ndeque.append(5)\ndeque.append(4)\ndeque.appendleft(3)  # Add to the front\ndeque.appendleft(1)\n\n# Access elements\nfront: int = deque[0]  # Front element\nrear: int = deque[-1]  # Rear element\n\n# Dequeue elements\npop_front: int = deque.popleft()  # Front element dequeued\npop_rear: int = deque.pop()       # Rear element dequeued\n\n# Get the length of the deque\nsize: int = len(deque)\n\n# Check if the deque is empty\nis_empty: bool = len(deque) == 0\n
deque.cpp
/* Initialize the deque */\ndeque<int> deque;\n\n/* Enqueue elements */\ndeque.push_back(2);   // Add to the rear\ndeque.push_back(5);\ndeque.push_back(4);\ndeque.push_front(3);  // Add to the front\ndeque.push_front(1);\n\n/* Access elements */\nint front = deque.front(); // Front element\nint back = deque.back();   // Rear element\n\n/* Dequeue elements */\ndeque.pop_front();  // Front element dequeued\ndeque.pop_back();   // Rear element dequeued\n\n/* Get the length of the deque */\nint size = deque.size();\n\n/* Check if the deque is empty */\nbool empty = deque.empty();\n
deque.java
/* Initialize the deque */\nDeque<Integer> deque = new LinkedList<>();\n\n/* Enqueue elements */\ndeque.offerLast(2);   // Add to the rear\ndeque.offerLast(5);\ndeque.offerLast(4);\ndeque.offerFirst(3);  // Add to the front\ndeque.offerFirst(1);\n\n/* Access elements */\nint peekFirst = deque.peekFirst();  // Front element\nint peekLast = deque.peekLast();    // Rear element\n\n/* Dequeue elements */\nint popFirst = deque.pollFirst();  // Front element dequeued\nint popLast = deque.pollLast();    // Rear element dequeued\n\n/* Get the length of the deque */\nint size = deque.size();\n\n/* Check if the deque is empty */\nboolean isEmpty = deque.isEmpty();\n
deque.cs
/* Initialize the deque */\n// In C#, LinkedList is used as a deque\nLinkedList<int> deque = new();\n\n/* Enqueue elements */\ndeque.AddLast(2);   // Add to the rear\ndeque.AddLast(5);\ndeque.AddLast(4);\ndeque.AddFirst(3);  // Add to the front\ndeque.AddFirst(1);\n\n/* Access elements */\nint peekFirst = deque.First.Value;  // Front element\nint peekLast = deque.Last.Value;    // Rear element\n\n/* Dequeue elements */\ndeque.RemoveFirst();  // Front element dequeued\ndeque.RemoveLast();   // Rear element dequeued\n\n/* Get the length of the deque */\nint size = deque.Count;\n\n/* Check if the deque is empty */\nbool isEmpty = deque.Count == 0;\n
deque_test.go
/* Initialize the deque */\n// In Go, use list as a deque\ndeque := list.New()\n\n/* Enqueue elements */\ndeque.PushBack(2)      // Add to the rear\ndeque.PushBack(5)\ndeque.PushBack(4)\ndeque.PushFront(3)     // Add to the front\ndeque.PushFront(1)\n\n/* Access elements */\nfront := deque.Front() // Front element\nrear := deque.Back()   // Rear element\n\n/* Dequeue elements */\ndeque.Remove(front)    // Front element dequeued\ndeque.Remove(rear)     // Rear element dequeued\n\n/* Get the length of the deque */\nsize := deque.Len()\n\n/* Check if the deque is empty */\nisEmpty := deque.Len() == 0\n
deque.swift
/* Initialize the deque */\n// Swift does not have a built-in deque class, so Array can be used as a deque\nvar deque: [Int] = []\n\n/* Enqueue elements */\ndeque.append(2) // Add to the rear\ndeque.append(5)\ndeque.append(4)\ndeque.insert(3, at: 0) // Add to the front\ndeque.insert(1, at: 0)\n\n/* Access elements */\nlet peekFirst = deque.first! // Front element\nlet peekLast = deque.last!   // Rear element\n\n/* Dequeue elements */\n// Using Array, popFirst has a complexity of O(n)\nlet popFirst = deque.removeFirst() // Front element dequeued\nlet popLast = deque.removeLast()   // Rear element dequeued\n\n/* Get the length of the deque */\nlet size = deque.count\n\n/* Check if the deque is empty */\nlet isEmpty = deque.isEmpty\n
deque.js
/* Initialize the deque */\n// JavaScript does not have a built-in deque, so Array is used as a deque\nconst deque = [];\n\n/* Enqueue elements */\ndeque.push(2);\ndeque.push(5);\ndeque.push(4);\n// Note that unshift() has a time complexity of O(n) as it's an array\ndeque.unshift(3);\ndeque.unshift(1);\n\n/* Access elements */\nconst peekFirst = deque[0]; // Front element\nconst peekLast = deque[deque.length - 1]; // Rear element\n\n/* Dequeue elements */\n// Note that shift() has a time complexity of O(n) as it's an array\nconst popFront = deque.shift(); // Front element dequeued\nconst popBack = deque.pop();    // Rear element dequeued\n\n/* Get the length of the deque */\nconst size = deque.length;\n\n/* Check if the deque is empty */\nconst isEmpty = size === 0;\n
deque.ts
/* Initialize the deque */\n// TypeScript does not have a built-in deque, so Array is used as a deque\nconst deque: number[] = [];\n\n/* Enqueue elements */\ndeque.push(2);\ndeque.push(5);\ndeque.push(4);\n// Note that unshift() has a time complexity of O(n) as it's an array\ndeque.unshift(3);\ndeque.unshift(1);\n\n/* Access elements */\nconst peekFirst: number = deque[0]; // Front element\nconst peekLast: number = deque[deque.length - 1]; // Rear element\n\n/* Dequeue elements */\n// Note that shift() has a time complexity of O(n) as it's an array\nconst popFront: number = deque.shift() as number; // Front element dequeued\nconst popBack: number = deque.pop() as number;    // Rear element dequeued\n\n/* Get the length of the deque */\nconst size: number = deque.length;\n\n/* Check if the deque is empty */\nconst isEmpty: boolean = size === 0;\n
deque.dart
/* Initialize the deque */\n// In Dart, Queue is defined as a deque\nQueue<int> deque = Queue<int>();\n\n/* Enqueue elements */\ndeque.addLast(2);  // Add to the rear\ndeque.addLast(5);\ndeque.addLast(4);\ndeque.addFirst(3); // Add to the front\ndeque.addFirst(1);\n\n/* Access elements */\nint peekFirst = deque.first; // Front element\nint peekLast = deque.last;   // Rear element\n\n/* Dequeue elements */\nint popFirst = deque.removeFirst(); // Front element dequeued\nint popLast = deque.removeLast();   // Rear element dequeued\n\n/* Get the length of the deque */\nint size = deque.length;\n\n/* Check if the deque is empty */\nbool isEmpty = deque.isEmpty;\n
deque.rs
/* Initialize the deque */\nlet mut deque: VecDeque<u32> = VecDeque::new();\n\n/* Enqueue elements */\ndeque.push_back(2);  // Add to the rear\ndeque.push_back(5);\ndeque.push_back(4);\ndeque.push_front(3); // Add to the front\ndeque.push_front(1);\n\n/* Access elements */\nif let Some(front) = deque.front() { // Front element\n}\nif let Some(rear) = deque.back() {   // Rear element\n}\n\n/* Dequeue elements */\nif let Some(pop_front) = deque.pop_front() { // Front element dequeued\n}\nif let Some(pop_rear) = deque.pop_back() {   // Rear element dequeued\n}\n\n/* Get the length of the deque */\nlet size = deque.len();\n\n/* Check if the deque is empty */\nlet is_empty = deque.is_empty();\n
deque.c
// C does not provide a built-in deque\n
deque.zig
\n
Visualizing Code

Full Screen >

"},{"location":"chapter_stack_and_queue/deque/#532-implementing-a-double-ended-queue","title":"5.3.2 \u00a0 Implementing a Double-Ended Queue *","text":"

The implementation of a double-ended queue is similar to that of a regular queue, with the choice of either linked lists or arrays as the underlying data structure.

"},{"location":"chapter_stack_and_queue/deque/#1-implementation-based-on-doubly-linked-list","title":"1. \u00a0 Implementation Based on Doubly Linked List","text":"

Recall from the previous section that we used a regular singly linked list to implement a queue, as it conveniently allows for deleting the head node (corresponding to dequeue operation) and adding new nodes after the tail node (corresponding to enqueue operation).

For a double-ended queue, both the head and the tail can perform enqueue and dequeue operations. In other words, a double-ended queue needs to implement another symmetric direction of operations. For this, we use a \"doubly linked list\" as the underlying data structure of the double-ended queue.

As shown in the Figure 5-8 , we treat the head and tail nodes of the doubly linked list as the front and rear of the double-ended queue, respectively, and implement the functionality to add and remove nodes at both ends.

LinkedListDequepushLast()pushFirst()popLast()popFirst()

Figure 5-8 \u00a0 Implementing Double-Ended Queue with Doubly Linked List for Enqueue and Dequeue Operations

The implementation code is as follows:

PythonC++JavaC#GoSwiftJSTSDartRustCZig linkedlist_deque.py
class ListNode:\n    \"\"\"\u53cc\u5411\u94fe\u8868\u8282\u70b9\"\"\"\n\n    def __init__(self, val: int):\n        \"\"\"\u6784\u9020\u65b9\u6cd5\"\"\"\n        self.val: int = val\n        self.next: ListNode | None = None  # \u540e\u7ee7\u8282\u70b9\u5f15\u7528\n        self.prev: ListNode | None = None  # \u524d\u9a71\u8282\u70b9\u5f15\u7528\n\nclass LinkedListDeque:\n    \"\"\"\u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217\"\"\"\n\n    def __init__(self):\n        \"\"\"\u6784\u9020\u65b9\u6cd5\"\"\"\n        self._front: ListNode | None = None  # \u5934\u8282\u70b9 front\n        self._rear: ListNode | None = None  # \u5c3e\u8282\u70b9 rear\n        self._size: int = 0  # \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n    def size(self) -> int:\n        \"\"\"\u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\"\"\"\n        return self._size\n\n    def is_empty(self) -> bool:\n        \"\"\"\u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a\"\"\"\n        return self.size() == 0\n\n    def push(self, num: int, is_front: bool):\n        \"\"\"\u5165\u961f\u64cd\u4f5c\"\"\"\n        node = ListNode(num)\n        # \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if self.is_empty():\n            self._front = self._rear = node\n        # \u961f\u9996\u5165\u961f\u64cd\u4f5c\n        elif is_front:\n            # \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n            self._front.prev = node\n            node.next = self._front\n            self._front = node  # \u66f4\u65b0\u5934\u8282\u70b9\n        # \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n        else:\n            # \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n            self._rear.next = node\n            node.prev = self._rear\n            self._rear = node  # \u66f4\u65b0\u5c3e\u8282\u70b9\n        self._size += 1  # \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n\n    def push_first(self, num: int):\n        \"\"\"\u961f\u9996\u5165\u961f\"\"\"\n        self.push(num, True)\n\n    def push_last(self, num: int):\n        \"\"\"\u961f\u5c3e\u5165\u961f\"\"\"\n        self.push(num, False)\n\n    def pop(self, is_front: bool) -> int:\n        \"\"\"\u51fa\u961f\u64cd\u4f5c\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\")\n        # \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n        if is_front:\n            val: int = self._front.val  # \u6682\u5b58\u5934\u8282\u70b9\u503c\n            # \u5220\u9664\u5934\u8282\u70b9\n            fnext: ListNode | None = self._front.next\n            if fnext != None:\n                fnext.prev = None\n                self._front.next = None\n            self._front = fnext  # \u66f4\u65b0\u5934\u8282\u70b9\n        # \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n        else:\n            val: int = self._rear.val  # \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n            # \u5220\u9664\u5c3e\u8282\u70b9\n            rprev: ListNode | None = self._rear.prev\n            if rprev != None:\n                rprev.next = None\n                self._rear.prev = None\n            self._rear = rprev  # \u66f4\u65b0\u5c3e\u8282\u70b9\n        self._size -= 1  # \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n        return val\n\n    def pop_first(self) -> int:\n        \"\"\"\u961f\u9996\u51fa\u961f\"\"\"\n        return self.pop(True)\n\n    def pop_last(self) -> int:\n        \"\"\"\u961f\u5c3e\u51fa\u961f\"\"\"\n        return self.pop(False)\n\n    def peek_first(self) -> int:\n        \"\"\"\u8bbf\u95ee\u961f\u9996\u5143\u7d20\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\")\n        return self._front.val\n\n    def peek_last(self) -> int:\n        \"\"\"\u8bbf\u95ee\u961f\u5c3e\u5143\u7d20\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\")\n        return self._rear.val\n\n    def to_array(self) -> list[int]:\n        \"\"\"\u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370\"\"\"\n        node = self._front\n        res = [0] * self.size()\n        for i in range(self.size()):\n            res[i] = node.val\n            node = node.next\n        return res\n
linkedlist_deque.cpp
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\nstruct DoublyListNode {\n    int val;              // \u8282\u70b9\u503c\n    DoublyListNode *next; // \u540e\u7ee7\u8282\u70b9\u6307\u9488\n    DoublyListNode *prev; // \u524d\u9a71\u8282\u70b9\u6307\u9488\n    DoublyListNode(int val) : val(val), prev(nullptr), next(nullptr) {\n    }\n};\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\nclass LinkedListDeque {\n  private:\n    DoublyListNode *front, *rear; // \u5934\u8282\u70b9 front \uff0c\u5c3e\u8282\u70b9 rear\n    int queSize = 0;              // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n  public:\n    /* \u6784\u9020\u65b9\u6cd5 */\n    LinkedListDeque() : front(nullptr), rear(nullptr) {\n    }\n\n    /* \u6790\u6784\u65b9\u6cd5 */\n    ~LinkedListDeque() {\n        // \u904d\u5386\u94fe\u8868\u5220\u9664\u8282\u70b9\uff0c\u91ca\u653e\u5185\u5b58\n        DoublyListNode *pre, *cur = front;\n        while (cur != nullptr) {\n            pre = cur;\n            cur = cur->next;\n            delete pre;\n        }\n    }\n\n    /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6 */\n    int size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    bool isEmpty() {\n        return size() == 0;\n    }\n\n    /* \u5165\u961f\u64cd\u4f5c */\n    void push(int num, bool isFront) {\n        DoublyListNode *node = new DoublyListNode(num);\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if (isEmpty())\n            front = rear = node;\n        // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n        else if (isFront) {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n            front->prev = node;\n            node->next = front;\n            front = node; // \u66f4\u65b0\u5934\u8282\u70b9\n        // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n        } else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n            rear->next = node;\n            node->prev = rear;\n            rear = node; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        queSize++; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n    }\n\n    /* \u961f\u9996\u5165\u961f */\n    void pushFirst(int num) {\n        push(num, true);\n    }\n\n    /* \u961f\u5c3e\u5165\u961f */\n    void pushLast(int num) {\n        push(num, false);\n    }\n\n    /* \u51fa\u961f\u64cd\u4f5c */\n    int pop(bool isFront) {\n        if (isEmpty())\n            throw out_of_range(\"\u961f\u5217\u4e3a\u7a7a\");\n        int val;\n        // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n        if (isFront) {\n            val = front->val; // \u6682\u5b58\u5934\u8282\u70b9\u503c\n            // \u5220\u9664\u5934\u8282\u70b9\n            DoublyListNode *fNext = front->next;\n            if (fNext != nullptr) {\n                fNext->prev = nullptr;\n                front->next = nullptr;\n                delete front;\n            }\n            front = fNext; // \u66f4\u65b0\u5934\u8282\u70b9\n        // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n        } else {\n            val = rear->val; // \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n            // \u5220\u9664\u5c3e\u8282\u70b9\n            DoublyListNode *rPrev = rear->prev;\n            if (rPrev != nullptr) {\n                rPrev->next = nullptr;\n                rear->prev = nullptr;\n                delete rear;\n            }\n            rear = rPrev; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        queSize--; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n        return val;\n    }\n\n    /* \u961f\u9996\u51fa\u961f */\n    int popFirst() {\n        return pop(true);\n    }\n\n    /* \u961f\u5c3e\u51fa\u961f */\n    int popLast() {\n        return pop(false);\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    int peekFirst() {\n        if (isEmpty())\n            throw out_of_range(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\");\n        return front->val;\n    }\n\n    /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n    int peekLast() {\n        if (isEmpty())\n            throw out_of_range(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\");\n        return rear->val;\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370 */\n    vector<int> toVector() {\n        DoublyListNode *node = front;\n        vector<int> res(size());\n        for (int i = 0; i < res.size(); i++) {\n            res[i] = node->val;\n            node = node->next;\n        }\n        return res;\n    }\n};\n
linkedlist_deque.java
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\nclass ListNode {\n    int val; // \u8282\u70b9\u503c\n    ListNode next; // \u540e\u7ee7\u8282\u70b9\u5f15\u7528\n    ListNode prev; // \u524d\u9a71\u8282\u70b9\u5f15\u7528\n\n    ListNode(int val) {\n        this.val = val;\n        prev = next = null;\n    }\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\nclass LinkedListDeque {\n    private ListNode front, rear; // \u5934\u8282\u70b9 front \uff0c\u5c3e\u8282\u70b9 rear\n    private int queSize = 0; // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n    public LinkedListDeque() {\n        front = rear = null;\n    }\n\n    /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6 */\n    public int size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /* \u5165\u961f\u64cd\u4f5c */\n    private void push(int num, boolean isFront) {\n        ListNode node = new ListNode(num);\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if (isEmpty())\n            front = rear = node;\n        // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n        else if (isFront) {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n            front.prev = node;\n            node.next = front;\n            front = node; // \u66f4\u65b0\u5934\u8282\u70b9\n        // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n        } else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n            rear.next = node;\n            node.prev = rear;\n            rear = node; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        queSize++; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n    }\n\n    /* \u961f\u9996\u5165\u961f */\n    public void pushFirst(int num) {\n        push(num, true);\n    }\n\n    /* \u961f\u5c3e\u5165\u961f */\n    public void pushLast(int num) {\n        push(num, false);\n    }\n\n    /* \u51fa\u961f\u64cd\u4f5c */\n    private int pop(boolean isFront) {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        int val;\n        // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n        if (isFront) {\n            val = front.val; // \u6682\u5b58\u5934\u8282\u70b9\u503c\n            // \u5220\u9664\u5934\u8282\u70b9\n            ListNode fNext = front.next;\n            if (fNext != null) {\n                fNext.prev = null;\n                front.next = null;\n            }\n            front = fNext; // \u66f4\u65b0\u5934\u8282\u70b9\n        // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n        } else {\n            val = rear.val; // \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n            // \u5220\u9664\u5c3e\u8282\u70b9\n            ListNode rPrev = rear.prev;\n            if (rPrev != null) {\n                rPrev.next = null;\n                rear.prev = null;\n            }\n            rear = rPrev; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        queSize--; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n        return val;\n    }\n\n    /* \u961f\u9996\u51fa\u961f */\n    public int popFirst() {\n        return pop(true);\n    }\n\n    /* \u961f\u5c3e\u51fa\u961f */\n    public int popLast() {\n        return pop(false);\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    public int peekFirst() {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        return front.val;\n    }\n\n    /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n    public int peekLast() {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        return rear.val;\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370 */\n    public int[] toArray() {\n        ListNode node = front;\n        int[] res = new int[size()];\n        for (int i = 0; i < res.length; i++) {\n            res[i] = node.val;\n            node = node.next;\n        }\n        return res;\n    }\n}\n
linkedlist_deque.cs
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\nclass ListNode(int val) {\n    public int val = val;       // \u8282\u70b9\u503c\n    public ListNode? next = null; // \u540e\u7ee7\u8282\u70b9\u5f15\u7528\n    public ListNode? prev = null; // \u524d\u9a71\u8282\u70b9\u5f15\u7528\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\nclass LinkedListDeque {\n    ListNode? front, rear; // \u5934\u8282\u70b9 front, \u5c3e\u8282\u70b9 rear\n    int queSize = 0;      // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n    public LinkedListDeque() {\n        front = null;\n        rear = null;\n    }\n\n    /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6 */\n    public int Size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    public bool IsEmpty() {\n        return Size() == 0;\n    }\n\n    /* \u5165\u961f\u64cd\u4f5c */\n    void Push(int num, bool isFront) {\n        ListNode node = new(num);\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if (IsEmpty()) {\n            front = node;\n            rear = node;\n        }\n        // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n        else if (isFront) {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n            front!.prev = node;\n            node.next = front;\n            front = node; // \u66f4\u65b0\u5934\u8282\u70b9                           \n        }\n        // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n        else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n            rear!.next = node;\n            node.prev = rear;\n            rear = node;  // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n\n        queSize++; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n    }\n\n    /* \u961f\u9996\u5165\u961f */\n    public void PushFirst(int num) {\n        Push(num, true);\n    }\n\n    /* \u961f\u5c3e\u5165\u961f */\n    public void PushLast(int num) {\n        Push(num, false);\n    }\n\n    /* \u51fa\u961f\u64cd\u4f5c */\n    int? Pop(bool isFront) {\n        if (IsEmpty())\n            throw new Exception();\n        int? val;\n        // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n        if (isFront) {\n            val = front?.val; // \u6682\u5b58\u5934\u8282\u70b9\u503c\n            // \u5220\u9664\u5934\u8282\u70b9\n            ListNode? fNext = front?.next;\n            if (fNext != null) {\n                fNext.prev = null;\n                front!.next = null;\n            }\n            front = fNext;   // \u66f4\u65b0\u5934\u8282\u70b9\n        }\n        // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n        else {\n            val = rear?.val;  // \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n            // \u5220\u9664\u5c3e\u8282\u70b9\n            ListNode? rPrev = rear?.prev;\n            if (rPrev != null) {\n                rPrev.next = null;\n                rear!.prev = null;\n            }\n            rear = rPrev;    // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n\n        queSize--; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n        return val;\n    }\n\n    /* \u961f\u9996\u51fa\u961f */\n    public int? PopFirst() {\n        return Pop(true);\n    }\n\n    /* \u961f\u5c3e\u51fa\u961f */\n    public int? PopLast() {\n        return Pop(false);\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    public int? PeekFirst() {\n        if (IsEmpty())\n            throw new Exception();\n        return front?.val;\n    }\n\n    /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n    public int? PeekLast() {\n        if (IsEmpty())\n            throw new Exception();\n        return rear?.val;\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370 */\n    public int?[] ToArray() {\n        ListNode? node = front;\n        int?[] res = new int?[Size()];\n        for (int i = 0; i < res.Length; i++) {\n            res[i] = node?.val;\n            node = node?.next;\n        }\n\n        return res;\n    }\n}\n
linkedlist_deque.go
/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\ntype linkedListDeque struct {\n    // \u4f7f\u7528\u5185\u7f6e\u5305 list\n    data *list.List\n}\n\n/* \u521d\u59cb\u5316\u53cc\u7aef\u961f\u5217 */\nfunc newLinkedListDeque() *linkedListDeque {\n    return &linkedListDeque{\n        data: list.New(),\n    }\n}\n\n/* \u961f\u9996\u5143\u7d20\u5165\u961f */\nfunc (s *linkedListDeque) pushFirst(value any) {\n    s.data.PushFront(value)\n}\n\n/* \u961f\u5c3e\u5143\u7d20\u5165\u961f */\nfunc (s *linkedListDeque) pushLast(value any) {\n    s.data.PushBack(value)\n}\n\n/* \u961f\u9996\u5143\u7d20\u51fa\u961f */\nfunc (s *linkedListDeque) popFirst() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Front()\n    s.data.Remove(e)\n    return e.Value\n}\n\n/* \u961f\u5c3e\u5143\u7d20\u51fa\u961f */\nfunc (s *linkedListDeque) popLast() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Back()\n    s.data.Remove(e)\n    return e.Value\n}\n\n/* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\nfunc (s *linkedListDeque) peekFirst() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Front()\n    return e.Value\n}\n\n/* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\nfunc (s *linkedListDeque) peekLast() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Back()\n    return e.Value\n}\n\n/* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\nfunc (s *linkedListDeque) size() int {\n    return s.data.Len()\n}\n\n/* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\nfunc (s *linkedListDeque) isEmpty() bool {\n    return s.data.Len() == 0\n}\n\n/* \u83b7\u53d6 List \u7528\u4e8e\u6253\u5370 */\nfunc (s *linkedListDeque) toList() *list.List {\n    return s.data\n}\n
linkedlist_deque.swift
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\nclass ListNode {\n    var val: Int // \u8282\u70b9\u503c\n    var next: ListNode? // \u540e\u7ee7\u8282\u70b9\u5f15\u7528\n    weak var prev: ListNode? // \u524d\u9a71\u8282\u70b9\u5f15\u7528\n\n    init(val: Int) {\n        self.val = val\n    }\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\nclass LinkedListDeque {\n    private var front: ListNode? // \u5934\u8282\u70b9 front\n    private var rear: ListNode? // \u5c3e\u8282\u70b9 rear\n    private var queSize: Int // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n    init() {\n        queSize = 0\n    }\n\n    /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6 */\n    func size() -> Int {\n        queSize\n    }\n\n    /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    func isEmpty() -> Bool {\n        size() == 0\n    }\n\n    /* \u5165\u961f\u64cd\u4f5c */\n    private func push(num: Int, isFront: Bool) {\n        let node = ListNode(val: num)\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if isEmpty() {\n            front = node\n            rear = node\n        }\n        // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n        else if isFront {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n            front?.prev = node\n            node.next = front\n            front = node // \u66f4\u65b0\u5934\u8282\u70b9\n        }\n        // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n        else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n            rear?.next = node\n            node.prev = rear\n            rear = node // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        queSize += 1 // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n    }\n\n    /* \u961f\u9996\u5165\u961f */\n    func pushFirst(num: Int) {\n        push(num: num, isFront: true)\n    }\n\n    /* \u961f\u5c3e\u5165\u961f */\n    func pushLast(num: Int) {\n        push(num: num, isFront: false)\n    }\n\n    /* \u51fa\u961f\u64cd\u4f5c */\n    private func pop(isFront: Bool) -> Int {\n        if isEmpty() {\n            fatalError(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\")\n        }\n        let val: Int\n        // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n        if isFront {\n            val = front!.val // \u6682\u5b58\u5934\u8282\u70b9\u503c\n            // \u5220\u9664\u5934\u8282\u70b9\n            let fNext = front?.next\n            if fNext != nil {\n                fNext?.prev = nil\n                front?.next = nil\n            }\n            front = fNext // \u66f4\u65b0\u5934\u8282\u70b9\n        }\n        // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n        else {\n            val = rear!.val // \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n            // \u5220\u9664\u5c3e\u8282\u70b9\n            let rPrev = rear?.prev\n            if rPrev != nil {\n                rPrev?.next = nil\n                rear?.prev = nil\n            }\n            rear = rPrev // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        queSize -= 1 // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n        return val\n    }\n\n    /* \u961f\u9996\u51fa\u961f */\n    func popFirst() -> Int {\n        pop(isFront: true)\n    }\n\n    /* \u961f\u5c3e\u51fa\u961f */\n    func popLast() -> Int {\n        pop(isFront: false)\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    func peekFirst() -> Int? {\n        isEmpty() ? nil : front?.val\n    }\n\n    /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n    func peekLast() -> Int? {\n        isEmpty() ? nil : rear?.val\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370 */\n    func toArray() -> [Int] {\n        var node = front\n        var res = Array(repeating: 0, count: size())\n        for i in res.indices {\n            res[i] = node!.val\n            node = node?.next\n        }\n        return res\n    }\n}\n
linkedlist_deque.js
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\nclass ListNode {\n    prev; // \u524d\u9a71\u8282\u70b9\u5f15\u7528 (\u6307\u9488)\n    next; // \u540e\u7ee7\u8282\u70b9\u5f15\u7528 (\u6307\u9488)\n    val; // \u8282\u70b9\u503c\n\n    constructor(val) {\n        this.val = val;\n        this.next = null;\n        this.prev = null;\n    }\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\nclass LinkedListDeque {\n    #front; // \u5934\u8282\u70b9 front\n    #rear; // \u5c3e\u8282\u70b9 rear\n    #queSize; // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n    constructor() {\n        this.#front = null;\n        this.#rear = null;\n        this.#queSize = 0;\n    }\n\n    /* \u961f\u5c3e\u5165\u961f\u64cd\u4f5c */\n    pushLast(val) {\n        const node = new ListNode(val);\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if (this.#queSize === 0) {\n            this.#front = node;\n            this.#rear = node;\n        } else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n            this.#rear.next = node;\n            node.prev = this.#rear;\n            this.#rear = node; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        this.#queSize++;\n    }\n\n    /* \u961f\u9996\u5165\u961f\u64cd\u4f5c */\n    pushFirst(val) {\n        const node = new ListNode(val);\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if (this.#queSize === 0) {\n            this.#front = node;\n            this.#rear = node;\n        } else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n            this.#front.prev = node;\n            node.next = this.#front;\n            this.#front = node; // \u66f4\u65b0\u5934\u8282\u70b9\n        }\n        this.#queSize++;\n    }\n\n    /* \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c */\n    popLast() {\n        if (this.#queSize === 0) {\n            return null;\n        }\n        const value = this.#rear.val; // \u5b58\u50a8\u5c3e\u8282\u70b9\u503c\n        // \u5220\u9664\u5c3e\u8282\u70b9\n        let temp = this.#rear.prev;\n        if (temp !== null) {\n            temp.next = null;\n            this.#rear.prev = null;\n        }\n        this.#rear = temp; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        this.#queSize--;\n        return value;\n    }\n\n    /* \u961f\u9996\u51fa\u961f\u64cd\u4f5c */\n    popFirst() {\n        if (this.#queSize === 0) {\n            return null;\n        }\n        const value = this.#front.val; // \u5b58\u50a8\u5c3e\u8282\u70b9\u503c\n        // \u5220\u9664\u5934\u8282\u70b9\n        let temp = this.#front.next;\n        if (temp !== null) {\n            temp.prev = null;\n            this.#front.next = null;\n        }\n        this.#front = temp; // \u66f4\u65b0\u5934\u8282\u70b9\n        this.#queSize--;\n        return value;\n    }\n\n    /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n    peekLast() {\n        return this.#queSize === 0 ? null : this.#rear.val;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    peekFirst() {\n        return this.#queSize === 0 ? null : this.#front.val;\n    }\n\n    /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6 */\n    size() {\n        return this.#queSize;\n    }\n\n    /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    isEmpty() {\n        return this.#queSize === 0;\n    }\n\n    /* \u6253\u5370\u53cc\u5411\u961f\u5217 */\n    print() {\n        const arr = [];\n        let temp = this.#front;\n        while (temp !== null) {\n            arr.push(temp.val);\n            temp = temp.next;\n        }\n        console.log('[' + arr.join(', ') + ']');\n    }\n}\n
linkedlist_deque.ts
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\nclass ListNode {\n    prev: ListNode; // \u524d\u9a71\u8282\u70b9\u5f15\u7528 (\u6307\u9488)\n    next: ListNode; // \u540e\u7ee7\u8282\u70b9\u5f15\u7528 (\u6307\u9488)\n    val: number; // \u8282\u70b9\u503c\n\n    constructor(val: number) {\n        this.val = val;\n        this.next = null;\n        this.prev = null;\n    }\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\nclass LinkedListDeque {\n    private front: ListNode; // \u5934\u8282\u70b9 front\n    private rear: ListNode; // \u5c3e\u8282\u70b9 rear\n    private queSize: number; // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n    constructor() {\n        this.front = null;\n        this.rear = null;\n        this.queSize = 0;\n    }\n\n    /* \u961f\u5c3e\u5165\u961f\u64cd\u4f5c */\n    pushLast(val: number): void {\n        const node: ListNode = new ListNode(val);\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if (this.queSize === 0) {\n            this.front = node;\n            this.rear = node;\n        } else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n            this.rear.next = node;\n            node.prev = this.rear;\n            this.rear = node; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        }\n        this.queSize++;\n    }\n\n    /* \u961f\u9996\u5165\u961f\u64cd\u4f5c */\n    pushFirst(val: number): void {\n        const node: ListNode = new ListNode(val);\n        // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n        if (this.queSize === 0) {\n            this.front = node;\n            this.rear = node;\n        } else {\n            // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n            this.front.prev = node;\n            node.next = this.front;\n            this.front = node; // \u66f4\u65b0\u5934\u8282\u70b9\n        }\n        this.queSize++;\n    }\n\n    /* \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c */\n    popLast(): number {\n        if (this.queSize === 0) {\n            return null;\n        }\n        const value: number = this.rear.val; // \u5b58\u50a8\u5c3e\u8282\u70b9\u503c\n        // \u5220\u9664\u5c3e\u8282\u70b9\n        let temp: ListNode = this.rear.prev;\n        if (temp !== null) {\n            temp.next = null;\n            this.rear.prev = null;\n        }\n        this.rear = temp; // \u66f4\u65b0\u5c3e\u8282\u70b9\n        this.queSize--;\n        return value;\n    }\n\n    /* \u961f\u9996\u51fa\u961f\u64cd\u4f5c */\n    popFirst(): number {\n        if (this.queSize === 0) {\n            return null;\n        }\n        const value: number = this.front.val; // \u5b58\u50a8\u5c3e\u8282\u70b9\u503c\n        // \u5220\u9664\u5934\u8282\u70b9\n        let temp: ListNode = this.front.next;\n        if (temp !== null) {\n            temp.prev = null;\n            this.front.next = null;\n        }\n        this.front = temp; // \u66f4\u65b0\u5934\u8282\u70b9\n        this.queSize--;\n        return value;\n    }\n\n    /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n    peekLast(): number {\n        return this.queSize === 0 ? null : this.rear.val;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    peekFirst(): number {\n        return this.queSize === 0 ? null : this.front.val;\n    }\n\n    /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6 */\n    size(): number {\n        return this.queSize;\n    }\n\n    /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    isEmpty(): boolean {\n        return this.queSize === 0;\n    }\n\n    /* \u6253\u5370\u53cc\u5411\u961f\u5217 */\n    print(): void {\n        const arr: number[] = [];\n        let temp: ListNode = this.front;\n        while (temp !== null) {\n            arr.push(temp.val);\n            temp = temp.next;\n        }\n        console.log('[' + arr.join(', ') + ']');\n    }\n}\n
linkedlist_deque.dart
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\nclass ListNode {\n  int val; // \u8282\u70b9\u503c\n  ListNode? next; // \u540e\u7ee7\u8282\u70b9\u5f15\u7528\n  ListNode? prev; // \u524d\u9a71\u8282\u70b9\u5f15\u7528\n\n  ListNode(this.val, {this.next, this.prev});\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u5bf9\u5217 */\nclass LinkedListDeque {\n  late ListNode? _front; // \u5934\u8282\u70b9 _front\n  late ListNode? _rear; // \u5c3e\u8282\u70b9 _rear\n  int _queSize = 0; // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n\n  LinkedListDeque() {\n    this._front = null;\n    this._rear = null;\n  }\n\n  /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u957f\u5ea6 */\n  int size() {\n    return this._queSize;\n  }\n\n  /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n  bool isEmpty() {\n    return size() == 0;\n  }\n\n  /* \u5165\u961f\u64cd\u4f5c */\n  void push(int _num, bool isFront) {\n    final ListNode node = ListNode(_num);\n    if (isEmpty()) {\n      // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 _front \u548c _rear \u90fd\u6307\u5411 node\n      _front = _rear = node;\n    } else if (isFront) {\n      // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n      // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n      _front!.prev = node;\n      node.next = _front;\n      _front = node; // \u66f4\u65b0\u5934\u8282\u70b9\n    } else {\n      // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n      // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n      _rear!.next = node;\n      node.prev = _rear;\n      _rear = node; // \u66f4\u65b0\u5c3e\u8282\u70b9\n    }\n    _queSize++; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n  }\n\n  /* \u961f\u9996\u5165\u961f */\n  void pushFirst(int _num) {\n    push(_num, true);\n  }\n\n  /* \u961f\u5c3e\u5165\u961f */\n  void pushLast(int _num) {\n    push(_num, false);\n  }\n\n  /* \u51fa\u961f\u64cd\u4f5c */\n  int? pop(bool isFront) {\n    // \u82e5\u961f\u5217\u4e3a\u7a7a\uff0c\u76f4\u63a5\u8fd4\u56de null\n    if (isEmpty()) {\n      return null;\n    }\n    final int val;\n    if (isFront) {\n      // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n      val = _front!.val; // \u6682\u5b58\u5934\u8282\u70b9\u503c\n      // \u5220\u9664\u5934\u8282\u70b9\n      ListNode? fNext = _front!.next;\n      if (fNext != null) {\n        fNext.prev = null;\n        _front!.next = null;\n      }\n      _front = fNext; // \u66f4\u65b0\u5934\u8282\u70b9\n    } else {\n      // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n      val = _rear!.val; // \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n      // \u5220\u9664\u5c3e\u8282\u70b9\n      ListNode? rPrev = _rear!.prev;\n      if (rPrev != null) {\n        rPrev.next = null;\n        _rear!.prev = null;\n      }\n      _rear = rPrev; // \u66f4\u65b0\u5c3e\u8282\u70b9\n    }\n    _queSize--; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n    return val;\n  }\n\n  /* \u961f\u9996\u51fa\u961f */\n  int? popFirst() {\n    return pop(true);\n  }\n\n  /* \u961f\u5c3e\u51fa\u961f */\n  int? popLast() {\n    return pop(false);\n  }\n\n  /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n  int? peekFirst() {\n    return _front?.val;\n  }\n\n  /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n  int? peekLast() {\n    return _rear?.val;\n  }\n\n  /* \u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370 */\n  List<int> toArray() {\n    ListNode? node = _front;\n    final List<int> res = [];\n    for (int i = 0; i < _queSize; i++) {\n      res.add(node!.val);\n      node = node.next;\n    }\n    return res;\n  }\n}\n
linkedlist_deque.rs
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\npub struct ListNode<T> {\n    pub val: T,                                 // \u8282\u70b9\u503c\n    pub next: Option<Rc<RefCell<ListNode<T>>>>, // \u540e\u7ee7\u8282\u70b9\u6307\u9488\n    pub prev: Option<Rc<RefCell<ListNode<T>>>>, // \u524d\u9a71\u8282\u70b9\u6307\u9488\n}\n\nimpl<T> ListNode<T> {\n    pub fn new(val: T) -> Rc<RefCell<ListNode<T>>> {\n        Rc::new(RefCell::new(ListNode {\n            val,\n            next: None,\n            prev: None,\n        }))\n    }\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\n#[allow(dead_code)]\npub struct LinkedListDeque<T> {\n    front: Option<Rc<RefCell<ListNode<T>>>>,    // \u5934\u8282\u70b9 front\n    rear: Option<Rc<RefCell<ListNode<T>>>>,     // \u5c3e\u8282\u70b9 rear \n    que_size: usize,                            // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n}\n\nimpl<T: Copy> LinkedListDeque<T> {\n    pub fn new() -> Self {\n        Self {\n            front: None,\n            rear: None,\n            que_size: 0, \n        }\n    }\n\n    /* \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6 */\n    pub fn size(&self) -> usize {\n        return self.que_size;\n    }\n\n    /* \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    pub fn is_empty(&self) -> bool {\n        return self.size() == 0;\n    }\n\n    /* \u5165\u961f\u64cd\u4f5c */\n    pub fn push(&mut self, num: T, is_front: bool) {\n        let node = ListNode::new(num);\n        // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n        if is_front {\n            match self.front.take() {\n                // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n                None => {\n                    self.rear = Some(node.clone());\n                    self.front = Some(node);\n                }\n                // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n                Some(old_front) => {\n                    old_front.borrow_mut().prev = Some(node.clone());\n                    node.borrow_mut().next = Some(old_front);\n                    self.front = Some(node); // \u66f4\u65b0\u5934\u8282\u70b9\n                }\n            }\n        } \n        // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n        else {\n            match self.rear.take() {\n                // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n                None => {\n                    self.front = Some(node.clone());\n                    self.rear = Some(node);\n                }\n                // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n                Some(old_rear) => {\n                    old_rear.borrow_mut().next = Some(node.clone());\n                    node.borrow_mut().prev = Some(old_rear);\n                    self.rear = Some(node); // \u66f4\u65b0\u5c3e\u8282\u70b9\n                }\n            }\n        }\n        self.que_size += 1; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n    }\n\n    /* \u961f\u9996\u5165\u961f */\n    pub fn push_first(&mut self, num: T) {\n        self.push(num, true);\n    }\n\n    /* \u961f\u5c3e\u5165\u961f */\n    pub fn push_last(&mut self, num: T) {\n        self.push(num, false);\n    }\n\n    /* \u51fa\u961f\u64cd\u4f5c */\n    pub fn pop(&mut self, is_front: bool) -> Option<T> {\n        // \u82e5\u961f\u5217\u4e3a\u7a7a\uff0c\u76f4\u63a5\u8fd4\u56de None\n        if self.is_empty() { \n            return None \n        };\n        // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n        if is_front {\n            self.front.take().map(|old_front| {\n                match old_front.borrow_mut().next.take() {\n                    Some(new_front) => {\n                        new_front.borrow_mut().prev.take();\n                        self.front = Some(new_front);   // \u66f4\u65b0\u5934\u8282\u70b9\n                    }\n                    None => {\n                        self.rear.take();\n                    }\n                }\n                self.que_size -= 1; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n                Rc::try_unwrap(old_front).ok().unwrap().into_inner().val\n            })\n\n        } \n        // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n        else {\n            self.rear.take().map(|old_rear| {\n                match old_rear.borrow_mut().prev.take() {\n                    Some(new_rear) => {\n                        new_rear.borrow_mut().next.take();\n                        self.rear = Some(new_rear);     // \u66f4\u65b0\u5c3e\u8282\u70b9\n                    }\n                    None => {\n                        self.front.take();\n                    }\n                }\n                self.que_size -= 1; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n                Rc::try_unwrap(old_rear).ok().unwrap().into_inner().val\n            })\n        }\n    }\n\n    /* \u961f\u9996\u51fa\u961f */\n    pub fn pop_first(&mut self) -> Option<T> {\n        return self.pop(true);\n    }\n\n    /* \u961f\u5c3e\u51fa\u961f */\n    pub fn pop_last(&mut self) -> Option<T> {\n        return self.pop(false);\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    pub fn peek_first(&self) -> Option<&Rc<RefCell<ListNode<T>>>> {\n        self.front.as_ref()\n    }\n\n    /* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\n    pub fn peek_last(&self) -> Option<&Rc<RefCell<ListNode<T>>>> {\n        self.rear.as_ref()\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370 */\n    pub fn to_array(&self, head: Option<&Rc<RefCell<ListNode<T>>>>) -> Vec<T> {\n        if let Some(node) = head {\n            let mut nums = self.to_array(node.borrow().next.as_ref());\n            nums.insert(0, node.borrow().val);\n            return nums;\n        }\n        return Vec::new();\n    }\n}\n
linkedlist_deque.c
/* \u53cc\u5411\u94fe\u8868\u8282\u70b9 */\ntypedef struct DoublyListNode {\n    int val;                     // \u8282\u70b9\u503c\n    struct DoublyListNode *next; // \u540e\u7ee7\u8282\u70b9\n    struct DoublyListNode *prev; // \u524d\u9a71\u8282\u70b9\n} DoublyListNode;\n\n/* \u6784\u9020\u51fd\u6570 */\nDoublyListNode *newDoublyListNode(int num) {\n    DoublyListNode *new = (DoublyListNode *)malloc(sizeof(DoublyListNode));\n    new->val = num;\n    new->next = NULL;\n    new->prev = NULL;\n    return new;\n}\n\n/* \u6790\u6784\u51fd\u6570 */\nvoid delDoublyListNode(DoublyListNode *node) {\n    free(node);\n}\n\n/* \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217 */\ntypedef struct {\n    DoublyListNode *front, *rear; // \u5934\u8282\u70b9 front \uff0c\u5c3e\u8282\u70b9 rear\n    int queSize;                  // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n} LinkedListDeque;\n\n/* \u6784\u9020\u51fd\u6570 */\nLinkedListDeque *newLinkedListDeque() {\n    LinkedListDeque *deque = (LinkedListDeque *)malloc(sizeof(LinkedListDeque));\n    deque->front = NULL;\n    deque->rear = NULL;\n    deque->queSize = 0;\n    return deque;\n}\n\n/* \u6790\u6784\u51fd\u6570 */\nvoid delLinkedListdeque(LinkedListDeque *deque) {\n    // \u91ca\u653e\u6240\u6709\u8282\u70b9\n    for (int i = 0; i < deque->queSize && deque->front != NULL; i++) {\n        DoublyListNode *tmp = deque->front;\n        deque->front = deque->front->next;\n        free(tmp);\n    }\n    // \u91ca\u653e deque \u7ed3\u6784\u4f53\n    free(deque);\n}\n\n/* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\nint size(LinkedListDeque *deque) {\n    return deque->queSize;\n}\n\n/* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\nbool empty(LinkedListDeque *deque) {\n    return (size(deque) == 0);\n}\n\n/* \u5165\u961f */\nvoid push(LinkedListDeque *deque, int num, bool isFront) {\n    DoublyListNode *node = newDoublyListNode(num);\n    // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411node\n    if (empty(deque)) {\n        deque->front = deque->rear = node;\n    }\n    // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n    else if (isFront) {\n        // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n        deque->front->prev = node;\n        node->next = deque->front;\n        deque->front = node; // \u66f4\u65b0\u5934\u8282\u70b9\n    }\n    // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n    else {\n        // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n        deque->rear->next = node;\n        node->prev = deque->rear;\n        deque->rear = node;\n    }\n    deque->queSize++; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n}\n\n/* \u961f\u9996\u5165\u961f */\nvoid pushFirst(LinkedListDeque *deque, int num) {\n    push(deque, num, true);\n}\n\n/* \u961f\u5c3e\u5165\u961f */\nvoid pushLast(LinkedListDeque *deque, int num) {\n    push(deque, num, false);\n}\n\n/* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\nint peekFirst(LinkedListDeque *deque) {\n    assert(size(deque) && deque->front);\n    return deque->front->val;\n}\n\n/* \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20 */\nint peekLast(LinkedListDeque *deque) {\n    assert(size(deque) && deque->rear);\n    return deque->rear->val;\n}\n\n/* \u51fa\u961f */\nint pop(LinkedListDeque *deque, bool isFront) {\n    if (empty(deque))\n        return -1;\n    int val;\n    // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n    if (isFront) {\n        val = peekFirst(deque); // \u6682\u5b58\u5934\u8282\u70b9\u503c\n        DoublyListNode *fNext = deque->front->next;\n        if (fNext) {\n            fNext->prev = NULL;\n            deque->front->next = NULL;\n            delDoublyListNode(deque->front);\n        }\n        deque->front = fNext; // \u66f4\u65b0\u5934\u8282\u70b9\n    }\n    // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n    else {\n        val = peekLast(deque); // \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n        DoublyListNode *rPrev = deque->rear->prev;\n        if (rPrev) {\n            rPrev->next = NULL;\n            deque->rear->prev = NULL;\n            delDoublyListNode(deque->rear);\n        }\n        deque->rear = rPrev; // \u66f4\u65b0\u5c3e\u8282\u70b9\n    }\n    deque->queSize--; // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n    return val;\n}\n\n/* \u961f\u9996\u51fa\u961f */\nint popFirst(LinkedListDeque *deque) {\n    return pop(deque, true);\n}\n\n/* \u961f\u5c3e\u51fa\u961f */\nint popLast(LinkedListDeque *deque) {\n    return pop(deque, false);\n}\n\n/* \u6253\u5370\u961f\u5217 */\nvoid printLinkedListDeque(LinkedListDeque *deque) {\n    int *arr = malloc(sizeof(int) * deque->queSize);\n    // \u62f7\u8d1d\u94fe\u8868\u4e2d\u7684\u6570\u636e\u5230\u6570\u7ec4\n    int i;\n    DoublyListNode *node;\n    for (i = 0, node = deque->front; i < deque->queSize; i++) {\n        arr[i] = node->val;\n        node = node->next;\n    }\n    printArray(arr, deque->queSize);\n    free(arr);\n}\n
linkedlist_deque.zig
// \u53cc\u5411\u94fe\u8868\u8282\u70b9\nfn ListNode(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        val: T = undefined,     // \u8282\u70b9\u503c\n        next: ?*Self = null,    // \u540e\u7ee7\u8282\u70b9\u6307\u9488\n        prev: ?*Self = null,    // \u524d\u9a71\u8282\u70b9\u6307\u9488\n\n        // Initialize a list node with specific value\n        pub fn init(self: *Self, x: i32) void {\n            self.val = x;\n            self.next = null;\n            self.prev = null;\n        }\n    };\n}\n\n// \u57fa\u4e8e\u53cc\u5411\u94fe\u8868\u5b9e\u73b0\u7684\u53cc\u5411\u961f\u5217\nfn LinkedListDeque(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        front: ?*ListNode(T) = null,                    // \u5934\u8282\u70b9 front\n        rear: ?*ListNode(T) = null,                     // \u5c3e\u8282\u70b9 rear\n        que_size: usize = 0,                             // \u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n        mem_arena: ?std.heap.ArenaAllocator = null,\n        mem_allocator: std.mem.Allocator = undefined,   // \u5185\u5b58\u5206\u914d\u5668\n\n        // \u6784\u9020\u51fd\u6570\uff08\u5206\u914d\u5185\u5b58+\u521d\u59cb\u5316\u961f\u5217\uff09\n        pub fn init(self: *Self, allocator: std.mem.Allocator) !void {\n            if (self.mem_arena == null) {\n                self.mem_arena = std.heap.ArenaAllocator.init(allocator);\n                self.mem_allocator = self.mem_arena.?.allocator();\n            }\n            self.front = null;\n            self.rear = null;\n            self.que_size = 0;\n        }\n\n        // \u6790\u6784\u51fd\u6570\uff08\u91ca\u653e\u5185\u5b58\uff09\n        pub fn deinit(self: *Self) void {\n            if (self.mem_arena == null) return;\n            self.mem_arena.?.deinit();\n        }\n\n        // \u83b7\u53d6\u53cc\u5411\u961f\u5217\u7684\u957f\u5ea6\n        pub fn size(self: *Self) usize {\n            return self.que_size;\n        }\n\n        // \u5224\u65ad\u53cc\u5411\u961f\u5217\u662f\u5426\u4e3a\u7a7a\n        pub fn isEmpty(self: *Self) bool {\n            return self.size() == 0;\n        }\n\n        // \u5165\u961f\u64cd\u4f5c\n        pub fn push(self: *Self, num: T, is_front: bool) !void {\n            var node = try self.mem_allocator.create(ListNode(T));\n            node.init(num);\n            // \u82e5\u94fe\u8868\u4e3a\u7a7a\uff0c\u5219\u4ee4 front \u548c rear \u90fd\u6307\u5411 node\n            if (self.isEmpty()) {\n                self.front = node;\n                self.rear = node;\n            // \u961f\u9996\u5165\u961f\u64cd\u4f5c\n            } else if (is_front) {\n                // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5934\u90e8\n                self.front.?.prev = node;\n                node.next = self.front;\n                self.front = node;  // \u66f4\u65b0\u5934\u8282\u70b9\n            // \u961f\u5c3e\u5165\u961f\u64cd\u4f5c\n            } else {\n                // \u5c06 node \u6dfb\u52a0\u81f3\u94fe\u8868\u5c3e\u90e8\n                self.rear.?.next = node;\n                node.prev = self.rear;\n                self.rear = node;   // \u66f4\u65b0\u5c3e\u8282\u70b9\n            }\n            self.que_size += 1;      // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n        } \n\n        // \u961f\u9996\u5165\u961f\n        pub fn pushFirst(self: *Self, num: T) !void {\n            try self.push(num, true);\n        } \n\n        // \u961f\u5c3e\u5165\u961f\n        pub fn pushLast(self: *Self, num: T) !void {\n            try self.push(num, false);\n        } \n\n        // \u51fa\u961f\u64cd\u4f5c\n        pub fn pop(self: *Self, is_front: bool) T {\n            if (self.isEmpty()) @panic(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\");\n            var val: T = undefined;\n            // \u961f\u9996\u51fa\u961f\u64cd\u4f5c\n            if (is_front) {\n                val = self.front.?.val;     // \u6682\u5b58\u5934\u8282\u70b9\u503c\n                // \u5220\u9664\u5934\u8282\u70b9\n                var fNext = self.front.?.next;\n                if (fNext != null) {\n                    fNext.?.prev = null;\n                    self.front.?.next = null;\n                }\n                self.front = fNext;         // \u66f4\u65b0\u5934\u8282\u70b9\n            // \u961f\u5c3e\u51fa\u961f\u64cd\u4f5c\n            } else {\n                val = self.rear.?.val;      // \u6682\u5b58\u5c3e\u8282\u70b9\u503c\n                // \u5220\u9664\u5c3e\u8282\u70b9\n                var rPrev = self.rear.?.prev;\n                if (rPrev != null) {\n                    rPrev.?.next = null;\n                    self.rear.?.prev = null;\n                }\n                self.rear = rPrev;          // \u66f4\u65b0\u5c3e\u8282\u70b9\n            }\n            self.que_size -= 1;              // \u66f4\u65b0\u961f\u5217\u957f\u5ea6\n            return val;\n        } \n\n        // \u961f\u9996\u51fa\u961f\n        pub fn popFirst(self: *Self) T {\n            return self.pop(true);\n        } \n\n        // \u961f\u5c3e\u51fa\u961f\n        pub fn popLast(self: *Self) T {\n            return self.pop(false);\n        } \n\n        // \u8bbf\u95ee\u961f\u9996\u5143\u7d20\n        pub fn peekFirst(self: *Self) T {\n            if (self.isEmpty()) @panic(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\");\n            return self.front.?.val;\n        }  \n\n        // \u8bbf\u95ee\u961f\u5c3e\u5143\u7d20\n        pub fn peekLast(self: *Self) T {\n            if (self.isEmpty()) @panic(\"\u53cc\u5411\u961f\u5217\u4e3a\u7a7a\");\n            return self.rear.?.val;\n        }\n\n        // \u8fd4\u56de\u6570\u7ec4\u7528\u4e8e\u6253\u5370\n        pub fn toArray(self: *Self) ![]T {\n            var node = self.front;\n            var res = try self.mem_allocator.alloc(T, self.size());\n            @memset(res, @as(T, 0));\n            var i: usize = 0;\n            while (i < res.len) : (i += 1) {\n                res[i] = node.?.val;\n                node = node.?.next;\n            }\n            return res;\n        }\n    };\n}\n
"},{"location":"chapter_stack_and_queue/deque/#2-implementation-based-on-array","title":"2. \u00a0 Implementation Based on Array","text":"

As shown in the Figure 5-9 , similar to implementing a queue with an array, we can also use a circular array to implement a double-ended queue.

ArrayDequepushLast()pushFirst()popLast()popFirst()

Figure 5-9 \u00a0 Implementing Double-Ended Queue with Array for Enqueue and Dequeue Operations

The implementation only needs to add methods for \"front enqueue\" and \"rear dequeue\":

[file]{array_deque}-[func]{}\n
"},{"location":"chapter_stack_and_queue/deque/#533-applications-of-double-ended-queue","title":"5.3.3 \u00a0 Applications of Double-Ended Queue","text":"

The double-ended queue combines the logic of both stacks and queues, thus it can implement all the application scenarios of these two, while offering greater flexibility.

We know that the \"undo\" feature in software is typically implemented using a stack: the system pushes each change operation onto the stack, and then pops to implement undoing. However, considering the limitations of system resources, software often restricts the number of undo steps (for example, only allowing the last 50 steps). When the length of the stack exceeds 50, the software needs to perform a deletion operation at the bottom of the stack (the front of the queue). But a regular stack cannot perform this function, which is where a double-ended queue becomes necessary. Note that the core logic of \"undo\" still follows the Last-In-First-Out principle of a stack, but a double-ended queue can more flexibly implement some additional logic.

"},{"location":"chapter_stack_and_queue/queue/","title":"5.2 \u00a0 Queue","text":"

\"Queue\" is a linear data structure that follows the First-In-First-Out (FIFO) rule. As the name suggests, a queue simulates the phenomenon of lining up, where newcomers join the back of the queue, and people at the front of the queue leave one by one.

As shown in the Figure 5-4 , we call the front of the queue the \"head\" and the back the \"tail.\" The operation of adding elements to the tail of the queue is termed \"enqueue,\" and the operation of removing elements from the head is termed \"dequeue.\"

Figure 5-4 \u00a0 Queue's First-In-First-Out Rule

"},{"location":"chapter_stack_and_queue/queue/#521-common-operations-on-queue","title":"5.2.1 \u00a0 Common Operations on Queue","text":"

The common operations on a queue are shown in the Table 5-2 . Note that method names may vary across different programming languages. Here, we adopt the same naming convention as used for stacks.

Table 5-2 \u00a0 Efficiency of Queue Operations

Method Name Description Time Complexity push() Enqueue an element, add it to the tail \\(O(1)\\) pop() Dequeue the head element \\(O(1)\\) peek() Access the head element \\(O(1)\\)

We can directly use the ready-made queue classes in programming languages:

PythonC++JavaC#GoSwiftJSTSDartRustCZig queue.py
from collections import deque\n\n# Initialize the queue\n# In Python, we generally use the deque class as a queue\n# Although queue.Queue() is a pure queue class, it's not very user-friendly, so it's not recommended\nque: deque[int] = deque()\n\n# Enqueue elements\nque.append(1)\nque.append(3)\nque.append(2)\nque.append(5)\nque.append(4)\n\n# Access the front element\nfront: int = que[0]\n\n# Dequeue an element\npop: int = que.popleft()\n\n# Get the length of the queue\nsize: int = len(que)\n\n# Check if the queue is empty\nis_empty: bool = len(que) == 0\n
queue.cpp
/* Initialize the queue */\nqueue<int> queue;\n\n/* Enqueue elements */\nqueue.push(1);\nqueue.push(3);\nqueue.push(2);\nqueue.push(5);\nqueue.push(4);\n\n/* Access the front element */\nint front = queue.front();\n\n/* Dequeue an element */\nqueue.pop();\n\n/* Get the length of the queue */\nint size = queue.size();\n\n/* Check if the queue is empty */\nbool empty = queue.empty();\n
queue.java
/* Initialize the queue */\nQueue<Integer> queue = new LinkedList<>();\n\n/* Enqueue elements */\nqueue.offer(1);\nqueue.offer(3);\nqueue.offer(2);\nqueue.offer(5);\nqueue.offer(4);\n\n/* Access the front element */\nint peek = queue.peek();\n\n/* Dequeue an element */\nint pop = queue.poll();\n\n/* Get the length of the queue */\nint size = queue.size();\n\n/* Check if the queue is empty */\nboolean isEmpty = queue.isEmpty();\n
queue.cs
/* Initialize the queue */\nQueue<int> queue = new();\n\n/* Enqueue elements */\nqueue.Enqueue(1);\nqueue.Enqueue(3);\nqueue.Enqueue(2);\nqueue.Enqueue(5);\nqueue.Enqueue(4);\n\n/* Access the front element */\nint peek = queue.Peek();\n\n/* Dequeue an element */\nint pop = queue.Dequeue();\n\n/* Get the length of the queue */\nint size = queue.Count;\n\n/* Check if the queue is empty */\nbool isEmpty = queue.Count == 0;\n
queue_test.go
/* Initialize the queue */\n// In Go, use list as a queue\nqueue := list.New()\n\n/* Enqueue elements */\nqueue.PushBack(1)\nqueue.PushBack(3)\nqueue.PushBack(2)\nqueue.PushBack(5)\nqueue.PushBack(4)\n\n/* Access the front element */\npeek := queue.Front()\n\n/* Dequeue an element */\npop := queue.Front()\nqueue.Remove(pop)\n\n/* Get the length of the queue */\nsize := queue.Len()\n\n/* Check if the queue is empty */\nisEmpty := queue.Len() == 0\n
queue.swift
/* Initialize the queue */\n// Swift does not have a built-in queue class, so Array can be used as a queue\nvar queue: [Int] = []\n\n/* Enqueue elements */\nqueue.append(1)\nqueue.append(3)\nqueue.append(2)\nqueue.append(5)\nqueue.append(4)\n\n/* Access the front element */\nlet peek = queue.first!\n\n/* Dequeue an element */\n// Since it's an array, removeFirst has a complexity of O(n)\nlet pool = queue.removeFirst()\n\n/* Get the length of the queue */\nlet size = queue.count\n\n/* Check if the queue is empty */\nlet isEmpty = queue.isEmpty\n
queue.js
/* Initialize the queue */\n// JavaScript does not have a built-in queue, so Array can be used as a queue\nconst queue = [];\n\n/* Enqueue elements */\nqueue.push(1);\nqueue.push(3);\nqueue.push(2);\nqueue.push(5);\nqueue.push(4);\n\n/* Access the front element */\nconst peek = queue[0];\n\n/* Dequeue an element */\n// Since the underlying structure is an array, shift() method has a time complexity of O(n)\nconst pop = queue.shift();\n\n/* Get the length of the queue */\nconst size = queue.length;\n\n/* Check if the queue is empty */\nconst empty = queue.length === 0;\n
queue.ts
/* Initialize the queue */\n// TypeScript does not have a built-in queue, so Array can be used as a queue \nconst queue: number[] = [];\n\n/* Enqueue elements */\nqueue.push(1);\nqueue.push(3);\nqueue.push(2);\nqueue.push(5);\nqueue.push(4);\n\n/* Access the front element */\nconst peek = queue[0];\n\n/* Dequeue an element */\n// Since the underlying structure is an array, shift() method has a time complexity of O(n)\nconst pop = queue.shift();\n\n/* Get the length of the queue */\nconst size = queue.length;\n\n/* Check if the queue is empty */\nconst empty = queue.length === 0;\n
queue.dart
/* Initialize the queue */\n// In Dart, the Queue class is a double-ended queue but can be used as a queue\nQueue<int> queue = Queue();\n\n/* Enqueue elements */\nqueue.add(1);\nqueue.add(3);\nqueue.add(2);\nqueue.add(5);\nqueue.add(4);\n\n/* Access the front element */\nint peek = queue.first;\n\n/* Dequeue an element */\nint pop = queue.removeFirst();\n\n/* Get the length of the queue */\nint size = queue.length;\n\n/* Check if the queue is empty */\nbool isEmpty = queue.isEmpty;\n
queue.rs
/* Initialize the double-ended queue */\n// In Rust, use a double-ended queue as a regular queue\nlet mut deque: VecDeque<u32> = VecDeque::new();\n\n/* Enqueue elements */\ndeque.push_back(1);\ndeque.push_back(3);\ndeque.push_back(2);\ndeque.push_back(5);\ndeque.push_back(4);\n\n/* Access the front element */\nif let Some(front) = deque.front() {\n}\n\n/* Dequeue an element */\nif let Some(pop) = deque.pop_front() {\n}\n\n/* Get the length of the queue */\nlet size = deque.len();\n\n/* Check if the queue is empty */\nlet is_empty = deque.is_empty();\n
queue.c
// C does not provide a built-in queue\n
queue.zig
\n
Visualizing Code

Full Screen >

"},{"location":"chapter_stack_and_queue/queue/#522-implementing-a-queue","title":"5.2.2 \u00a0 Implementing a Queue","text":"

To implement a queue, we need a data structure that allows adding elements at one end and removing them at the other. Both linked lists and arrays meet this requirement.

"},{"location":"chapter_stack_and_queue/queue/#1-implementation-based-on-linked-list","title":"1. \u00a0 Implementation Based on Linked List","text":"

As shown in the Figure 5-5 , we can consider the \"head node\" and \"tail node\" of a linked list as the \"head\" and \"tail\" of the queue, respectively. We restrict the operations so that nodes can only be added at the tail and removed at the head.

LinkedListQueuepush()pop()

Figure 5-5 \u00a0 Implementing Queue with Linked List for Enqueue and Dequeue Operations

Below is the code for implementing a queue using a linked list:

PythonC++JavaC#GoSwiftJSTSDartRustCZig linkedlist_queue.py
class LinkedListQueue:\n    \"\"\"\u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217\"\"\"\n\n    def __init__(self):\n        \"\"\"\u6784\u9020\u65b9\u6cd5\"\"\"\n        self._front: ListNode | None = None  # \u5934\u8282\u70b9 front\n        self._rear: ListNode | None = None  # \u5c3e\u8282\u70b9 rear\n        self._size: int = 0\n\n    def size(self) -> int:\n        \"\"\"\u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6\"\"\"\n        return self._size\n\n    def is_empty(self) -> bool:\n        \"\"\"\u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a\"\"\"\n        return not self._front\n\n    def push(self, num: int):\n        \"\"\"\u5165\u961f\"\"\"\n        # \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        node = ListNode(num)\n        # \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n        if self._front is None:\n            self._front = node\n            self._rear = node\n        # \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n        else:\n            self._rear.next = node\n            self._rear = node\n        self._size += 1\n\n    def pop(self) -> int:\n        \"\"\"\u51fa\u961f\"\"\"\n        num = self.peek()\n        # \u5220\u9664\u5934\u8282\u70b9\n        self._front = self._front.next\n        self._size -= 1\n        return num\n\n    def peek(self) -> int:\n        \"\"\"\u8bbf\u95ee\u961f\u9996\u5143\u7d20\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u961f\u5217\u4e3a\u7a7a\")\n        return self._front.val\n\n    def to_list(self) -> list[int]:\n        \"\"\"\u8f6c\u5316\u4e3a\u5217\u8868\u7528\u4e8e\u6253\u5370\"\"\"\n        queue = []\n        temp = self._front\n        while temp:\n            queue.append(temp.val)\n            temp = temp.next\n        return queue\n
linkedlist_queue.cpp
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\nclass LinkedListQueue {\n  private:\n    ListNode *front, *rear; // \u5934\u8282\u70b9 front \uff0c\u5c3e\u8282\u70b9 rear\n    int queSize;\n\n  public:\n    LinkedListQueue() {\n        front = nullptr;\n        rear = nullptr;\n        queSize = 0;\n    }\n\n    ~LinkedListQueue() {\n        // \u904d\u5386\u94fe\u8868\u5220\u9664\u8282\u70b9\uff0c\u91ca\u653e\u5185\u5b58\n        freeMemoryLinkedList(front);\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    int size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    bool isEmpty() {\n        return queSize == 0;\n    }\n\n    /* \u5165\u961f */\n    void push(int num) {\n        // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        ListNode *node = new ListNode(num);\n        // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n        if (front == nullptr) {\n            front = node;\n            rear = node;\n        }\n        // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n        else {\n            rear->next = node;\n            rear = node;\n        }\n        queSize++;\n    }\n\n    /* \u51fa\u961f */\n    int pop() {\n        int num = peek();\n        // \u5220\u9664\u5934\u8282\u70b9\n        ListNode *tmp = front;\n        front = front->next;\n        // \u91ca\u653e\u5185\u5b58\n        delete tmp;\n        queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    int peek() {\n        if (size() == 0)\n            throw out_of_range(\"\u961f\u5217\u4e3a\u7a7a\");\n        return front->val;\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Vector \u5e76\u8fd4\u56de */\n    vector<int> toVector() {\n        ListNode *node = front;\n        vector<int> res(size());\n        for (int i = 0; i < res.size(); i++) {\n            res[i] = node->val;\n            node = node->next;\n        }\n        return res;\n    }\n};\n
linkedlist_queue.java
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\nclass LinkedListQueue {\n    private ListNode front, rear; // \u5934\u8282\u70b9 front \uff0c\u5c3e\u8282\u70b9 rear\n    private int queSize = 0;\n\n    public LinkedListQueue() {\n        front = null;\n        rear = null;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    public int size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /* \u5165\u961f */\n    public void push(int num) {\n        // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        ListNode node = new ListNode(num);\n        // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n        if (front == null) {\n            front = node;\n            rear = node;\n        // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n        } else {\n            rear.next = node;\n            rear = node;\n        }\n        queSize++;\n    }\n\n    /* \u51fa\u961f */\n    public int pop() {\n        int num = peek();\n        // \u5220\u9664\u5934\u8282\u70b9\n        front = front.next;\n        queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    public int peek() {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        return front.val;\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    public int[] toArray() {\n        ListNode node = front;\n        int[] res = new int[size()];\n        for (int i = 0; i < res.length; i++) {\n            res[i] = node.val;\n            node = node.next;\n        }\n        return res;\n    }\n}\n
linkedlist_queue.cs
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\nclass LinkedListQueue {\n    ListNode? front, rear;  // \u5934\u8282\u70b9 front \uff0c\u5c3e\u8282\u70b9 rear \n    int queSize = 0;\n\n    public LinkedListQueue() {\n        front = null;\n        rear = null;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    public int Size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    public bool IsEmpty() {\n        return Size() == 0;\n    }\n\n    /* \u5165\u961f */\n    public void Push(int num) {\n        // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        ListNode node = new(num);\n        // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n        if (front == null) {\n            front = node;\n            rear = node;\n            // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n        } else if (rear != null) {\n            rear.next = node;\n            rear = node;\n        }\n        queSize++;\n    }\n\n    /* \u51fa\u961f */\n    public int Pop() {\n        int num = Peek();\n        // \u5220\u9664\u5934\u8282\u70b9\n        front = front?.next;\n        queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    public int Peek() {\n        if (IsEmpty())\n            throw new Exception();\n        return front!.val;\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    public int[] ToArray() {\n        if (front == null)\n            return [];\n\n        ListNode? node = front;\n        int[] res = new int[Size()];\n        for (int i = 0; i < res.Length; i++) {\n            res[i] = node!.val;\n            node = node.next;\n        }\n        return res;\n    }\n}\n
linkedlist_queue.go
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\ntype linkedListQueue struct {\n    // \u4f7f\u7528\u5185\u7f6e\u5305 list \u6765\u5b9e\u73b0\u961f\u5217\n    data *list.List\n}\n\n/* \u521d\u59cb\u5316\u961f\u5217 */\nfunc newLinkedListQueue() *linkedListQueue {\n    return &linkedListQueue{\n        data: list.New(),\n    }\n}\n\n/* \u5165\u961f */\nfunc (s *linkedListQueue) push(value any) {\n    s.data.PushBack(value)\n}\n\n/* \u51fa\u961f */\nfunc (s *linkedListQueue) pop() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Front()\n    s.data.Remove(e)\n    return e.Value\n}\n\n/* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\nfunc (s *linkedListQueue) peek() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Front()\n    return e.Value\n}\n\n/* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\nfunc (s *linkedListQueue) size() int {\n    return s.data.Len()\n}\n\n/* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\nfunc (s *linkedListQueue) isEmpty() bool {\n    return s.data.Len() == 0\n}\n\n/* \u83b7\u53d6 List \u7528\u4e8e\u6253\u5370 */\nfunc (s *linkedListQueue) toList() *list.List {\n    return s.data\n}\n
linkedlist_queue.swift
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\nclass LinkedListQueue {\n    private var front: ListNode? // \u5934\u8282\u70b9\n    private var rear: ListNode? // \u5c3e\u8282\u70b9\n    private var _size = 0\n\n    init() {}\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    func size() -> Int {\n        _size\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    func isEmpty() -> Bool {\n        size() == 0\n    }\n\n    /* \u5165\u961f */\n    func push(num: Int) {\n        // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        let node = ListNode(x: num)\n        // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n        if front == nil {\n            front = node\n            rear = node\n        }\n        // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n        else {\n            rear?.next = node\n            rear = node\n        }\n        _size += 1\n    }\n\n    /* \u51fa\u961f */\n    @discardableResult\n    func pop() -> Int {\n        let num = peek()\n        // \u5220\u9664\u5934\u8282\u70b9\n        front = front?.next\n        _size -= 1\n        return num\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    func peek() -> Int {\n        if isEmpty() {\n            fatalError(\"\u961f\u5217\u4e3a\u7a7a\")\n        }\n        return front!.val\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    func toArray() -> [Int] {\n        var node = front\n        var res = Array(repeating: 0, count: size())\n        for i in res.indices {\n            res[i] = node!.val\n            node = node?.next\n        }\n        return res\n    }\n}\n
linkedlist_queue.js
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\nclass LinkedListQueue {\n    #front; // \u5934\u8282\u70b9 #front\n    #rear; // \u5c3e\u8282\u70b9 #rear\n    #queSize = 0;\n\n    constructor() {\n        this.#front = null;\n        this.#rear = null;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    get size() {\n        return this.#queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    isEmpty() {\n        return this.size === 0;\n    }\n\n    /* \u5165\u961f */\n    push(num) {\n        // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        const node = new ListNode(num);\n        // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n        if (!this.#front) {\n            this.#front = node;\n            this.#rear = node;\n            // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n        } else {\n            this.#rear.next = node;\n            this.#rear = node;\n        }\n        this.#queSize++;\n    }\n\n    /* \u51fa\u961f */\n    pop() {\n        const num = this.peek();\n        // \u5220\u9664\u5934\u8282\u70b9\n        this.#front = this.#front.next;\n        this.#queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    peek() {\n        if (this.size === 0) throw new Error('\u961f\u5217\u4e3a\u7a7a');\n        return this.#front.val;\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    toArray() {\n        let node = this.#front;\n        const res = new Array(this.size);\n        for (let i = 0; i < res.length; i++) {\n            res[i] = node.val;\n            node = node.next;\n        }\n        return res;\n    }\n}\n
linkedlist_queue.ts
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\nclass LinkedListQueue {\n    private front: ListNode | null; // \u5934\u8282\u70b9 front\n    private rear: ListNode | null; // \u5c3e\u8282\u70b9 rear\n    private queSize: number = 0;\n\n    constructor() {\n        this.front = null;\n        this.rear = null;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    get size(): number {\n        return this.queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    isEmpty(): boolean {\n        return this.size === 0;\n    }\n\n    /* \u5165\u961f */\n    push(num: number): void {\n        // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        const node = new ListNode(num);\n        // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n        if (!this.front) {\n            this.front = node;\n            this.rear = node;\n            // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n        } else {\n            this.rear!.next = node;\n            this.rear = node;\n        }\n        this.queSize++;\n    }\n\n    /* \u51fa\u961f */\n    pop(): number {\n        const num = this.peek();\n        if (!this.front) throw new Error('\u961f\u5217\u4e3a\u7a7a');\n        // \u5220\u9664\u5934\u8282\u70b9\n        this.front = this.front.next;\n        this.queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    peek(): number {\n        if (this.size === 0) throw new Error('\u961f\u5217\u4e3a\u7a7a');\n        return this.front!.val;\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    toArray(): number[] {\n        let node = this.front;\n        const res = new Array<number>(this.size);\n        for (let i = 0; i < res.length; i++) {\n            res[i] = node!.val;\n            node = node!.next;\n        }\n        return res;\n    }\n}\n
linkedlist_queue.dart
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\nclass LinkedListQueue {\n  ListNode? _front; // \u5934\u8282\u70b9 _front\n  ListNode? _rear; // \u5c3e\u8282\u70b9 _rear\n  int _queSize = 0; // \u961f\u5217\u957f\u5ea6\n\n  LinkedListQueue() {\n    _front = null;\n    _rear = null;\n  }\n\n  /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n  int size() {\n    return _queSize;\n  }\n\n  /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n  bool isEmpty() {\n    return _queSize == 0;\n  }\n\n  /* \u5165\u961f */\n  void push(int _num) {\n    // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 _num\n    final node = ListNode(_num);\n    // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n    if (_front == null) {\n      _front = node;\n      _rear = node;\n    } else {\n      // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n      _rear!.next = node;\n      _rear = node;\n    }\n    _queSize++;\n  }\n\n  /* \u51fa\u961f */\n  int pop() {\n    final int _num = peek();\n    // \u5220\u9664\u5934\u8282\u70b9\n    _front = _front!.next;\n    _queSize--;\n    return _num;\n  }\n\n  /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n  int peek() {\n    if (_queSize == 0) {\n      throw Exception('\u961f\u5217\u4e3a\u7a7a');\n    }\n    return _front!.val;\n  }\n\n  /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n  List<int> toArray() {\n    ListNode? node = _front;\n    final List<int> queue = [];\n    while (node != null) {\n      queue.add(node.val);\n      node = node.next;\n    }\n    return queue;\n  }\n}\n
linkedlist_queue.rs
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\n#[allow(dead_code)]\npub struct LinkedListQueue<T> {\n    front: Option<Rc<RefCell<ListNode<T>>>>,    // \u5934\u8282\u70b9 front\n    rear: Option<Rc<RefCell<ListNode<T>>>>,     // \u5c3e\u8282\u70b9 rear \n    que_size: usize,                            // \u961f\u5217\u7684\u957f\u5ea6\n}\n\nimpl<T: Copy> LinkedListQueue<T> {\n    pub fn new() -> Self {\n        Self {\n            front: None,\n            rear: None,\n            que_size: 0, \n        }\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    pub fn size(&self) -> usize {\n        return self.que_size;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    pub fn is_empty(&self) -> bool {\n        return self.size() == 0;\n    }\n\n    /* \u5165\u961f */\n    pub fn push(&mut self, num: T) {\n        // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n        let new_rear = ListNode::new(num);\n        match self.rear.take() {\n            // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n            Some(old_rear) => {\n                old_rear.borrow_mut().next = Some(new_rear.clone());\n                self.rear = Some(new_rear);\n            }\n            // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n            None => {\n                self.front = Some(new_rear.clone());\n                self.rear = Some(new_rear);\n            }\n        }\n        self.que_size += 1;\n    }\n\n    /* \u51fa\u961f */\n    pub fn pop(&mut self) -> Option<T> {\n        self.front.take().map(|old_front| {\n            match old_front.borrow_mut().next.take() {\n                Some(new_front) => {\n                    self.front = Some(new_front);\n                }\n                None => {\n                    self.rear.take();\n                }\n            }\n            self.que_size -= 1;\n            Rc::try_unwrap(old_front).ok().unwrap().into_inner().val\n        })\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    pub fn peek(&self) -> Option<&Rc<RefCell<ListNode<T>>>> {\n        self.front.as_ref()\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    pub fn to_array(&self, head: Option<&Rc<RefCell<ListNode<T>>>>) -> Vec<T> {\n        if let Some(node) = head {\n            let mut nums = self.to_array(node.borrow().next.as_ref());\n            nums.insert(0, node.borrow().val);\n            return nums;\n        }\n        return Vec::new();\n    }\n}\n
linkedlist_queue.c
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217 */\ntypedef struct {\n    ListNode *front, *rear;\n    int queSize;\n} LinkedListQueue;\n\n/* \u6784\u9020\u51fd\u6570 */\nLinkedListQueue *newLinkedListQueue() {\n    LinkedListQueue *queue = (LinkedListQueue *)malloc(sizeof(LinkedListQueue));\n    queue->front = NULL;\n    queue->rear = NULL;\n    queue->queSize = 0;\n    return queue;\n}\n\n/* \u6790\u6784\u51fd\u6570 */\nvoid delLinkedListQueue(LinkedListQueue *queue) {\n    // \u91ca\u653e\u6240\u6709\u8282\u70b9\n    for (int i = 0; i < queue->queSize && queue->front != NULL; i++) {\n        ListNode *tmp = queue->front;\n        queue->front = queue->front->next;\n        free(tmp);\n    }\n    // \u91ca\u653e queue \u7ed3\u6784\u4f53\n    free(queue);\n}\n\n/* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\nint size(LinkedListQueue *queue) {\n    return queue->queSize;\n}\n\n/* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\nbool empty(LinkedListQueue *queue) {\n    return (size(queue) == 0);\n}\n\n/* \u5165\u961f */\nvoid push(LinkedListQueue *queue, int num) {\n    // \u5c3e\u8282\u70b9\u5904\u6dfb\u52a0 node\n    ListNode *node = newListNode(num);\n    // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n    if (queue->front == NULL) {\n        queue->front = node;\n        queue->rear = node;\n    }\n    // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n    else {\n        queue->rear->next = node;\n        queue->rear = node;\n    }\n    queue->queSize++;\n}\n\n/* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\nint peek(LinkedListQueue *queue) {\n    assert(size(queue) && queue->front);\n    return queue->front->val;\n}\n\n/* \u51fa\u961f */\nint pop(LinkedListQueue *queue) {\n    int num = peek(queue);\n    ListNode *tmp = queue->front;\n    queue->front = queue->front->next;\n    free(tmp);\n    queue->queSize--;\n    return num;\n}\n\n/* \u6253\u5370\u961f\u5217 */\nvoid printLinkedListQueue(LinkedListQueue *queue) {\n    int *arr = malloc(sizeof(int) * queue->queSize);\n    // \u62f7\u8d1d\u94fe\u8868\u4e2d\u7684\u6570\u636e\u5230\u6570\u7ec4\n    int i;\n    ListNode *node;\n    for (i = 0, node = queue->front; i < queue->queSize; i++) {\n        arr[i] = node->val;\n        node = node->next;\n    }\n    printArray(arr, queue->queSize);\n    free(arr);\n}\n
linkedlist_queue.zig
// \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u961f\u5217\nfn LinkedListQueue(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        front: ?*inc.ListNode(T) = null,                // \u5934\u8282\u70b9 front\n        rear: ?*inc.ListNode(T) = null,                 // \u5c3e\u8282\u70b9 rear\n        que_size: usize = 0,                            // \u961f\u5217\u7684\u957f\u5ea6\n        mem_arena: ?std.heap.ArenaAllocator = null,\n        mem_allocator: std.mem.Allocator = undefined,   // \u5185\u5b58\u5206\u914d\u5668\n\n        // \u6784\u9020\u51fd\u6570\uff08\u5206\u914d\u5185\u5b58+\u521d\u59cb\u5316\u961f\u5217\uff09\n        pub fn init(self: *Self, allocator: std.mem.Allocator) !void {\n            if (self.mem_arena == null) {\n                self.mem_arena = std.heap.ArenaAllocator.init(allocator);\n                self.mem_allocator = self.mem_arena.?.allocator();\n            }\n            self.front = null;\n            self.rear = null;\n            self.que_size = 0;\n        }\n\n        // \u6790\u6784\u51fd\u6570\uff08\u91ca\u653e\u5185\u5b58\uff09\n        pub fn deinit(self: *Self) void {\n            if (self.mem_arena == null) return;\n            self.mem_arena.?.deinit();\n        }\n\n        // \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6\n        pub fn size(self: *Self) usize {\n            return self.que_size;\n        }\n\n        // \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a\n        pub fn isEmpty(self: *Self) bool {\n            return self.size() == 0;\n        }\n\n        // \u8bbf\u95ee\u961f\u9996\u5143\u7d20\n        pub fn peek(self: *Self) T {\n            if (self.size() == 0) @panic(\"\u961f\u5217\u4e3a\u7a7a\");\n            return self.front.?.val;\n        }  \n\n        // \u5165\u961f\n        pub fn push(self: *Self, num: T) !void {\n            // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n            var node = try self.mem_allocator.create(inc.ListNode(T));\n            node.init(num);\n            // \u5982\u679c\u961f\u5217\u4e3a\u7a7a\uff0c\u5219\u4ee4\u5934\u3001\u5c3e\u8282\u70b9\u90fd\u6307\u5411\u8be5\u8282\u70b9\n            if (self.front == null) {\n                self.front = node;\n                self.rear = node;\n            // \u5982\u679c\u961f\u5217\u4e0d\u4e3a\u7a7a\uff0c\u5219\u5c06\u8be5\u8282\u70b9\u6dfb\u52a0\u5230\u5c3e\u8282\u70b9\u540e\n            } else {\n                self.rear.?.next = node;\n                self.rear = node;\n            }\n            self.que_size += 1;\n        } \n\n        // \u51fa\u961f\n        pub fn pop(self: *Self) T {\n            var num = self.peek();\n            // \u5220\u9664\u5934\u8282\u70b9\n            self.front = self.front.?.next;\n            self.que_size -= 1;\n            return num;\n        } \n\n        // \u5c06\u94fe\u8868\u8f6c\u6362\u4e3a\u6570\u7ec4\n        pub fn toArray(self: *Self) ![]T {\n            var node = self.front;\n            var res = try self.mem_allocator.alloc(T, self.size());\n            @memset(res, @as(T, 0));\n            var i: usize = 0;\n            while (i < res.len) : (i += 1) {\n                res[i] = node.?.val;\n                node = node.?.next;\n            }\n            return res;\n        }\n    };\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_stack_and_queue/queue/#2-implementation-based-on-array","title":"2. \u00a0 Implementation Based on Array","text":"

Deleting the first element in an array has a time complexity of \\(O(n)\\), which would make the dequeue operation inefficient. However, this problem can be cleverly avoided as follows.

We can use a variable front to point to the index of the head element and maintain a size variable to record the length of the queue. Define rear = front + size, which points to the position right after the tail element.

With this design, the effective interval of elements in the array is [front, rear - 1]. The implementation methods for various operations are shown in the Figure 5-6 .

  • Enqueue operation: Assign the input element to the rear index and increase size by 1.
  • Dequeue operation: Simply increase front by 1 and decrease size by 1.

Both enqueue and dequeue operations only require a single operation, each with a time complexity of \\(O(1)\\).

ArrayQueuepush()pop()

Figure 5-6 \u00a0 Implementing Queue with Array for Enqueue and Dequeue Operations

You might notice a problem: as enqueue and dequeue operations are continuously performed, both front and rear move to the right and will eventually reach the end of the array and can't move further. To resolve this issue, we can treat the array as a \"circular array.\"

For a circular array, front or rear needs to loop back to the start of the array upon reaching the end. This cyclical pattern can be achieved with a \"modulo operation,\" as shown in the code below:

PythonC++JavaC#GoSwiftJSTSDartRustCZig array_queue.py
class ArrayQueue:\n    \"\"\"\u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217\"\"\"\n\n    def __init__(self, size: int):\n        \"\"\"\u6784\u9020\u65b9\u6cd5\"\"\"\n        self._nums: list[int] = [0] * size  # \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n        self._front: int = 0  # \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n        self._size: int = 0  # \u961f\u5217\u957f\u5ea6\n\n    def capacity(self) -> int:\n        \"\"\"\u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf\"\"\"\n        return len(self._nums)\n\n    def size(self) -> int:\n        \"\"\"\u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6\"\"\"\n        return self._size\n\n    def is_empty(self) -> bool:\n        \"\"\"\u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a\"\"\"\n        return self._size == 0\n\n    def push(self, num: int):\n        \"\"\"\u5165\u961f\"\"\"\n        if self._size == self.capacity():\n            raise IndexError(\"\u961f\u5217\u5df2\u6ee1\")\n        # \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        # \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        rear: int = (self._front + self._size) % self.capacity()\n        # \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        self._nums[rear] = num\n        self._size += 1\n\n    def pop(self) -> int:\n        \"\"\"\u51fa\u961f\"\"\"\n        num: int = self.peek()\n        # \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        self._front = (self._front + 1) % self.capacity()\n        self._size -= 1\n        return num\n\n    def peek(self) -> int:\n        \"\"\"\u8bbf\u95ee\u961f\u9996\u5143\u7d20\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u961f\u5217\u4e3a\u7a7a\")\n        return self._nums[self._front]\n\n    def to_list(self) -> list[int]:\n        \"\"\"\u8fd4\u56de\u5217\u8868\u7528\u4e8e\u6253\u5370\"\"\"\n        res = [0] * self.size()\n        j: int = self._front\n        for i in range(self.size()):\n            res[i] = self._nums[(j % self.capacity())]\n            j += 1\n        return res\n
array_queue.cpp
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nclass ArrayQueue {\n  private:\n    int *nums;       // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    int front;       // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    int queSize;     // \u961f\u5217\u957f\u5ea6\n    int queCapacity; // \u961f\u5217\u5bb9\u91cf\n\n  public:\n    ArrayQueue(int capacity) {\n        // \u521d\u59cb\u5316\u6570\u7ec4\n        nums = new int[capacity];\n        queCapacity = capacity;\n        front = queSize = 0;\n    }\n\n    ~ArrayQueue() {\n        delete[] nums;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n    int capacity() {\n        return queCapacity;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    int size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    bool isEmpty() {\n        return size() == 0;\n    }\n\n    /* \u5165\u961f */\n    void push(int num) {\n        if (queSize == queCapacity) {\n            cout << \"\u961f\u5217\u5df2\u6ee1\" << endl;\n            return;\n        }\n        // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        int rear = (front + queSize) % queCapacity;\n        // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        nums[rear] = num;\n        queSize++;\n    }\n\n    /* \u51fa\u961f */\n    int pop() {\n        int num = peek();\n        // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        front = (front + 1) % queCapacity;\n        queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    int peek() {\n        if (isEmpty())\n            throw out_of_range(\"\u961f\u5217\u4e3a\u7a7a\");\n        return nums[front];\n    }\n\n    /* \u5c06\u6570\u7ec4\u8f6c\u5316\u4e3a Vector \u5e76\u8fd4\u56de */\n    vector<int> toVector() {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        vector<int> arr(queSize);\n        for (int i = 0, j = front; i < queSize; i++, j++) {\n            arr[i] = nums[j % queCapacity];\n        }\n        return arr;\n    }\n};\n
array_queue.java
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nclass ArrayQueue {\n    private int[] nums; // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    private int front; // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    private int queSize; // \u961f\u5217\u957f\u5ea6\n\n    public ArrayQueue(int capacity) {\n        nums = new int[capacity];\n        front = queSize = 0;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n    public int capacity() {\n        return nums.length;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    public int size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    public boolean isEmpty() {\n        return queSize == 0;\n    }\n\n    /* \u5165\u961f */\n    public void push(int num) {\n        if (queSize == capacity()) {\n            System.out.println(\"\u961f\u5217\u5df2\u6ee1\");\n            return;\n        }\n        // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        int rear = (front + queSize) % capacity();\n        // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        nums[rear] = num;\n        queSize++;\n    }\n\n    /* \u51fa\u961f */\n    public int pop() {\n        int num = peek();\n        // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        front = (front + 1) % capacity();\n        queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    public int peek() {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        return nums[front];\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4 */\n    public int[] toArray() {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        int[] res = new int[queSize];\n        for (int i = 0, j = front; i < queSize; i++, j++) {\n            res[i] = nums[j % capacity()];\n        }\n        return res;\n    }\n}\n
array_queue.cs
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nclass ArrayQueue {\n    int[] nums;  // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    int front;   // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    int queSize; // \u961f\u5217\u957f\u5ea6\n\n    public ArrayQueue(int capacity) {\n        nums = new int[capacity];\n        front = queSize = 0;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n    int Capacity() {\n        return nums.Length;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    public int Size() {\n        return queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    public bool IsEmpty() {\n        return queSize == 0;\n    }\n\n    /* \u5165\u961f */\n    public void Push(int num) {\n        if (queSize == Capacity()) {\n            Console.WriteLine(\"\u961f\u5217\u5df2\u6ee1\");\n            return;\n        }\n        // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        int rear = (front + queSize) % Capacity();\n        // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        nums[rear] = num;\n        queSize++;\n    }\n\n    /* \u51fa\u961f */\n    public int Pop() {\n        int num = Peek();\n        // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        front = (front + 1) % Capacity();\n        queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    public int Peek() {\n        if (IsEmpty())\n            throw new Exception();\n        return nums[front];\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4 */\n    public int[] ToArray() {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        int[] res = new int[queSize];\n        for (int i = 0, j = front; i < queSize; i++, j++) {\n            res[i] = nums[j % this.Capacity()];\n        }\n        return res;\n    }\n}\n
array_queue.go
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\ntype arrayQueue struct {\n    nums        []int // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    front       int   // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    queSize     int   // \u961f\u5217\u957f\u5ea6\n    queCapacity int   // \u961f\u5217\u5bb9\u91cf\uff08\u5373\u6700\u5927\u5bb9\u7eb3\u5143\u7d20\u6570\u91cf\uff09\n}\n\n/* \u521d\u59cb\u5316\u961f\u5217 */\nfunc newArrayQueue(queCapacity int) *arrayQueue {\n    return &arrayQueue{\n        nums:        make([]int, queCapacity),\n        queCapacity: queCapacity,\n        front:       0,\n        queSize:     0,\n    }\n}\n\n/* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\nfunc (q *arrayQueue) size() int {\n    return q.queSize\n}\n\n/* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\nfunc (q *arrayQueue) isEmpty() bool {\n    return q.queSize == 0\n}\n\n/* \u5165\u961f */\nfunc (q *arrayQueue) push(num int) {\n    // \u5f53 rear == queCapacity \u8868\u793a\u961f\u5217\u5df2\u6ee1\n    if q.queSize == q.queCapacity {\n        return\n    }\n    // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n    // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n    rear := (q.front + q.queSize) % q.queCapacity\n    // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n    q.nums[rear] = num\n    q.queSize++\n}\n\n/* \u51fa\u961f */\nfunc (q *arrayQueue) pop() any {\n    num := q.peek()\n    // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n    q.front = (q.front + 1) % q.queCapacity\n    q.queSize--\n    return num\n}\n\n/* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\nfunc (q *arrayQueue) peek() any {\n    if q.isEmpty() {\n        return nil\n    }\n    return q.nums[q.front]\n}\n\n/* \u83b7\u53d6 Slice \u7528\u4e8e\u6253\u5370 */\nfunc (q *arrayQueue) toSlice() []int {\n    rear := (q.front + q.queSize)\n    if rear >= q.queCapacity {\n        rear %= q.queCapacity\n        return append(q.nums[q.front:], q.nums[:rear]...)\n    }\n    return q.nums[q.front:rear]\n}\n
array_queue.swift
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nclass ArrayQueue {\n    private var nums: [Int] // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    private var front = 0 // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    private var queSize = 0 // \u961f\u5217\u957f\u5ea6\n\n    init(capacity: Int) {\n        // \u521d\u59cb\u5316\u6570\u7ec4\n        nums = Array(repeating: 0, count: capacity)\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n    func capacity() -> Int {\n        nums.count\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    func size() -> Int {\n        queSize\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    func isEmpty() -> Bool {\n        queSize == 0\n    }\n\n    /* \u5165\u961f */\n    func push(num: Int) {\n        if size() == capacity() {\n            print(\"\u961f\u5217\u5df2\u6ee1\")\n            return\n        }\n        // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        let rear = (front + queSize) % capacity()\n        // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        nums[rear] = num\n        queSize += 1\n    }\n\n    /* \u51fa\u961f */\n    @discardableResult\n    func pop() -> Int {\n        let num = peek()\n        // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        front = (front + 1) % capacity()\n        queSize -= 1\n        return num\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    func peek() -> Int {\n        if isEmpty() {\n            fatalError(\"\u961f\u5217\u4e3a\u7a7a\")\n        }\n        return nums[front]\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4 */\n    func toArray() -> [Int] {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        var res = Array(repeating: 0, count: queSize)\n        for (i, j) in sequence(first: (0, front), next: { $0 < self.queSize - 1 ? ($0 + 1, $1 + 1) : nil }) {\n            res[i] = nums[j % capacity()]\n        }\n        return res\n    }\n}\n
array_queue.js
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nclass ArrayQueue {\n    #nums; // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    #front = 0; // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    #queSize = 0; // \u961f\u5217\u957f\u5ea6\n\n    constructor(capacity) {\n        this.#nums = new Array(capacity);\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n    get capacity() {\n        return this.#nums.length;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    get size() {\n        return this.#queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    isEmpty() {\n        return this.#queSize === 0;\n    }\n\n    /* \u5165\u961f */\n    push(num) {\n        if (this.size === this.capacity) {\n            console.log('\u961f\u5217\u5df2\u6ee1');\n            return;\n        }\n        // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        const rear = (this.#front + this.size) % this.capacity;\n        // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        this.#nums[rear] = num;\n        this.#queSize++;\n    }\n\n    /* \u51fa\u961f */\n    pop() {\n        const num = this.peek();\n        // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        this.#front = (this.#front + 1) % this.capacity;\n        this.#queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    peek() {\n        if (this.isEmpty()) throw new Error('\u961f\u5217\u4e3a\u7a7a');\n        return this.#nums[this.#front];\n    }\n\n    /* \u8fd4\u56de Array */\n    toArray() {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        const arr = new Array(this.size);\n        for (let i = 0, j = this.#front; i < this.size; i++, j++) {\n            arr[i] = this.#nums[j % this.capacity];\n        }\n        return arr;\n    }\n}\n
array_queue.ts
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nclass ArrayQueue {\n    private nums: number[]; // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    private front: number; // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    private queSize: number; // \u961f\u5217\u957f\u5ea6\n\n    constructor(capacity: number) {\n        this.nums = new Array(capacity);\n        this.front = this.queSize = 0;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n    get capacity(): number {\n        return this.nums.length;\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    get size(): number {\n        return this.queSize;\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    isEmpty(): boolean {\n        return this.queSize === 0;\n    }\n\n    /* \u5165\u961f */\n    push(num: number): void {\n        if (this.size === this.capacity) {\n            console.log('\u961f\u5217\u5df2\u6ee1');\n            return;\n        }\n        // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        const rear = (this.front + this.queSize) % this.capacity;\n        // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        this.nums[rear] = num;\n        this.queSize++;\n    }\n\n    /* \u51fa\u961f */\n    pop(): number {\n        const num = this.peek();\n        // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        this.front = (this.front + 1) % this.capacity;\n        this.queSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    peek(): number {\n        if (this.isEmpty()) throw new Error('\u961f\u5217\u4e3a\u7a7a');\n        return this.nums[this.front];\n    }\n\n    /* \u8fd4\u56de Array */\n    toArray(): number[] {\n        // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n        const arr = new Array(this.size);\n        for (let i = 0, j = this.front; i < this.size; i++, j++) {\n            arr[i] = this.nums[j % this.capacity];\n        }\n        return arr;\n    }\n}\n
array_queue.dart
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nclass ArrayQueue {\n  late List<int> _nums; // \u7528\u4e8e\u50a8\u5b58\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n  late int _front; // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n  late int _queSize; // \u961f\u5217\u957f\u5ea6\n\n  ArrayQueue(int capacity) {\n    _nums = List.filled(capacity, 0);\n    _front = _queSize = 0;\n  }\n\n  /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n  int capaCity() {\n    return _nums.length;\n  }\n\n  /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n  int size() {\n    return _queSize;\n  }\n\n  /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n  bool isEmpty() {\n    return _queSize == 0;\n  }\n\n  /* \u5165\u961f */\n  void push(int _num) {\n    if (_queSize == capaCity()) {\n      throw Exception(\"\u961f\u5217\u5df2\u6ee1\");\n    }\n    // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n    // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n    int rear = (_front + _queSize) % capaCity();\n    // \u5c06 _num \u6dfb\u52a0\u81f3\u961f\u5c3e\n    _nums[rear] = _num;\n    _queSize++;\n  }\n\n  /* \u51fa\u961f */\n  int pop() {\n    int _num = peek();\n    // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n    _front = (_front + 1) % capaCity();\n    _queSize--;\n    return _num;\n  }\n\n  /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n  int peek() {\n    if (isEmpty()) {\n      throw Exception(\"\u961f\u5217\u4e3a\u7a7a\");\n    }\n    return _nums[_front];\n  }\n\n  /* \u8fd4\u56de Array */\n  List<int> toArray() {\n    // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n    final List<int> res = List.filled(_queSize, 0);\n    for (int i = 0, j = _front; i < _queSize; i++, j++) {\n      res[i] = _nums[j % capaCity()];\n    }\n    return res;\n  }\n}\n
array_queue.rs
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\nstruct ArrayQueue {\n    nums: Vec<i32>,     // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    front: i32,         // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    que_size: i32,      // \u961f\u5217\u957f\u5ea6\n    que_capacity: i32,  // \u961f\u5217\u5bb9\u91cf\n}\n\nimpl ArrayQueue {\n    /* \u6784\u9020\u65b9\u6cd5 */\n    fn new(capacity: i32) -> ArrayQueue {\n        ArrayQueue {\n            nums: vec![0; capacity as usize],\n            front: 0,\n            que_size: 0,\n            que_capacity: capacity,\n        }\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\n    fn capacity(&self) -> i32 {\n        self.que_capacity\n    }\n\n    /* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\n    fn size(&self) -> i32 {\n        self.que_size\n    }\n\n    /* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\n    fn is_empty(&self) -> bool {\n        self.que_size == 0\n    }\n\n    /* \u5165\u961f */\n    fn push(&mut self, num: i32) {\n        if self.que_size == self.capacity() {\n            println!(\"\u961f\u5217\u5df2\u6ee1\");\n            return;\n        }\n        // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n        // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n        let rear = (self.front + self.que_size) % self.que_capacity;\n        // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n        self.nums[rear as usize] = num;\n        self.que_size += 1;\n    }\n\n    /* \u51fa\u961f */\n    fn pop(&mut self) -> i32 {\n        let num = self.peek();\n        // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n        self.front = (self.front + 1) % self.que_capacity;\n        self.que_size -= 1;\n        num\n    }\n\n    /* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\n    fn peek(&self) -> i32 {\n        if self.is_empty() {\n            panic!(\"index out of bounds\");\n        }\n        self.nums[self.front as usize]\n    }\n\n    /* \u8fd4\u56de\u6570\u7ec4 */\n    fn to_vector(&self) -> Vec<i32> {\n        let cap = self.que_capacity;\n        let mut j = self.front;\n        let mut arr = vec![0; self.que_size as usize];\n        for i in 0..self.que_size {\n            arr[i as usize] = self.nums[(j % cap) as usize];\n            j += 1;\n        }\n        arr\n    }\n}\n
array_queue.c
/* \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217 */\ntypedef struct {\n    int *nums;       // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4\n    int front;       // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n    int queSize;     // \u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e + 1\n    int queCapacity; // \u961f\u5217\u5bb9\u91cf\n} ArrayQueue;\n\n/* \u6784\u9020\u51fd\u6570 */\nArrayQueue *newArrayQueue(int capacity) {\n    ArrayQueue *queue = (ArrayQueue *)malloc(sizeof(ArrayQueue));\n    // \u521d\u59cb\u5316\u6570\u7ec4\n    queue->queCapacity = capacity;\n    queue->nums = (int *)malloc(sizeof(int) * queue->queCapacity);\n    queue->front = queue->queSize = 0;\n    return queue;\n}\n\n/* \u6790\u6784\u51fd\u6570 */\nvoid delArrayQueue(ArrayQueue *queue) {\n    free(queue->nums);\n    free(queue);\n}\n\n/* \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf */\nint capacity(ArrayQueue *queue) {\n    return queue->queCapacity;\n}\n\n/* \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6 */\nint size(ArrayQueue *queue) {\n    return queue->queSize;\n}\n\n/* \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a */\nbool empty(ArrayQueue *queue) {\n    return queue->queSize == 0;\n}\n\n/* \u8bbf\u95ee\u961f\u9996\u5143\u7d20 */\nint peek(ArrayQueue *queue) {\n    assert(size(queue) != 0);\n    return queue->nums[queue->front];\n}\n\n/* \u5165\u961f */\nvoid push(ArrayQueue *queue, int num) {\n    if (size(queue) == capacity(queue)) {\n        printf(\"\u961f\u5217\u5df2\u6ee1\\r\\n\");\n        return;\n    }\n    // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n    // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n    int rear = (queue->front + queue->queSize) % queue->queCapacity;\n    // \u5c06 num \u6dfb\u52a0\u81f3\u961f\u5c3e\n    queue->nums[rear] = num;\n    queue->queSize++;\n}\n\n/* \u51fa\u961f */\nint pop(ArrayQueue *queue) {\n    int num = peek(queue);\n    // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n    queue->front = (queue->front + 1) % queue->queCapacity;\n    queue->queSize--;\n    return num;\n}\n
array_queue.zig
// \u57fa\u4e8e\u73af\u5f62\u6570\u7ec4\u5b9e\u73b0\u7684\u961f\u5217\nfn ArrayQueue(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        nums: []T = undefined,                          // \u7528\u4e8e\u5b58\u50a8\u961f\u5217\u5143\u7d20\u7684\u6570\u7ec4     \n        cap: usize = 0,                                 // \u961f\u5217\u5bb9\u91cf\n        front: usize = 0,                               // \u961f\u9996\u6307\u9488\uff0c\u6307\u5411\u961f\u9996\u5143\u7d20\n        queSize: usize = 0,                             // \u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e + 1\n        mem_arena: ?std.heap.ArenaAllocator = null,\n        mem_allocator: std.mem.Allocator = undefined,   // \u5185\u5b58\u5206\u914d\u5668\n\n        // \u6784\u9020\u51fd\u6570\uff08\u5206\u914d\u5185\u5b58+\u521d\u59cb\u5316\u6570\u7ec4\uff09\n        pub fn init(self: *Self, allocator: std.mem.Allocator, cap: usize) !void {\n            if (self.mem_arena == null) {\n                self.mem_arena = std.heap.ArenaAllocator.init(allocator);\n                self.mem_allocator = self.mem_arena.?.allocator();\n            }\n            self.cap = cap;\n            self.nums = try self.mem_allocator.alloc(T, self.cap);\n            @memset(self.nums, @as(T, 0));\n        }\n\n        // \u6790\u6784\u51fd\u6570\uff08\u91ca\u653e\u5185\u5b58\uff09\n        pub fn deinit(self: *Self) void {\n            if (self.mem_arena == null) return;\n            self.mem_arena.?.deinit();\n        }\n\n        // \u83b7\u53d6\u961f\u5217\u7684\u5bb9\u91cf\n        pub fn capacity(self: *Self) usize {\n            return self.cap;\n        }\n\n        // \u83b7\u53d6\u961f\u5217\u7684\u957f\u5ea6\n        pub fn size(self: *Self) usize {\n            return self.queSize;\n        }\n\n        // \u5224\u65ad\u961f\u5217\u662f\u5426\u4e3a\u7a7a\n        pub fn isEmpty(self: *Self) bool {\n            return self.queSize == 0;\n        }\n\n        // \u5165\u961f\n        pub fn push(self: *Self, num: T) !void {\n            if (self.size() == self.capacity()) {\n                std.debug.print(\"\u961f\u5217\u5df2\u6ee1\\n\", .{});\n                return;\n            }\n            // \u8ba1\u7b97\u961f\u5c3e\u6307\u9488\uff0c\u6307\u5411\u961f\u5c3e\u7d22\u5f15 + 1\n            // \u901a\u8fc7\u53d6\u4f59\u64cd\u4f5c\u5b9e\u73b0 rear \u8d8a\u8fc7\u6570\u7ec4\u5c3e\u90e8\u540e\u56de\u5230\u5934\u90e8\n            var rear = (self.front + self.queSize) % self.capacity();\n            // \u5728\u5c3e\u8282\u70b9\u540e\u6dfb\u52a0 num\n            self.nums[rear] = num;\n            self.queSize += 1;\n        } \n\n        // \u51fa\u961f\n        pub fn pop(self: *Self) T {\n            var num = self.peek();\n            // \u961f\u9996\u6307\u9488\u5411\u540e\u79fb\u52a8\u4e00\u4f4d\uff0c\u82e5\u8d8a\u8fc7\u5c3e\u90e8\uff0c\u5219\u8fd4\u56de\u5230\u6570\u7ec4\u5934\u90e8\n            self.front = (self.front + 1) % self.capacity();\n            self.queSize -= 1;\n            return num;\n        } \n\n        // \u8bbf\u95ee\u961f\u9996\u5143\u7d20\n        pub fn peek(self: *Self) T {\n            if (self.isEmpty()) @panic(\"\u961f\u5217\u4e3a\u7a7a\");\n            return self.nums[self.front];\n        } \n\n        // \u8fd4\u56de\u6570\u7ec4\n        pub fn toArray(self: *Self) ![]T {\n            // \u4ec5\u8f6c\u6362\u6709\u6548\u957f\u5ea6\u8303\u56f4\u5185\u7684\u5217\u8868\u5143\u7d20\n            var res = try self.mem_allocator.alloc(T, self.size());\n            @memset(res, @as(T, 0));\n            var i: usize = 0;\n            var j: usize = self.front;\n            while (i < self.size()) : ({ i += 1; j += 1; }) {\n                res[i] = self.nums[j % self.capacity()];\n            }\n            return res;\n        }\n    };\n}\n
Visualizing Code

Full Screen >

The above implementation of the queue still has limitations: its length is fixed. However, this issue is not difficult to resolve. We can replace the array with a dynamic array to introduce an expansion mechanism. Interested readers can try to implement this themselves.

The comparison of the two implementations is consistent with that of the stack and is not repeated here.

"},{"location":"chapter_stack_and_queue/queue/#523-typical-applications-of-queue","title":"5.2.3 \u00a0 Typical Applications of Queue","text":"
  • Amazon Orders. After shoppers place orders, these orders join a queue, and the system processes them in order. During events like Singles' Day, a massive number of orders are generated in a short time, making high concurrency a key challenge for engineers.
  • Various To-Do Lists. Any scenario requiring a \"first-come, first-served\" functionality, such as a printer's task queue or a restaurant's food delivery queue, can effectively maintain the order of processing with a queue.
"},{"location":"chapter_stack_and_queue/stack/","title":"5.1 \u00a0 Stack","text":"

\"Stack\" is a linear data structure that follows the principle of Last-In-First-Out (LIFO).

We can compare a stack to a pile of plates on a table. To access the bottom plate, one must remove the plates on top. If we replace the plates with various types of elements (such as integers, characters, objects, etc.), we obtain the data structure known as a stack.

As shown in the following figure, we refer to the top of the pile of elements as the \"top of the stack\" and the bottom as the \"bottom of the stack.\" The operation of adding elements to the top of the stack is called \"push,\" and the operation of removing the top element is called \"pop.\"

Figure 5-1 \u00a0 Stack's Last-In-First-Out Rule

"},{"location":"chapter_stack_and_queue/stack/#511-common-operations-on-stack","title":"5.1.1 \u00a0 Common Operations on Stack","text":"

The common operations on a stack are shown in the Table 5-1 . The specific method names depend on the programming language used. Here, we use push(), pop(), and peek() as examples.

Table 5-1 \u00a0 Efficiency of Stack Operations

Method Description Time Complexity push() Push an element onto the stack (add to the top) \\(O(1)\\) pop() Pop the top element from the stack \\(O(1)\\) peek() Access the top element of the stack \\(O(1)\\)

Typically, we can directly use the stack class built into the programming language. However, some languages may not specifically provide a stack class. In these cases, we can use the language's \"array\" or \"linked list\" as a stack and ignore operations that are not related to stack logic in the program.

PythonC++JavaC#GoSwiftJSTSDartRustCZig stack.py
# Initialize the stack\n# Python does not have a built-in stack class, so a list can be used as a stack\nstack: list[int] = []\n\n# Push elements onto the stack\nstack.append(1)\nstack.append(3)\nstack.append(2)\nstack.append(5)\nstack.append(4)\n\n# Access the top element of the stack\npeek: int = stack[-1]\n\n# Pop an element from the stack\npop: int = stack.pop()\n\n# Get the length of the stack\nsize: int = len(stack)\n\n# Check if the stack is empty\nis_empty: bool = len(stack) == 0\n
stack.cpp
/* Initialize the stack */\nstack<int> stack;\n\n/* Push elements onto the stack */\nstack.push(1);\nstack.push(3);\nstack.push(2);\nstack.push(5);\nstack.push(4);\n\n/* Access the top element of the stack */\nint top = stack.top();\n\n/* Pop an element from the stack */\nstack.pop(); // No return value\n\n/* Get the length of the stack */\nint size = stack.size();\n\n/* Check if the stack is empty */\nbool empty = stack.empty();\n
stack.java
/* Initialize the stack */\nStack<Integer> stack = new Stack<>();\n\n/* Push elements onto the stack */\nstack.push(1);\nstack.push(3);\nstack.push(2);\nstack.push(5);\nstack.push(4);\n\n/* Access the top element of the stack */\nint peek = stack.peek();\n\n/* Pop an element from the stack */\nint pop = stack.pop();\n\n/* Get the length of the stack */\nint size = stack.size();\n\n/* Check if the stack is empty */\nboolean isEmpty = stack.isEmpty();\n
stack.cs
/* Initialize the stack */\nStack<int> stack = new();\n\n/* Push elements onto the stack */\nstack.Push(1);\nstack.Push(3);\nstack.Push(2);\nstack.Push(5);\nstack.Push(4);\n\n/* Access the top element of the stack */\nint peek = stack.Peek();\n\n/* Pop an element from the stack */\nint pop = stack.Pop();\n\n/* Get the length of the stack */\nint size = stack.Count;\n\n/* Check if the stack is empty */\nbool isEmpty = stack.Count == 0;\n
stack_test.go
/* Initialize the stack */\n// In Go, it is recommended to use a Slice as a stack\nvar stack []int\n\n/* Push elements onto the stack */\nstack = append(stack, 1)\nstack = append(stack, 3)\nstack = append(stack, 2)\nstack = append(stack, 5)\nstack = append(stack, 4)\n\n/* Access the top element of the stack */\npeek := stack[len(stack)-1]\n\n/* Pop an element from the stack */\npop := stack[len(stack)-1]\nstack = stack[:len(stack)-1]\n\n/* Get the length of the stack */\nsize := len(stack)\n\n/* Check if the stack is empty */\nisEmpty := len(stack) == 0\n
stack.swift
/* Initialize the stack */\n// Swift does not have a built-in stack class, so Array can be used as a stack\nvar stack: [Int] = []\n\n/* Push elements onto the stack */\nstack.append(1)\nstack.append(3)\nstack.append(2)\nstack.append(5)\nstack.append(4)\n\n/* Access the top element of the stack */\nlet peek = stack.last!\n\n/* Pop an element from the stack */\nlet pop = stack.removeLast()\n\n/* Get the length of the stack */\nlet size = stack.count\n\n/* Check if the stack is empty */\nlet isEmpty = stack.isEmpty\n
stack.js
/* Initialize the stack */\n// JavaScript does not have a built-in stack class, so Array can be used as a stack\nconst stack = [];\n\n/* Push elements onto the stack */\nstack.push(1);\nstack.push(3);\nstack.push(2);\nstack.push(5);\nstack.push(4);\n\n/* Access the top element of the stack */\nconst peek = stack[stack.length-1];\n\n/* Pop an element from the stack */\nconst pop = stack.pop();\n\n/* Get the length of the stack */\nconst size = stack.length;\n\n/* Check if the stack is empty */\nconst is_empty = stack.length === 0;\n
stack.ts
/* Initialize the stack */\n// TypeScript does not have a built-in stack class, so Array can be used as a stack\nconst stack: number[] = [];\n\n/* Push elements onto the stack */\nstack.push(1);\nstack.push(3);\nstack.push(2);\nstack.push(5);\nstack.push(4);\n\n/* Access the top element of the stack */\nconst peek = stack[stack.length - 1];\n\n/* Pop an element from the stack */\nconst pop = stack.pop();\n\n/* Get the length of the stack */\nconst size = stack.length;\n\n/* Check if the stack is empty */\nconst is_empty = stack.length === 0;\n
stack.dart
/* Initialize the stack */\n// Dart does not have a built-in stack class, so List can be used as a stack\nList<int> stack = [];\n\n/* Push elements onto the stack */\nstack.add(1);\nstack.add(3);\nstack.add(2);\nstack.add(5);\nstack.add(4);\n\n/* Access the top element of the stack */\nint peek = stack.last;\n\n/* Pop an element from the stack */\nint pop = stack.removeLast();\n\n/* Get the length of the stack */\nint size = stack.length;\n\n/* Check if the stack is empty */\nbool isEmpty = stack.isEmpty;\n
stack.rs
/* Initialize the stack */\n// Use Vec as a stack\nlet mut stack: Vec<i32> = Vec::new();\n\n/* Push elements onto the stack */\nstack.push(1);\nstack.push(3);\nstack.push(2);\nstack.push(5);\nstack.push(4);\n\n/* Access the top element of the stack */\nlet top = stack.last().unwrap();\n\n/* Pop an element from the stack */\nlet pop = stack.pop().unwrap();\n\n/* Get the length of the stack */\nlet size = stack.len();\n\n/* Check if the stack is empty */\nlet is_empty = stack.is_empty();\n
stack.c
// C does not provide a built-in stack\n
stack.zig
\n
Visualizing Code

Full Screen >

"},{"location":"chapter_stack_and_queue/stack/#512-implementing-a-stack","title":"5.1.2 \u00a0 Implementing a Stack","text":"

To understand the mechanics of a stack more deeply, let's try implementing a stack class ourselves.

A stack follows the principle of Last-In-First-Out, which means we can only add or remove elements at the top of the stack. However, both arrays and linked lists allow adding and removing elements at any position, therefore a stack can be seen as a restricted array or linked list. In other words, we can \"mask\" some unrelated operations of arrays or linked lists to make their logic conform to the characteristics of a stack.

"},{"location":"chapter_stack_and_queue/stack/#1-implementation-based-on-linked-list","title":"1. \u00a0 Implementation Based on Linked List","text":"

When implementing a stack using a linked list, we can consider the head node of the list as the top of the stack and the tail node as the bottom of the stack.

As shown in the Figure 5-2 , for the push operation, we simply insert elements at the head of the linked list. This method of node insertion is known as \"head insertion.\" For the pop operation, we just need to remove the head node from the list.

LinkedListStackpush()pop()

Figure 5-2 \u00a0 Implementing Stack with Linked List for Push and Pop Operations

Below is an example code for implementing a stack based on a linked list:

PythonC++JavaC#GoSwiftJSTSDartRustCZig linkedlist_stack.py
class LinkedListStack:\n    \"\"\"\u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808\"\"\"\n\n    def __init__(self):\n        \"\"\"\u6784\u9020\u65b9\u6cd5\"\"\"\n        self._peek: ListNode | None = None\n        self._size: int = 0\n\n    def size(self) -> int:\n        \"\"\"\u83b7\u53d6\u6808\u7684\u957f\u5ea6\"\"\"\n        return self._size\n\n    def is_empty(self) -> bool:\n        \"\"\"\u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a\"\"\"\n        return not self._peek\n\n    def push(self, val: int):\n        \"\"\"\u5165\u6808\"\"\"\n        node = ListNode(val)\n        node.next = self._peek\n        self._peek = node\n        self._size += 1\n\n    def pop(self) -> int:\n        \"\"\"\u51fa\u6808\"\"\"\n        num = self.peek()\n        self._peek = self._peek.next\n        self._size -= 1\n        return num\n\n    def peek(self) -> int:\n        \"\"\"\u8bbf\u95ee\u6808\u9876\u5143\u7d20\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u6808\u4e3a\u7a7a\")\n        return self._peek.val\n\n    def to_list(self) -> list[int]:\n        \"\"\"\u8f6c\u5316\u4e3a\u5217\u8868\u7528\u4e8e\u6253\u5370\"\"\"\n        arr = []\n        node = self._peek\n        while node:\n            arr.append(node.val)\n            node = node.next\n        arr.reverse()\n        return arr\n
linkedlist_stack.cpp
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\nclass LinkedListStack {\n  private:\n    ListNode *stackTop; // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    int stkSize;        // \u6808\u7684\u957f\u5ea6\n\n  public:\n    LinkedListStack() {\n        stackTop = nullptr;\n        stkSize = 0;\n    }\n\n    ~LinkedListStack() {\n        // \u904d\u5386\u94fe\u8868\u5220\u9664\u8282\u70b9\uff0c\u91ca\u653e\u5185\u5b58\n        freeMemoryLinkedList(stackTop);\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    int size() {\n        return stkSize;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    bool isEmpty() {\n        return size() == 0;\n    }\n\n    /* \u5165\u6808 */\n    void push(int num) {\n        ListNode *node = new ListNode(num);\n        node->next = stackTop;\n        stackTop = node;\n        stkSize++;\n    }\n\n    /* \u51fa\u6808 */\n    int pop() {\n        int num = top();\n        ListNode *tmp = stackTop;\n        stackTop = stackTop->next;\n        // \u91ca\u653e\u5185\u5b58\n        delete tmp;\n        stkSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    int top() {\n        if (isEmpty())\n            throw out_of_range(\"\u6808\u4e3a\u7a7a\");\n        return stackTop->val;\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    vector<int> toVector() {\n        ListNode *node = stackTop;\n        vector<int> res(size());\n        for (int i = res.size() - 1; i >= 0; i--) {\n            res[i] = node->val;\n            node = node->next;\n        }\n        return res;\n    }\n};\n
linkedlist_stack.java
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\nclass LinkedListStack {\n    private ListNode stackPeek; // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    private int stkSize = 0; // \u6808\u7684\u957f\u5ea6\n\n    public LinkedListStack() {\n        stackPeek = null;\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    public int size() {\n        return stkSize;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /* \u5165\u6808 */\n    public void push(int num) {\n        ListNode node = new ListNode(num);\n        node.next = stackPeek;\n        stackPeek = node;\n        stkSize++;\n    }\n\n    /* \u51fa\u6808 */\n    public int pop() {\n        int num = peek();\n        stackPeek = stackPeek.next;\n        stkSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    public int peek() {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        return stackPeek.val;\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    public int[] toArray() {\n        ListNode node = stackPeek;\n        int[] res = new int[size()];\n        for (int i = res.length - 1; i >= 0; i--) {\n            res[i] = node.val;\n            node = node.next;\n        }\n        return res;\n    }\n}\n
linkedlist_stack.cs
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\nclass LinkedListStack {\n    ListNode? stackPeek;  // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    int stkSize = 0;   // \u6808\u7684\u957f\u5ea6\n\n    public LinkedListStack() {\n        stackPeek = null;\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    public int Size() {\n        return stkSize;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    public bool IsEmpty() {\n        return Size() == 0;\n    }\n\n    /* \u5165\u6808 */\n    public void Push(int num) {\n        ListNode node = new(num) {\n            next = stackPeek\n        };\n        stackPeek = node;\n        stkSize++;\n    }\n\n    /* \u51fa\u6808 */\n    public int Pop() {\n        int num = Peek();\n        stackPeek = stackPeek!.next;\n        stkSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    public int Peek() {\n        if (IsEmpty())\n            throw new Exception();\n        return stackPeek!.val;\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    public int[] ToArray() {\n        if (stackPeek == null)\n            return [];\n\n        ListNode? node = stackPeek;\n        int[] res = new int[Size()];\n        for (int i = res.Length - 1; i >= 0; i--) {\n            res[i] = node!.val;\n            node = node.next;\n        }\n        return res;\n    }\n}\n
linkedlist_stack.go
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\ntype linkedListStack struct {\n    // \u4f7f\u7528\u5185\u7f6e\u5305 list \u6765\u5b9e\u73b0\u6808\n    data *list.List\n}\n\n/* \u521d\u59cb\u5316\u6808 */\nfunc newLinkedListStack() *linkedListStack {\n    return &linkedListStack{\n        data: list.New(),\n    }\n}\n\n/* \u5165\u6808 */\nfunc (s *linkedListStack) push(value int) {\n    s.data.PushBack(value)\n}\n\n/* \u51fa\u6808 */\nfunc (s *linkedListStack) pop() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Back()\n    s.data.Remove(e)\n    return e.Value\n}\n\n/* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\nfunc (s *linkedListStack) peek() any {\n    if s.isEmpty() {\n        return nil\n    }\n    e := s.data.Back()\n    return e.Value\n}\n\n/* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\nfunc (s *linkedListStack) size() int {\n    return s.data.Len()\n}\n\n/* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\nfunc (s *linkedListStack) isEmpty() bool {\n    return s.data.Len() == 0\n}\n\n/* \u83b7\u53d6 List \u7528\u4e8e\u6253\u5370 */\nfunc (s *linkedListStack) toList() *list.List {\n    return s.data\n}\n
linkedlist_stack.swift
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\nclass LinkedListStack {\n    private var _peek: ListNode? // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    private var _size = 0 // \u6808\u7684\u957f\u5ea6\n\n    init() {}\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    func size() -> Int {\n        _size\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    func isEmpty() -> Bool {\n        size() == 0\n    }\n\n    /* \u5165\u6808 */\n    func push(num: Int) {\n        let node = ListNode(x: num)\n        node.next = _peek\n        _peek = node\n        _size += 1\n    }\n\n    /* \u51fa\u6808 */\n    @discardableResult\n    func pop() -> Int {\n        let num = peek()\n        _peek = _peek?.next\n        _size -= 1\n        return num\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    func peek() -> Int {\n        if isEmpty() {\n            fatalError(\"\u6808\u4e3a\u7a7a\")\n        }\n        return _peek!.val\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    func toArray() -> [Int] {\n        var node = _peek\n        var res = Array(repeating: 0, count: _size)\n        for i in sequence(first: res.count - 1, next: { $0 >= 0 + 1 ? $0 - 1 : nil }) {\n            res[i] = node!.val\n            node = node?.next\n        }\n        return res\n    }\n}\n
linkedlist_stack.js
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\nclass LinkedListStack {\n    #stackPeek; // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    #stkSize = 0; // \u6808\u7684\u957f\u5ea6\n\n    constructor() {\n        this.#stackPeek = null;\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    get size() {\n        return this.#stkSize;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    isEmpty() {\n        return this.size === 0;\n    }\n\n    /* \u5165\u6808 */\n    push(num) {\n        const node = new ListNode(num);\n        node.next = this.#stackPeek;\n        this.#stackPeek = node;\n        this.#stkSize++;\n    }\n\n    /* \u51fa\u6808 */\n    pop() {\n        const num = this.peek();\n        this.#stackPeek = this.#stackPeek.next;\n        this.#stkSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    peek() {\n        if (!this.#stackPeek) throw new Error('\u6808\u4e3a\u7a7a');\n        return this.#stackPeek.val;\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    toArray() {\n        let node = this.#stackPeek;\n        const res = new Array(this.size);\n        for (let i = res.length - 1; i >= 0; i--) {\n            res[i] = node.val;\n            node = node.next;\n        }\n        return res;\n    }\n}\n
linkedlist_stack.ts
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\nclass LinkedListStack {\n    private stackPeek: ListNode | null; // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    private stkSize: number = 0; // \u6808\u7684\u957f\u5ea6\n\n    constructor() {\n        this.stackPeek = null;\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    get size(): number {\n        return this.stkSize;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    isEmpty(): boolean {\n        return this.size === 0;\n    }\n\n    /* \u5165\u6808 */\n    push(num: number): void {\n        const node = new ListNode(num);\n        node.next = this.stackPeek;\n        this.stackPeek = node;\n        this.stkSize++;\n    }\n\n    /* \u51fa\u6808 */\n    pop(): number {\n        const num = this.peek();\n        if (!this.stackPeek) throw new Error('\u6808\u4e3a\u7a7a');\n        this.stackPeek = this.stackPeek.next;\n        this.stkSize--;\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    peek(): number {\n        if (!this.stackPeek) throw new Error('\u6808\u4e3a\u7a7a');\n        return this.stackPeek.val;\n    }\n\n    /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    toArray(): number[] {\n        let node = this.stackPeek;\n        const res = new Array<number>(this.size);\n        for (let i = res.length - 1; i >= 0; i--) {\n            res[i] = node!.val;\n            node = node!.next;\n        }\n        return res;\n    }\n}\n
linkedlist_stack.dart
/* \u57fa\u4e8e\u94fe\u8868\u7c7b\u5b9e\u73b0\u7684\u6808 */\nclass LinkedListStack {\n  ListNode? _stackPeek; // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n  int _stkSize = 0; // \u6808\u7684\u957f\u5ea6\n\n  LinkedListStack() {\n    _stackPeek = null;\n  }\n\n  /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n  int size() {\n    return _stkSize;\n  }\n\n  /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n  bool isEmpty() {\n    return _stkSize == 0;\n  }\n\n  /* \u5165\u6808 */\n  void push(int _num) {\n    final ListNode node = ListNode(_num);\n    node.next = _stackPeek;\n    _stackPeek = node;\n    _stkSize++;\n  }\n\n  /* \u51fa\u6808 */\n  int pop() {\n    final int _num = peek();\n    _stackPeek = _stackPeek!.next;\n    _stkSize--;\n    return _num;\n  }\n\n  /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n  int peek() {\n    if (_stackPeek == null) {\n      throw Exception(\"\u6808\u4e3a\u7a7a\");\n    }\n    return _stackPeek!.val;\n  }\n\n  /* \u5c06\u94fe\u8868\u8f6c\u5316\u4e3a List \u5e76\u8fd4\u56de */\n  List<int> toList() {\n    ListNode? node = _stackPeek;\n    List<int> list = [];\n    while (node != null) {\n      list.add(node.val);\n      node = node.next;\n    }\n    list = list.reversed.toList();\n    return list;\n  }\n}\n
linkedlist_stack.rs
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\n#[allow(dead_code)]\npub struct LinkedListStack<T> {\n    stack_peek: Option<Rc<RefCell<ListNode<T>>>>,   // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    stk_size: usize,                                // \u6808\u7684\u957f\u5ea6\n}\n\nimpl<T: Copy> LinkedListStack<T> {\n    pub fn new() -> Self {\n        Self {\n            stack_peek: None,\n            stk_size: 0,\n        }\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    pub fn size(&self) -> usize {\n        return self.stk_size;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    pub fn is_empty(&self) -> bool {\n        return self.size() == 0;\n    }\n\n    /* \u5165\u6808 */\n    pub fn push(&mut self, num: T) {\n        let node = ListNode::new(num);\n        node.borrow_mut().next = self.stack_peek.take();\n        self.stack_peek = Some(node);\n        self.stk_size += 1;\n    }\n\n    /* \u51fa\u6808 */\n    pub fn pop(&mut self) -> Option<T> {\n        self.stack_peek.take().map(|old_head| {\n            match old_head.borrow_mut().next.take() {\n                Some(new_head) => {\n                    self.stack_peek = Some(new_head);\n                }\n                None => {\n                    self.stack_peek = None;\n                }\n            }\n            self.stk_size -= 1;\n            Rc::try_unwrap(old_head).ok().unwrap().into_inner().val\n        })\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    pub fn peek(&self) -> Option<&Rc<RefCell<ListNode<T>>>> {\n        self.stack_peek.as_ref()\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    pub fn to_array(&self, head: Option<&Rc<RefCell<ListNode<T>>>>) -> Vec<T> {\n        if let Some(node) = head {\n            let mut nums = self.to_array(node.borrow().next.as_ref());\n            nums.push(node.borrow().val);\n            return nums;\n        }\n        return Vec::new();\n    }\n}\n
linkedlist_stack.c
/* \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808 */\ntypedef struct {\n    ListNode *top; // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n    int size;      // \u6808\u7684\u957f\u5ea6\n} LinkedListStack;\n\n/* \u6784\u9020\u51fd\u6570 */\nLinkedListStack *newLinkedListStack() {\n    LinkedListStack *s = malloc(sizeof(LinkedListStack));\n    s->top = NULL;\n    s->size = 0;\n    return s;\n}\n\n/* \u6790\u6784\u51fd\u6570 */\nvoid delLinkedListStack(LinkedListStack *s) {\n    while (s->top) {\n        ListNode *n = s->top->next;\n        free(s->top);\n        s->top = n;\n    }\n    free(s);\n}\n\n/* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\nint size(LinkedListStack *s) {\n    return s->size;\n}\n\n/* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\nbool isEmpty(LinkedListStack *s) {\n    return size(s) == 0;\n}\n\n/* \u5165\u6808 */\nvoid push(LinkedListStack *s, int num) {\n    ListNode *node = (ListNode *)malloc(sizeof(ListNode));\n    node->next = s->top; // \u66f4\u65b0\u65b0\u52a0\u8282\u70b9\u6307\u9488\u57df\n    node->val = num;     // \u66f4\u65b0\u65b0\u52a0\u8282\u70b9\u6570\u636e\u57df\n    s->top = node;       // \u66f4\u65b0\u6808\u9876\n    s->size++;           // \u66f4\u65b0\u6808\u5927\u5c0f\n}\n\n/* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\nint peek(LinkedListStack *s) {\n    if (s->size == 0) {\n        printf(\"\u6808\u4e3a\u7a7a\\n\");\n        return INT_MAX;\n    }\n    return s->top->val;\n}\n\n/* \u51fa\u6808 */\nint pop(LinkedListStack *s) {\n    int val = peek(s);\n    ListNode *tmp = s->top;\n    s->top = s->top->next;\n    // \u91ca\u653e\u5185\u5b58\n    free(tmp);\n    s->size--;\n    return val;\n}\n
linkedlist_stack.zig
// \u57fa\u4e8e\u94fe\u8868\u5b9e\u73b0\u7684\u6808\nfn LinkedListStack(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        stack_top: ?*inc.ListNode(T) = null,             // \u5c06\u5934\u8282\u70b9\u4f5c\u4e3a\u6808\u9876\n        stk_size: usize = 0,                             // \u6808\u7684\u957f\u5ea6\n        mem_arena: ?std.heap.ArenaAllocator = null,\n        mem_allocator: std.mem.Allocator = undefined,    // \u5185\u5b58\u5206\u914d\u5668\n\n        // \u6784\u9020\u51fd\u6570\uff08\u5206\u914d\u5185\u5b58+\u521d\u59cb\u5316\u6808\uff09\n        pub fn init(self: *Self, allocator: std.mem.Allocator) !void {\n            if (self.mem_arena == null) {\n                self.mem_arena = std.heap.ArenaAllocator.init(allocator);\n                self.mem_allocator = self.mem_arena.?.allocator();\n            }\n            self.stack_top = null;\n            self.stk_size = 0;\n        }\n\n        // \u6790\u6784\u51fd\u6570\uff08\u91ca\u653e\u5185\u5b58\uff09\n        pub fn deinit(self: *Self) void {\n            if (self.mem_arena == null) return;\n            self.mem_arena.?.deinit();\n        }\n\n        // \u83b7\u53d6\u6808\u7684\u957f\u5ea6\n        pub fn size(self: *Self) usize {\n            return self.stk_size;\n        }\n\n        // \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a\n        pub fn isEmpty(self: *Self) bool {\n            return self.size() == 0;\n        }\n\n        // \u8bbf\u95ee\u6808\u9876\u5143\u7d20\n        pub fn peek(self: *Self) T {\n            if (self.size() == 0) @panic(\"\u6808\u4e3a\u7a7a\");\n            return self.stack_top.?.val;\n        }  \n\n        // \u5165\u6808\n        pub fn push(self: *Self, num: T) !void {\n            var node = try self.mem_allocator.create(inc.ListNode(T));\n            node.init(num);\n            node.next = self.stack_top;\n            self.stack_top = node;\n            self.stk_size += 1;\n        } \n\n        // \u51fa\u6808\n        pub fn pop(self: *Self) T {\n            var num = self.peek();\n            self.stack_top = self.stack_top.?.next;\n            self.stk_size -= 1;\n            return num;\n        } \n\n        // \u5c06\u6808\u8f6c\u6362\u4e3a\u6570\u7ec4\n        pub fn toArray(self: *Self) ![]T {\n            var node = self.stack_top;\n            var res = try self.mem_allocator.alloc(T, self.size());\n            @memset(res, @as(T, 0));\n            var i: usize = 0;\n            while (i < res.len) : (i += 1) {\n                res[res.len - i - 1] = node.?.val;\n                node = node.?.next;\n            }\n            return res;\n        }\n    };\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_stack_and_queue/stack/#2-implementation-based-on-array","title":"2. \u00a0 Implementation Based on Array","text":"

When implementing a stack using an array, we can consider the end of the array as the top of the stack. As shown in the Figure 5-3 , push and pop operations correspond to adding and removing elements at the end of the array, respectively, both with a time complexity of \\(O(1)\\).

ArrayStackpush()pop()

Figure 5-3 \u00a0 Implementing Stack with Array for Push and Pop Operations

Since the elements to be pushed onto the stack may continuously increase, we can use a dynamic array, thus avoiding the need to handle array expansion ourselves. Here is an example code:

PythonC++JavaC#GoSwiftJSTSDartRustCZig array_stack.py
class ArrayStack:\n    \"\"\"\u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808\"\"\"\n\n    def __init__(self):\n        \"\"\"\u6784\u9020\u65b9\u6cd5\"\"\"\n        self._stack: list[int] = []\n\n    def size(self) -> int:\n        \"\"\"\u83b7\u53d6\u6808\u7684\u957f\u5ea6\"\"\"\n        return len(self._stack)\n\n    def is_empty(self) -> bool:\n        \"\"\"\u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a\"\"\"\n        return self._stack == []\n\n    def push(self, item: int):\n        \"\"\"\u5165\u6808\"\"\"\n        self._stack.append(item)\n\n    def pop(self) -> int:\n        \"\"\"\u51fa\u6808\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u6808\u4e3a\u7a7a\")\n        return self._stack.pop()\n\n    def peek(self) -> int:\n        \"\"\"\u8bbf\u95ee\u6808\u9876\u5143\u7d20\"\"\"\n        if self.is_empty():\n            raise IndexError(\"\u6808\u4e3a\u7a7a\")\n        return self._stack[-1]\n\n    def to_list(self) -> list[int]:\n        \"\"\"\u8fd4\u56de\u5217\u8868\u7528\u4e8e\u6253\u5370\"\"\"\n        return self._stack\n
array_stack.cpp
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nclass ArrayStack {\n  private:\n    vector<int> stack;\n\n  public:\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    int size() {\n        return stack.size();\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    bool isEmpty() {\n        return stack.size() == 0;\n    }\n\n    /* \u5165\u6808 */\n    void push(int num) {\n        stack.push_back(num);\n    }\n\n    /* \u51fa\u6808 */\n    int pop() {\n        int num = top();\n        stack.pop_back();\n        return num;\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    int top() {\n        if (isEmpty())\n            throw out_of_range(\"\u6808\u4e3a\u7a7a\");\n        return stack.back();\n    }\n\n    /* \u8fd4\u56de Vector */\n    vector<int> toVector() {\n        return stack;\n    }\n};\n
array_stack.java
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nclass ArrayStack {\n    private ArrayList<Integer> stack;\n\n    public ArrayStack() {\n        // \u521d\u59cb\u5316\u5217\u8868\uff08\u52a8\u6001\u6570\u7ec4\uff09\n        stack = new ArrayList<>();\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    public int size() {\n        return stack.size();\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    public boolean isEmpty() {\n        return size() == 0;\n    }\n\n    /* \u5165\u6808 */\n    public void push(int num) {\n        stack.add(num);\n    }\n\n    /* \u51fa\u6808 */\n    public int pop() {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        return stack.remove(size() - 1);\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    public int peek() {\n        if (isEmpty())\n            throw new IndexOutOfBoundsException();\n        return stack.get(size() - 1);\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    public Object[] toArray() {\n        return stack.toArray();\n    }\n}\n
array_stack.cs
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nclass ArrayStack {\n    List<int> stack;\n    public ArrayStack() {\n        // \u521d\u59cb\u5316\u5217\u8868\uff08\u52a8\u6001\u6570\u7ec4\uff09\n        stack = [];\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    public int Size() {\n        return stack.Count;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    public bool IsEmpty() {\n        return Size() == 0;\n    }\n\n    /* \u5165\u6808 */\n    public void Push(int num) {\n        stack.Add(num);\n    }\n\n    /* \u51fa\u6808 */\n    public int Pop() {\n        if (IsEmpty())\n            throw new Exception();\n        var val = Peek();\n        stack.RemoveAt(Size() - 1);\n        return val;\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    public int Peek() {\n        if (IsEmpty())\n            throw new Exception();\n        return stack[Size() - 1];\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    public int[] ToArray() {\n        return [.. stack];\n    }\n}\n
array_stack.go
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\ntype arrayStack struct {\n    data []int // \u6570\u636e\n}\n\n/* \u521d\u59cb\u5316\u6808 */\nfunc newArrayStack() *arrayStack {\n    return &arrayStack{\n        // \u8bbe\u7f6e\u6808\u7684\u957f\u5ea6\u4e3a 0\uff0c\u5bb9\u91cf\u4e3a 16\n        data: make([]int, 0, 16),\n    }\n}\n\n/* \u6808\u7684\u957f\u5ea6 */\nfunc (s *arrayStack) size() int {\n    return len(s.data)\n}\n\n/* \u6808\u662f\u5426\u4e3a\u7a7a */\nfunc (s *arrayStack) isEmpty() bool {\n    return s.size() == 0\n}\n\n/* \u5165\u6808 */\nfunc (s *arrayStack) push(v int) {\n    // \u5207\u7247\u4f1a\u81ea\u52a8\u6269\u5bb9\n    s.data = append(s.data, v)\n}\n\n/* \u51fa\u6808 */\nfunc (s *arrayStack) pop() any {\n    val := s.peek()\n    s.data = s.data[:len(s.data)-1]\n    return val\n}\n\n/* \u83b7\u53d6\u6808\u9876\u5143\u7d20 */\nfunc (s *arrayStack) peek() any {\n    if s.isEmpty() {\n        return nil\n    }\n    val := s.data[len(s.data)-1]\n    return val\n}\n\n/* \u83b7\u53d6 Slice \u7528\u4e8e\u6253\u5370 */\nfunc (s *arrayStack) toSlice() []int {\n    return s.data\n}\n
array_stack.swift
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nclass ArrayStack {\n    private var stack: [Int]\n\n    init() {\n        // \u521d\u59cb\u5316\u5217\u8868\uff08\u52a8\u6001\u6570\u7ec4\uff09\n        stack = []\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    func size() -> Int {\n        stack.count\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    func isEmpty() -> Bool {\n        stack.isEmpty\n    }\n\n    /* \u5165\u6808 */\n    func push(num: Int) {\n        stack.append(num)\n    }\n\n    /* \u51fa\u6808 */\n    @discardableResult\n    func pop() -> Int {\n        if isEmpty() {\n            fatalError(\"\u6808\u4e3a\u7a7a\")\n        }\n        return stack.removeLast()\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    func peek() -> Int {\n        if isEmpty() {\n            fatalError(\"\u6808\u4e3a\u7a7a\")\n        }\n        return stack.last!\n    }\n\n    /* \u5c06 List \u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n    func toArray() -> [Int] {\n        stack\n    }\n}\n
array_stack.js
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nclass ArrayStack {\n    #stack;\n    constructor() {\n        this.#stack = [];\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    get size() {\n        return this.#stack.length;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    isEmpty() {\n        return this.#stack.length === 0;\n    }\n\n    /* \u5165\u6808 */\n    push(num) {\n        this.#stack.push(num);\n    }\n\n    /* \u51fa\u6808 */\n    pop() {\n        if (this.isEmpty()) throw new Error('\u6808\u4e3a\u7a7a');\n        return this.#stack.pop();\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    top() {\n        if (this.isEmpty()) throw new Error('\u6808\u4e3a\u7a7a');\n        return this.#stack[this.#stack.length - 1];\n    }\n\n    /* \u8fd4\u56de Array */\n    toArray() {\n        return this.#stack;\n    }\n}\n
array_stack.ts
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nclass ArrayStack {\n    private stack: number[];\n    constructor() {\n        this.stack = [];\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    get size(): number {\n        return this.stack.length;\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    isEmpty(): boolean {\n        return this.stack.length === 0;\n    }\n\n    /* \u5165\u6808 */\n    push(num: number): void {\n        this.stack.push(num);\n    }\n\n    /* \u51fa\u6808 */\n    pop(): number | undefined {\n        if (this.isEmpty()) throw new Error('\u6808\u4e3a\u7a7a');\n        return this.stack.pop();\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    top(): number | undefined {\n        if (this.isEmpty()) throw new Error('\u6808\u4e3a\u7a7a');\n        return this.stack[this.stack.length - 1];\n    }\n\n    /* \u8fd4\u56de Array */\n    toArray() {\n        return this.stack;\n    }\n}\n
array_stack.dart
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nclass ArrayStack {\n  late List<int> _stack;\n  ArrayStack() {\n    _stack = [];\n  }\n\n  /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n  int size() {\n    return _stack.length;\n  }\n\n  /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n  bool isEmpty() {\n    return _stack.isEmpty;\n  }\n\n  /* \u5165\u6808 */\n  void push(int _num) {\n    _stack.add(_num);\n  }\n\n  /* \u51fa\u6808 */\n  int pop() {\n    if (isEmpty()) {\n      throw Exception(\"\u6808\u4e3a\u7a7a\");\n    }\n    return _stack.removeLast();\n  }\n\n  /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n  int peek() {\n    if (isEmpty()) {\n      throw Exception(\"\u6808\u4e3a\u7a7a\");\n    }\n    return _stack.last;\n  }\n\n  /* \u5c06\u6808\u8f6c\u5316\u4e3a Array \u5e76\u8fd4\u56de */\n  List<int> toArray() => _stack;\n}\n
array_stack.rs
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\nstruct ArrayStack<T> {\n    stack: Vec<T>,\n}\n\nimpl<T> ArrayStack<T> {\n    /* \u521d\u59cb\u5316\u6808 */\n    fn new() -> ArrayStack<T> {\n        ArrayStack::<T> { stack: Vec::<T>::new() }\n    }\n\n    /* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\n    fn size(&self) -> usize {\n        self.stack.len()\n    }\n\n    /* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\n    fn is_empty(&self) -> bool {\n        self.size() == 0\n    }\n\n    /* \u5165\u6808 */\n    fn push(&mut self, num: T) {\n        self.stack.push(num);\n    }\n\n    /* \u51fa\u6808 */\n    fn pop(&mut self) -> Option<T> {\n        match self.stack.pop() {\n            Some(num) => Some(num),\n            None => None,\n        }\n    }\n\n    /* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\n    fn peek(&self) -> Option<&T> {\n        if self.is_empty() { panic!(\"\u6808\u4e3a\u7a7a\") };\n        self.stack.last()\n    }\n\n    /* \u8fd4\u56de &Vec */\n    fn to_array(&self) -> &Vec<T> {\n        &self.stack\n    }\n}\n
array_stack.c
/* \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808 */\ntypedef struct {\n    int *data;\n    int size;\n} ArrayStack;\n\n/* \u6784\u9020\u51fd\u6570 */\nArrayStack *newArrayStack() {\n    ArrayStack *stack = malloc(sizeof(ArrayStack));\n    // \u521d\u59cb\u5316\u4e00\u4e2a\u5927\u5bb9\u91cf\uff0c\u907f\u514d\u6269\u5bb9\n    stack->data = malloc(sizeof(int) * MAX_SIZE);\n    stack->size = 0;\n    return stack;\n}\n\n/* \u6790\u6784\u51fd\u6570 */\nvoid delArrayStack(ArrayStack *stack) {\n    free(stack->data);\n    free(stack);\n}\n\n/* \u83b7\u53d6\u6808\u7684\u957f\u5ea6 */\nint size(ArrayStack *stack) {\n    return stack->size;\n}\n\n/* \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a */\nbool isEmpty(ArrayStack *stack) {\n    return stack->size == 0;\n}\n\n/* \u5165\u6808 */\nvoid push(ArrayStack *stack, int num) {\n    if (stack->size == MAX_SIZE) {\n        printf(\"\u6808\u5df2\u6ee1\\n\");\n        return;\n    }\n    stack->data[stack->size] = num;\n    stack->size++;\n}\n\n/* \u8bbf\u95ee\u6808\u9876\u5143\u7d20 */\nint peek(ArrayStack *stack) {\n    if (stack->size == 0) {\n        printf(\"\u6808\u4e3a\u7a7a\\n\");\n        return INT_MAX;\n    }\n    return stack->data[stack->size - 1];\n}\n\n/* \u51fa\u6808 */\nint pop(ArrayStack *stack) {\n    int val = peek(stack);\n    stack->size--;\n    return val;\n}\n
array_stack.zig
// \u57fa\u4e8e\u6570\u7ec4\u5b9e\u73b0\u7684\u6808\nfn ArrayStack(comptime T: type) type {\n    return struct {\n        const Self = @This();\n\n        stack: ?std.ArrayList(T) = null,     \n\n        // \u6784\u9020\u65b9\u6cd5\uff08\u5206\u914d\u5185\u5b58+\u521d\u59cb\u5316\u6808\uff09\n        pub fn init(self: *Self, allocator: std.mem.Allocator) void {\n            if (self.stack == null) {\n                self.stack = std.ArrayList(T).init(allocator);\n            }\n        }\n\n        // \u6790\u6784\u65b9\u6cd5\uff08\u91ca\u653e\u5185\u5b58\uff09\n        pub fn deinit(self: *Self) void {\n            if (self.stack == null) return;\n            self.stack.?.deinit();\n        }\n\n        // \u83b7\u53d6\u6808\u7684\u957f\u5ea6\n        pub fn size(self: *Self) usize {\n            return self.stack.?.items.len;\n        }\n\n        // \u5224\u65ad\u6808\u662f\u5426\u4e3a\u7a7a\n        pub fn isEmpty(self: *Self) bool {\n            return self.size() == 0;\n        }\n\n        // \u8bbf\u95ee\u6808\u9876\u5143\u7d20\n        pub fn peek(self: *Self) T {\n            if (self.isEmpty()) @panic(\"\u6808\u4e3a\u7a7a\");\n            return self.stack.?.items[self.size() - 1];\n        }  \n\n        // \u5165\u6808\n        pub fn push(self: *Self, num: T) !void {\n            try self.stack.?.append(num);\n        } \n\n        // \u51fa\u6808\n        pub fn pop(self: *Self) T {\n            var num = self.stack.?.pop();\n            return num;\n        } \n\n        // \u8fd4\u56de ArrayList\n        pub fn toList(self: *Self) std.ArrayList(T) {\n            return self.stack.?;\n        }\n    };\n}\n
Visualizing Code

Full Screen >

"},{"location":"chapter_stack_and_queue/stack/#513-comparison-of-the-two-implementations","title":"5.1.3 \u00a0 Comparison of the Two Implementations","text":"

Supported Operations

Both implementations support all the operations defined in a stack. The array implementation additionally supports random access, but this is beyond the scope of a stack definition and is generally not used.

Time Efficiency

In the array-based implementation, both push and pop operations occur in pre-allocated continuous memory, which has good cache locality and therefore higher efficiency. However, if the push operation exceeds the array capacity, it triggers a resizing mechanism, making the time complexity of that push operation \\(O(n)\\).

In the linked list implementation, list expansion is very flexible, and there is no efficiency decrease issue as in array expansion. However, the push operation requires initializing a node object and modifying pointers, so its efficiency is relatively lower. If the elements being pushed are already node objects, then the initialization step can be skipped, improving efficiency.

Thus, when the elements for push and pop operations are basic data types like int or double, we can draw the following conclusions:

  • The array-based stack implementation's efficiency decreases during expansion, but since expansion is a low-frequency operation, its average efficiency is higher.
  • The linked list-based stack implementation provides more stable efficiency performance.

Space Efficiency

When initializing a list, the system allocates an \"initial capacity,\" which might exceed the actual need; moreover, the expansion mechanism usually increases capacity by a specific factor (like doubling), which may also exceed the actual need. Therefore, the array-based stack might waste some space.

However, since linked list nodes require extra space for storing pointers, the space occupied by linked list nodes is relatively larger.

In summary, we cannot simply determine which implementation is more memory-efficient. It requires analysis based on specific circumstances.

"},{"location":"chapter_stack_and_queue/stack/#514-typical-applications-of-stack","title":"5.1.4 \u00a0 Typical Applications of Stack","text":"
  • Back and forward in browsers, undo and redo in software. Every time we open a new webpage, the browser pushes the previous page onto the stack, allowing us to go back to the previous page through the back operation, which is essentially a pop operation. To support both back and forward, two stacks are needed to work together.
  • Memory management in programs. Each time a function is called, the system adds a stack frame at the top of the stack to record the function's context information. In recursive functions, the downward recursion phase keeps pushing onto the stack, while the upward backtracking phase keeps popping from the stack.
"},{"location":"chapter_stack_and_queue/summary/","title":"5.4 \u00a0 Summary","text":""},{"location":"chapter_stack_and_queue/summary/#1-key-review","title":"1. \u00a0 Key Review","text":"
  • A stack is a data structure that follows the Last-In-First-Out (LIFO) principle and can be implemented using either arrays or linked lists.
  • In terms of time efficiency, the array implementation of a stack has higher average efficiency, but during expansion, the time complexity for a single push operation can degrade to \\(O(n)\\). In contrast, the linked list implementation of a stack offers more stable efficiency.
  • Regarding space efficiency, the array implementation of a stack may lead to some level of space wastage. However, it's important to note that the memory space occupied by nodes in a linked list is generally larger than that for elements in an array.
  • A queue is a data structure that follows the First-In-First-Out (FIFO) principle, and it can also be implemented using either arrays or linked lists. The conclusions regarding time and space efficiency for queues are similar to those for stacks.
  • A double-ended queue is a more flexible type of queue that allows adding and removing elements from both ends.
"},{"location":"chapter_stack_and_queue/summary/#2-q-a","title":"2. \u00a0 Q & A","text":"

Q: Is the browser's forward and backward functionality implemented with a doubly linked list?

The forward and backward functionality of a browser fundamentally represents the \"stack\" concept. When a user visits a new page, it is added to the top of the stack; when they click the back button, the page is popped from the top. A double-ended queue can conveniently implement some additional operations, as mentioned in the \"Double-Ended Queue\" section.

Q: After popping from a stack, is it necessary to free the memory of the popped node?

If the popped node will still be used later, it's not necessary to free its memory. In languages like Java and Python that have automatic garbage collection, manual memory release isn't required; in C and C++, manual memory release is necessary if the node will no longer be used.

Q: A double-ended queue seems like two stacks joined together. What are its uses?

A double-ended queue is essentially a combination of a stack and a queue, or like two stacks joined together. It exhibits both stack and queue logic, therefore enabling the implementation of all applications of stacks and queues with added flexibility.

Q: How exactly are undo and redo implemented?

Undo and redo are implemented using two stacks: Stack A for undo and Stack B for redo.

  1. Each time a user performs an operation, it is pushed onto Stack A, and Stack B is cleared.
  2. When the user executes an \"undo\", the most recent operation is popped from Stack A and pushed onto Stack B.
  3. When the user executes a \"redo\", the most recent operation is popped from Stack B and pushed back onto Stack A.
"}]} \ No newline at end of file diff --git a/en/sitemap.xml b/en/sitemap.xml index 806c85b87..2f469298e 100644 --- a/en/sitemap.xml +++ b/en/sitemap.xml @@ -2,162 +2,162 @@ https://www.hello-algo.com/en/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_array_and_linkedlist/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_array_and_linkedlist/array/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_array_and_linkedlist/linked_list/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_array_and_linkedlist/list/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_array_and_linkedlist/ram_and_cache/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_array_and_linkedlist/summary/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_computational_complexity/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_computational_complexity/iteration_and_recursion/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_computational_complexity/performance_evaluation/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_computational_complexity/space_complexity/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_computational_complexity/summary/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_computational_complexity/time_complexity/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_data_structure/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_data_structure/basic_data_types/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_data_structure/character_encoding/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_data_structure/classification_of_data_structure/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_data_structure/number_encoding/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_data_structure/summary/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_introduction/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_introduction/algorithms_are_everywhere/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_introduction/summary/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_introduction/what_is_dsa/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_preface/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_preface/about_the_book/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_preface/suggestions/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_preface/summary/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_stack_and_queue/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_stack_and_queue/deque/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_stack_and_queue/queue/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_stack_and_queue/stack/ - 2024-01-15 + 2024-01-22 daily https://www.hello-algo.com/en/chapter_stack_and_queue/summary/ - 2024-01-15 + 2024-01-22 daily \ No newline at end of file diff --git a/en/sitemap.xml.gz b/en/sitemap.xml.gz index fc10b44b6c4a40e3e2b455018b7e05e7ba46cbc1..c6f09f3cf1ed71b9aaa1218bcc3ff07b193a9c0c 100644 GIT binary patch delta 433 zcmV;i0Z#ti1Kb0DABzYG%}cIj0{?SqbY*Q}a4vXlYyjPt&2HN;41n)_ioo~SY0$$q zB<`(Gu$=`)rfnhmaYU+a-oCP&4e4>0A)GE2X`1*bQ6hbK{cv{kj*(38$LhJ>RU7m= zbjAetV=?YHW+eLAFQ33-!^Jsqo&dHT^b^E}sN7#&Q1REIb;q{l2!b5l0E`g_$r zZSq(gtg|u>Ht2ToLN_-fS{t@thfwR_8uZPfS#0h<0b&=rcE8)dY4@~r^LYdZU$Q;^p!nznl!=t0zm@Yj7#_K%d<7fGoC?sad zJOV32sv~%G?kQrQ8!;)Ea0-bPkEl)|oTX4x8U~~#HAoJ!h+{_#`dohSE(sG#!|m`Q b4_f3(7g-$izdD5FLCEbV&0}eZq!$1HtEbO7 delta 434 zcmV;j0Zsng1Kk6EABzYGp);jr0{?SqbY*Q}a4vXlYyjPt&2HN;41n)_ioo|+Nznn@ zkhr%!!Fo0rnYM-K#}TQzdHcz7Hl)X0hH$!Aq-o-#M2Ym_^~2fCJ4Q0WAFF-6t2XF$ z=!_qZ)!WY>+ppDY^K?kj67nV+dpcGl^YmS*d7f)Bj1DG$szV$U=`jnWZc4SQzg5lC zCXdCzIxFK~gKictbaOMJwP6c(2(=DQp;rgB*xY{t#4dEr^X~a&yW4N~U$V(fcW0(Y z@B{V{FHHx=UJvR{v$Ci^Fn^DgolT6fg&5)5g6~>u{24oIh($6NrAYF1+KOFyvEUJ0 zQEABMU1S79l$?Y3@M)jLDKT)qo52>z;)h|m+_^5qqAnW}QKwRP#KtpW>_c?mHMaN; zHWeGO;m`y*kpCdhq@Qm#PSQSfz|aztK>;^q#JU(n!=t0zm@Yj7#_K%d<7fG&C?sad zJOa0d+K%ASxu=MIZp5Tu!YL$fdBpY`@?y`&ca0JSCAod5s; diff --git a/en/stylesheets/extra.css b/en/stylesheets/extra.css index 332bf26bb..adaa54446 100644 --- a/en/stylesheets/extra.css +++ b/en/stylesheets/extra.css @@ -216,3 +216,183 @@ body { transform-origin: top left; border: none; } + +/* landing page container */ +.home-div { + width: 100%; + height: auto; + display: flex; + justify-content: center; + align-items: center; + background-color: var(--md-default-bg-color); + color: var(--md-default-fg-color); + font-size: 0.9rem; + padding: 2em; + text-align: center; +} + +.section-content { + width: 100%; + height: auto; + max-width: 70vw; +} + +.hero-btn { + margin: 0 0.1em; + padding: 0.5em 1.3em; + font-size: 0.85em; +} + +/* hero image */ +.hero-image-div { + height: min(84vh, 75vw); + width: min(112vh, 100vw); + margin: 0 auto; + margin-top: -2.4rem; + padding: 0; + position: relative; + color: white; + font-size: min(2vh, 2.5vw); + font-weight: 500; +} + +.hero-bg { + height: 100%; + width: 100%; + object-fit: cover; + position: absolute; +} + +/* hover on the planets */ +.hero-on-hover { + width: auto; + position: absolute; + transition: transform 0.3s ease-in-out, filter 0.3s ease-in-out; +} + +.hero-caption { + margin: 0; + position: absolute; + transform: translateX(-50%) translateY(-50%); +} + +a:hover .hero-on-hover { + filter: brightness(1.2) saturate(1.1); + transform: scale(1.03); +} + +a:hover .hero-caption { + color: var(--md-typeset-btn-color); +} + +/* device */ +.device-on-hover { + width: auto; + position: absolute; + transition: transform 0.3s ease-in-out; +} + +.device-on-hover:hover { + transform: scale(1.03); +} + +/* brief intro */ +.intro-container { + display: flex; + align-items: center; + margin: 2em auto; +} + +.intro-image { + flex-shrink: 0; + flex-grow: 0; + width: 55%; + border-radius: 0.5em; + box-shadow: var(--md-shadow-z2); +} + +.intro-text { + flex-grow: 1; /* 允许元素填充剩余空间 */ + display: flex; + flex-direction: column; + justify-content: center; + text-align: left; + align-items: flex-start; + width: fit-content; + margin: 2em; +} + +.intro-text > div { + align-self: flex-start; + width: auto; + margin: 0 auto; +} + +.intro-quote { + color: var(--md-accent-fg-color); + font-weight: bold; +} + +/* contributors table */ +.profile-div { + display: flex; + flex-wrap: wrap; /* 当空间不足时换行 */ + justify-content: center; /* 居中对齐子元素 */ + max-width: 1080px; /* 或其他最大宽度 */ + margin: 1em auto; +} + +.profile-cell { + flex: 1; /* 每个单元格均分空间 */ + flex-basis: 15%; + margin: 1em 0.5em; /* 为了清晰间隔,可以根据需要调整 */ + text-align: center; /* 文本居中 */ +} + +.profile-img { + width: 5em; + border-radius: 50%; + margin-bottom: 0.2em; +} + +.contrib-image { + width: 45%; +} + +/* Hide table of contents */ +@media screen and (max-width: 60em) { + .home-div { + font-size: 0.75rem; + } +} + +/* Hide navigation */ +@media screen and (max-width: 76.25em) { + .section-content { + max-width: 95vw; + } + + .intro-container { + flex-direction: column; /* 竖向布局 */ + } + + .intro-text { + width: auto; + order: 2; + margin: 0 auto; + } + + .intro-image { + width: 100%; /* 占满屏幕宽度 */ + order: 1; + margin-bottom: 1em; + } + + .contrib-image { + width: 100%; + } + + .profile-cell { + flex-basis: 25%; + } +} diff --git a/index.html b/index.html index 938ce3947..c7deff91c 100644 --- a/index.html +++ b/index.html @@ -85,7 +85,7 @@ -
+
+ + + +
+ + +
+
+
+ +
+
+ + + + + + + + + + + + +
+

500 幅动画图解、12 种编程语言代码、2000 条社区问答,助你快速入门数据结构与算法

+
+
+ + +
+
+
+ + + + + + + +
+

提供网页版和 PDF 版,兼容 PC、平板或手机,随时随地阅读

+
+
+ + +
+
+

推荐语

+
+
+

“一本通俗易懂的数据结构与算法入门书,引导读者手脑并用地学习,强烈推荐算法初学者阅读。”

+

—— 邓俊辉,清华大学计算机系教授

+
+
+

“如果我当年学数据结构与算法的时候有《Hello 算法》,学起来应该会简单 10 倍!”

+

—— 李沐,亚马逊资深首席科学家

+
+
+
+
+ + +
+
+
+
+
+
+ + + +

动画图解

+
+

内容清晰易懂,学习曲线平滑

+

"A picture is worth a thousand words."
“一图胜千言”

+
+
+ +
+ +
+ +
+
+
+ + + +

一键运行

+
+

十余种编程语言,代码可视化运行

+

"Talk is cheap. Show me the code."
“少吹牛,看代码”

+
+
+
+ +
+
+
+
+ + + +

互助学习

+
+

欢迎讨论与提问,读者间携手共进

+

"Knowledge increases by sharing."
“知识在分享中得以增长”

+
+
+ +
+ +
+
+ + +
+
+ +
+

作者

+ +
+ + + + + +
+

贡献者

+

本书在开源社区 130 多位贡献者的共同努力下不断完善,感谢他们付出的时间与精力!

+ + + +
+
+
+ @@ -245,7 +591,7 @@ -
+