c++如何输入数组_从一个数组中找出 N 个数,其和为 M 的所有可能最 nice 的解法...
編者按:本文由前端狂想錄公眾號(hào)授權(quán)奇舞周刊轉(zhuǎn)載。
故事的背景
這是一個(gè)呆萌炫酷吊炸天的前端算法題,曾經(jīng)乃至現(xiàn)在也是叱咤風(fēng)云在各個(gè)面試場景中。
可以這樣說,有 90% 以上的前端工程師不會(huì)做這個(gè)題目。
這道題涉及的知識(shí)點(diǎn)很多,雖然網(wǎng)上也有相關(guān)的解答文章,但是在算法小分隊(duì)的討論和分析中,一致認(rèn)為網(wǎng)上的文章太舊了,而且最多就是貼貼代碼,寫寫注釋,并沒有具體的分析。
暴風(fēng)雨前的寧靜
我們看一下題目:
從一個(gè)數(shù)組中找出 N 個(gè)數(shù),其和為 M 的所有可能。
大家可以中斷 5 分鐘想一下,不管想什么,反正先看著題目想 5 分鐘。
想完了嗎?
是不是感受到了一股殺氣,好像知道些,但是又無從下手的那種勝利的感覺,嗯...?
機(jī)智(雞賊)的我,選擇先把題目留在這兒,我們先去探討一下算法。
為什么算法就可以無法無天?
關(guān)于上面這個(gè)無解的問題,我們默默不說話。現(xiàn)在,我們來思考幾個(gè)簡單點(diǎn)的哲學(xué)問題:
什么是算法?
算法的作用和目的是什么?
如何設(shè)計(jì)我們的算法?
算法的復(fù)雜度該如何表示?
如何測試和優(yōu)化我們的算法?
嗯?我怎么感覺死循環(huán)了呢?無限遞歸且沒有終止條件?
什么是算法
《算法導(dǎo)論》一書將算法( algorithm )描述為定義良好的計(jì)算過程,它取一個(gè)或一組值作為輸入,并產(chǎn)生一個(gè)或一組值作為輸出。
計(jì)算的組成
計(jì)算機(jī)主要的單元包括:I/O 、CPU 、內(nèi)存等,這里我們要介紹的是CPU。
CPU 負(fù)責(zé)的功能主要就是解釋和執(zhí)行程序,它能認(rèn)識(shí)的就是一堆 0 和 1 組成的機(jī)器碼。
我們敲下的每一行代碼最終都被編譯成機(jī)器碼,然后將機(jī)器碼交給 CPU 執(zhí)行。
想一想上面的話,我們可以知道:
我們所知的程序,其實(shí)就是指令和數(shù)據(jù)的集合,而算法的本質(zhì)就是執(zhí)行設(shè)計(jì)好的指令集,從輸入到產(chǎn)生輸出的過程。
算法是抽象的概念,但越是抽象的東西,其越具有清晰的特征。特征如下:
確定性: 算法的每一個(gè)步驟都是明確的、可行的、結(jié)果可預(yù)期的
有窮性: 算法要有一個(gè)終止條件
輸入和輸出: 算法是用來解決問題的,少不了輸入和輸出
大多數(shù)人只看見了樹,卻未見森林
看到這,你可能有疑問,為什么要這樣說呢?且聽我娓娓道來:
列舉一些大家可能知道的一些詞吧:
遞歸法、貪婪法、分治法、動(dòng)態(tài)規(guī)劃法、線性規(guī)劃法、搜索和枚舉法(包括窮盡枚舉)、極大極小值法、 Alpha-beta 、剪枝等等。
看到上面這些稀罕詞,很多人認(rèn)為這就是算法了,但其實(shí)這只是算法設(shè)計(jì)范式中,一些前人總結(jié)出來的模式而已。
我們可以將這種算法層面的模式和平常我們說的設(shè)計(jì)模式進(jìn)行對(duì)比。
對(duì)比后,會(huì)發(fā)現(xiàn),這就是一種算法抽象的最佳實(shí)踐范式。其實(shí)我們寫的任何一個(gè)代碼片段(包含輸入和輸出),都可以認(rèn)為是算法的子集,甚至程序也只是算法的一種存在形式而已。
之前看到有人把程序比做水流,從源頭順流而下(順序執(zhí)行),也可以分流而下(分支、并發(fā)),還可以起個(gè)漩渦(遞歸),其實(shí)這些也都只是算法中具體的實(shí)現(xiàn)或者組織方式而已。
算法的領(lǐng)域極其廣闊,不要把思維僅僅局限在計(jì)算機(jī)領(lǐng)域中。
對(duì)于計(jì)算機(jī)行業(yè)人員來說,算法就是內(nèi)功。就好比乾坤大挪移,學(xué)成之后,天下武功皆能快速掌握。
算法設(shè)計(jì)
這一塊兒其實(shí)是很龐大的知識(shí)體系,需要苦練內(nèi)功根基。下面簡要介紹下算法設(shè)計(jì)方面的知識(shí)。
順序執(zhí)行、循環(huán)和分支跳轉(zhuǎn)是程序設(shè)計(jì)的三大基本結(jié)構(gòu)。
算法也是程序,千姿百態(tài)的算法也是由這三大基礎(chǔ)結(jié)構(gòu)構(gòu)成的。
算法和數(shù)據(jù)結(jié)構(gòu)關(guān)系緊密,數(shù)據(jù)結(jié)構(gòu)是算法設(shè)計(jì)的基礎(chǔ)。
如果對(duì)諸如哈希表、隊(duì)列、樹、圖等數(shù)據(jù)結(jié)構(gòu)有深刻的認(rèn)識(shí),那在算法設(shè)計(jì)上將會(huì)事半功倍。
上面提到的知識(shí),主要的目的是拋磚引玉。算法的設(shè)計(jì)與分析是無上神功的心法口訣和入門要領(lǐng)。無論多么精妙絕倫的算法實(shí)現(xiàn),都是由一些最基礎(chǔ)的模型和范式組裝起來的。
關(guān)于算法設(shè)計(jì),這里給大家推薦一門課程,很不錯(cuò),小伙伴可以看看:
算法設(shè)計(jì)與分析-Design and Analysis of Algorithms(https://zh.coursera.org/learn/algorithms)
TIPS: 小伙伴如果有好的資源,也可以留言 mark 哦。
最?NICE?的解法
降維分析,化繁為簡
現(xiàn)在,到了最關(guān)鍵的時(shí)刻。我們回到題目中,開始設(shè)計(jì)我們的算法。
題干信息很簡單,核心問題在于:
如何從數(shù)組中選取?N?個(gè)數(shù)進(jìn)行求和運(yùn)算。
如何做,這里我們通常且正確的做法,是對(duì)問題進(jìn)行降維分析,并且化繁為簡。
下面開始降維分析,化繁為簡:
假如 N = 2 ,也就是找出數(shù)組中兩個(gè)數(shù)的和為 M 的話,你會(huì)怎么做?可能你會(huì)想到每次從數(shù)組中彈出一個(gè)數(shù),然后與余下的每個(gè)數(shù)進(jìn)行相加,最后做判斷。
那么問題來了,當(dāng) N = 3 呢,N = 10 呢,會(huì)發(fā)現(xiàn)運(yùn)算量越來越大,之前的方式已經(jīng)不可行了。
不妨換一種思路:
數(shù)組中選取不固定數(shù)值 N ,我們可以嘗試著使用標(biāo)記的方式,我們把 1 表示成選取狀態(tài), 把 0 表示成未選取狀態(tài)。
假設(shè)數(shù)組 const arr=[1,2,3,4] ,對(duì)應(yīng)著每個(gè)元素都有標(biāo)記 0 或者 1 。如果 N=4 ,也就是在這個(gè)數(shù)組中,需要選擇 4 個(gè)元素,那么對(duì)應(yīng)的標(biāo)記就只有一種可能 1111 ,如果 N=3 ,那就有 4 種可能,分別是 1110 、 1101 、1011 以及 0111 (也就是 C4取3->4 ) 種可能。
開始抽象
通過上面的層層敘述,我們現(xiàn)在的問題可以抽象為:
標(biāo)記中有幾個(gè) 1 就是代表選取了幾個(gè)數(shù),然后再去遍歷這些 1 所有可能存在的排列方式,最后做一個(gè)判斷,這個(gè)判斷就是:每一種排列方式,都代表著數(shù)組中不同位置的被選中的數(shù)的組合,所以這里就是將選中的這些數(shù)字,進(jìn)行求和運(yùn)算,然后判斷求出的和是不是等于 M 。
于是,問題開始變得簡單了。
如何將數(shù)組和標(biāo)記關(guān)聯(lián)
0101?這樣的數(shù)據(jù)一眼望上去第一反應(yīng)就是二進(jìn)制啊
對(duì)于 arr 來說,有 4 個(gè)元素,對(duì)應(yīng)的選擇方式就是從 0000( N = 0 )到 1111( N = 4 )的所有可能。
而 1111 就是 15 的二進(jìn)制,也就是說這所有的可能其實(shí)對(duì)應(yīng)的就是 0 - 15 中所有數(shù)對(duì)應(yīng)的二進(jìn)制。
這里的問題最終變成了如何從數(shù)組長度?4?推導(dǎo)出?0 - 15
這里采用了位運(yùn)算--左移運(yùn)算, 1 << 4 的結(jié)果是 16 。
所以我們可以建立這樣一個(gè)迭代:
const?arr?=?[1,?2,?3,?4]
let?len?=?arr.length,?bit?=?1?<<?len
// 這里忽略了 0 的情況(N = 0),取值就是 1 - 15
for(let?i?=?1;?i?<?bit;?i++)?{
??// ...
}
如何從?1110?標(biāo)記中取出?1?的個(gè)數(shù)
最簡單的方式:
const?n?=?num?=>?num.toString(2).replace(/0/g,?'').length
這其實(shí)也是一道算法常考題,因?yàn)槲贿\(yùn)算是不需要編譯的,肯定速度最快。
PS: 如果不理解位運(yùn)算為何會(huì)提高性能的同學(xué),可以自行搜索一下位運(yùn)算。簡單點(diǎn)說就是:位運(yùn)算直接用二進(jìn)制進(jìn)行表示,省去了中間過程的各種復(fù)雜轉(zhuǎn)換,提高了速度。
我們嘗試使用?&?運(yùn)算來解決這個(gè)問題
首先我們肯定知道 1 & 1 = 1; 1 & 0 = 0 這些結(jié)論的。所以我們從 15 & 14 => 14 可以推導(dǎo)出 1111 & 1110 => 1110 ,為什么可以這樣推導(dǎo)呢,因?yàn)?15 的二進(jìn)制就是 1111 ,14 同理。
我們可以看到,通過上面的操作消掉了最后的 1。
所以我們可以建立一個(gè)迭代,通過統(tǒng)計(jì)消除的次數(shù),就能確定最終有幾個(gè) 1 了。
代碼如下:
const?n?=?num?=>?{
??let?count?=?0
??while(num)?{
????num?&=?(num?-?1)
????count++
??}
??return?count
}
計(jì)算和等于?M
現(xiàn)在我們已經(jīng)可以把所有的選取可能轉(zhuǎn)變?yōu)楸闅v一個(gè)數(shù)組,然后通過迭代數(shù)組中的每個(gè)數(shù)對(duì)應(yīng)的二進(jìn)制,有幾個(gè) 1 來確定選取元素的個(gè)數(shù)。
那么,現(xiàn)在需要的最后一層判斷就是選取的這些數(shù)字和必須等于?M
這里其實(shí)就是建立一個(gè)映射:
1110 到 [1, 2, 3, 4] 的映射,就代表選取了 2, 3, 4,然后判斷 2 + 3 + 4 與 M 。
這里可以這樣看:1110 中的左邊第一個(gè) 1 對(duì)應(yīng)著數(shù)組 [1, 2, 3, 4] 中的 4 。
現(xiàn)在有一個(gè)問題,該如何建立這個(gè)映射關(guān)系呢?
我們知道前者 1110 其實(shí)就是對(duì)應(yīng)的外層遍歷中的 i = 14 的情況。
再看看數(shù)組[1, 2, 3, 4] ,我們可以將元素及其位置分別映射為 1000 0100 0010 0001。
實(shí)現(xiàn)方式也是通過位運(yùn)算--左位移來實(shí)現(xiàn):
1 << inx ,inx 為數(shù)組的下標(biāo)。
位掩碼介紹
對(duì) 位掩碼 不熟悉的童鞋會(huì)有點(diǎn)暈,這里簡單科普下:
實(shí)質(zhì)上,這里的 1 << j ,是指使用 1 的移位來生成其中僅設(shè)置第 j 位的位掩碼。
比如:14 的二進(jìn)制表示為 1110,其代表(從右往左)選取了第 2 , 3 , 4 位。
那么(下面故意寫成上下對(duì)應(yīng)的方式):
// demo1
??1110
&
??0001
=
??0000
// demo2
??1110
&
??0010
=
??0010
PS: 通過上面代碼,我們可以看到上下對(duì)應(yīng)的 0 和 1 在進(jìn)行 & 運(yùn)算以后,得出的結(jié)果和在 js 中進(jìn)行相同條件下 & 運(yùn)算的結(jié)果相同。
所以:
1?<<?0?// 1 -> 0001
1?<<?1?// 2 -> 0010
1?<<?2?// 4 -> 0100
1?<<?3?// 8 -> 1000
// 說白了,就是把左邊的值變成二進(jìn)制形式,然后左移或者右移,超出補(bǔ)0
// 所以, 1110 對(duì)應(yīng)著 第一位沒有選取,那么 1110 & 0001(設(shè)置為第一位的位掩碼) = 0,如果 i & (1 << inx) !== 0 代表該位被選取了
for(let?j?=?0;?j?<?arr.length;?j++){
??if((i?&?(1?<<?j)?!==?0)?{
????// 代表這個(gè)數(shù)被選取了,我們做累加求和就行
??}
}
所以綜上所述,最終代碼實(shí)現(xiàn)如下:
// 參數(shù)依次為目標(biāo)數(shù)組、選取元素?cái)?shù)目、目標(biāo)和
const?search?=?(arr,?count,?sum)?=>?{
??// 計(jì)算某選擇情況下有幾個(gè) `1`,也就是選擇元素的個(gè)數(shù)
??const?n?=?num?=>?{
????let?count?=?0
????while(num)?{
??????num?&=?(num?-?1)
??????count++
????}
????return?count
??}
??let?len?=?arr.length,?bit?=?1?<<?len,?res?=?[]
??// 遍歷所有的選擇情況
??for(let?i?=?1;?i?<?bit;?i++){
????// 滿足選擇的元素個(gè)數(shù) === count
????if(n(i)?===?count){
??????let?s?=?0,?temp?=?[]
??????// 每一種滿足個(gè)數(shù)為 N 的選擇情況下,繼續(xù)判斷是否滿足 和為 M
??????for(let?j?=?0;?j?<?len;?j++){
????????// 建立映射,找出選擇位上的元素
????????if((i?&?1?<<?j)?!==?0)?{
??????????s?+=?arr[j]
??????????temp.push(arr[j])
????????}
??????}
??????// 如果這種選擇情況滿足和為 M
??????if(s?===?sum)?{
????????res.push(temp)
??????}
????}
??}
??return?res
}
如何測試
這其實(shí)也是可以單獨(dú)寫一篇文章的知識(shí)點(diǎn)。
測試的種類、方式多種多樣,我們將自己想象成一個(gè) TroubleMaker ,各種為難自己寫的算法,然后不斷優(yōu)化自己的代碼,這個(gè)過程也是有趣極了。
首先二話不說,照著心里一開始就想的最簡單的方式擼一個(gè)測試用例。
代碼如下:
// 寫一個(gè)很大的數(shù)組進(jìn)行測試
const?arr?=?Array.from({length:?10000000},?(item,?index)?=>?index)
// 測試不同選取容量
const?mocks?=?sum?=>?[3,?300,?3000,?30000,?300000,?3000000].map(item?=>?({count:?item,?sum?}))
let?res?=?[]
mocks(3000).forEach((count,?sum)?=>?{
??const?start?=?window.performance.now()
??search(arr,?count,?sum)
??const?end?=?window.performance.now()
??res.push(end?-?start)
})
然后結(jié)果如下圖:
發(fā)現(xiàn)造了一個(gè)長度為 1000 萬的數(shù)組,找 6 個(gè)數(shù),居然只要 0.014 秒。什么鬼,這么快的么,開掛了吧。不行,感覺這不靠譜,還是從長計(jì)議,寫一個(gè)專業(yè)的測試案例比較好,請(qǐng)繼續(xù)往下看。
我們主要從兩個(gè)方向下手:
第一個(gè)方向:全方位攻擊
其實(shí)就是摳腦袋想出一萬種情況去折騰自己的代碼,也就是所謂的 地毯式測試案例轟炸。
完整代碼如下:
// 比如針對(duì)上面的算法,可以這樣寫
export?const?assert?=?(desc,?condition)?=>?{
??condition?=?typeof?condition?===?"function"???condition()?:?condition;
??console.info(`[Test] %c${desc}`,?"color: orange");
??if?(!condition)?{
????throw?new?Error(`[Error] %c${desc}?failed.`,?"color: pink");
??}
??console.info(`[Success] %c${desc}?success.`,?"color: #198");
};
const?mock_a?=?Array.from({?length:?4?},?(item,?index)?=>?index);
const?mock_b?=?Array.from({?length:?6?},?(item,?index)?=>?index?-?3);
const?mock_c?=?Array.from({?length:?4?},?()?=>?0);
assert(`正整數(shù)情況測試`,?()?=>?{
??const?res?=?search(mock_a,?2,?3);
??const?lengthTest?=?res.length?===?2;
??const?resTest?=?JSON.stringify(res)?===?JSON.stringify([[1,?2],?[0,?3]]);
??return?lengthTest?&&?resTest;
});
assert(`負(fù)數(shù)情況測試`,?()?=>?{
??const?res?=?search(mock_b,?2,?0);
??const?lengthTest?=?res.length?===?2;
??const?resTest?=?JSON.stringify(res)?===?JSON.stringify([[-1,?1],?[-2,?2]]);
??return?lengthTest?&&?resTest;
});
// ...
codesandbox 完整代碼地址(https://codesandbox.io/s/38pn0jvmr1)
在 codesandbox 的運(yùn)行控制臺(tái)下,可以看到測試結(jié)果如下圖所示:
會(huì)發(fā)現(xiàn),這里把很多測試場景都覆蓋了,這樣的好處就是讓自己的代碼能夠更魯棒、更安全。
當(dāng)然,上面的 case 還可以再極端點(diǎn),從而可以驅(qū)使代碼變得更加魯棒。
極端的場景帶來的優(yōu)化如下:
第一個(gè)極端:增加小數(shù)的情況。因?yàn)榫日`差的問題,這里就可以將代碼繼續(xù)優(yōu)化,以支持小數(shù)情況。
第二個(gè)極端:增加公差參數(shù)的情況。不用絕對(duì)相等來取數(shù),可以通過公差來增加靈活性。
第二個(gè)方向:性能測試和持續(xù)優(yōu)化
關(guān)注的第二個(gè)點(diǎn)在于性能測試,為什么呢?
如果要將自己的算法付諸生產(chǎn),除需要穩(wěn)定的功能表現(xiàn)之外,還要有足夠讓人信服的性能。畢竟,性能高的代碼是我們普遍的追求。
這里分享一下有用的技巧:
通過 window.performance.now() ,或者 console.time() ,我們可以簡單快捷的獲取到程序執(zhí)行的時(shí)間。
在寫這樣的測試案例的時(shí)候,有幾個(gè)原則,分別是:
只關(guān)注自己的測試內(nèi)容。
保持干凈
考慮極端情況(比如數(shù)組很大很大)
將多次測試結(jié)果進(jìn)行對(duì)比分析
當(dāng)然你也可以使用類似 jsperf 之類的工具,然后一點(diǎn)一點(diǎn)的去扣這些優(yōu)化點(diǎn),來持續(xù)打磨自己的代碼。
這里提一下,雖然通過測試數(shù)據(jù)的反饋,可以調(diào)整你的算法。但是不要為了性能盲目的進(jìn)行優(yōu)化,性能優(yōu)化其實(shí)就是找一個(gè)平衡點(diǎn),原則是足夠用就好。
具體怎么做呢?對(duì)于上面的算法,我們?nèi)绻捎每臻g換時(shí)間的優(yōu)化方式,可以在計(jì)算 1 的個(gè)數(shù)的 n 函數(shù)上做一些優(yōu)化 ,比如加個(gè)緩存。
然后對(duì)比性能,如下圖所示::
完整的測試案例地址(https://jsperf.com/acm-perf/1)
測試性能對(duì)比
說到測試性能對(duì)比,這里主要收集一些實(shí)現(xiàn)方式,比如基于 jsperf 做一些對(duì)比。
如果有其他的實(shí)現(xiàn)方式,歡迎小伙伴留言補(bǔ)充。
jsperf 測試性能結(jié)果,如下圖所示::
完整的測試案例地址(https://jsperf.com/acm-r/1)
總結(jié)
這道題很有難度,用到的知識(shí)也很多,認(rèn)真想一想,一定能有很多收獲的,這道算題的解決,大致用到了以下這些知識(shí):
二進(jìn)制以及位運(yùn)算的知識(shí)
剪枝的思想
如何全方位、地毯式、走極端、多方面的對(duì)一個(gè)算法進(jìn)行性能測試
算法思想,算法設(shè)計(jì)相關(guān)的簡要知識(shí)
如何將極其抽象的問題進(jìn)行降維分析,化繁為簡
番外篇--復(fù)雜度
算法復(fù)雜度
這涉及到大 O 判斷法。(算法業(yè)內(nèi)一般不叫大 O ,叫 big O 連起來讀,比如 B溝N )
這部分內(nèi)容大家自行維基搜索吧,很詳細(xì)的。下面我們提一下,離我們工作很近的一種復(fù)雜度的計(jì)算法則。
如何判斷業(yè)務(wù)代碼的復(fù)雜度
對(duì)前端來說,大 O 判斷法不能太適用,其實(shí)還有一種很有趣的判斷復(fù)雜度的方法,它叫做 Tom McCabe 方法。
該方法很簡單,通過計(jì)算函數(shù)中 決策點(diǎn) 的數(shù)量來衡量復(fù)雜度。下面是一種計(jì)算決策點(diǎn)(結(jié)合前端)的方法:
從 1 開始,一直往下通過函數(shù)
一旦遇到 if while for else 或者帶有循環(huán)的高階函數(shù),比如 forEach map 等就加 1
給 case 語句中的每一種情況都加 1
比如下面代碼:
function?fun(arr,?n)?{
??let?len?=?arr.length
??for?(let?i?=?0;?i?<?len;?i++)?{
????if?(arr[i]?==?n)?{
????????// todo...
????}?else?{
????????// todo...
????}
??}
}
按照 Tom McCabe 方法來計(jì)算復(fù)雜度,那么這個(gè) fun 函數(shù)的決策點(diǎn)數(shù)量是 3 。知道決策點(diǎn)數(shù)量后,怎么知道其度量結(jié)果呢?這里有一個(gè)數(shù)值區(qū)間判斷:
| 0-5 | 這個(gè)函數(shù)可能還不錯(cuò) |
| 6-10 | 得想辦法簡化這個(gè)函數(shù)了 |
| 10+ | 把這個(gè)函數(shù)的某一部分拆分成另一個(gè)函數(shù)并調(diào)用他 |
從上面的判斷依據(jù)可以看出,我上面寫的代碼,數(shù)量是 3 ,可以稱為函數(shù)還不錯(cuò)。我個(gè)人覺得這個(gè)判斷方法還是很科學(xué)和簡單的,可以作為平時(shí)寫代碼時(shí)判斷函數(shù)需不需要重構(gòu)的一個(gè)考慮點(diǎn),畢竟一個(gè)函數(shù),一眼掃去,決策點(diǎn)數(shù)量大致就知道是多少了,很好計(jì)算。
感謝付出的小伙伴
非常感謝前端算法小分隊(duì)的成員一起努力攻克了這個(gè)題目。
特此感謝:
本文第一作者:小金剛(大佬)
github 地址:https://github.com/cbbfcd
掘金地址:https://juejin.im/user/593df367128fe1006aecb3cf
文章排版和內(nèi)容深度完善:源碼終結(jié)者
github 地址:https://github.com/godkun
參與審校和核對(duì):Ninja
github 地址:https://github.com/jiameng123
其他小伙伴的貢獻(xiàn):前端狂想錄算法小分隊(duì)整體成員
編者:此外還有一篇《改進(jìn),從一個(gè)數(shù)組中找出 N 個(gè)數(shù),其和為 M 的所有可能》(https://juejin.im/post/5c81fee66fb9a049b82b4128),采用的是二進(jìn)制正序表示法,各位同學(xué)可以對(duì)照看一下。
關(guān)于奇舞周刊
《奇舞周刊》是360公司專業(yè)前端團(tuán)隊(duì)「奇舞團(tuán)」運(yùn)營的前端技術(shù)社區(qū)。關(guān)注公眾號(hào)后,直接發(fā)送鏈接到后臺(tái)即可給我們投稿。
總結(jié)
以上是生活随笔為你收集整理的c++如何输入数组_从一个数组中找出 N 个数,其和为 M 的所有可能最 nice 的解法...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 航空工业集团:运五 B 灭火型取证机机身
- 下一篇: 增幅不超过 20%,消息称苹果 A17