排列組合的寫法 茴香豆 組合序列生成的四種寫法

2021-10-14 14:35:03 字數 2522 閱讀 4446

偶爾無聊,生搬硬湊下組合序列生成的四種寫法。

組合,combination,或者說n choose k的問題。一般在命令式程式語言中,採用生成器的方式來完成。大體就是儲存狀態,按序列生成。這種方式的標準方式,參考c++的algorithm的庫。在python中,使用itertools生成出來。原理都是相似的。

在函式式程式語言中,則有著不同的思路。函式式程式語言中,不提倡使用狀態這種方式。或者說通過遞迴呼叫+延遲計算的方式,綜合起來的特性,得到數學結構上更為優美的解法。

我們約定組合序列生成的函式為comb :: int -> [a] -> a, comb k xs,其中k為選擇個數,xs為待選取列表。生成結果為乙個列表的列表。在數學表示式中,我們按照中國約定俗稱的c(n,k),表示從n個中選取k個。注意下面的**示例,可以左右撥動。

我們知道關於組合有一些基本的公式。根據這些公式,其實組合問題,實在逐步遞降的(待組合的列表更短,或者選擇個數k變小)。而以下的種種寫法,其實都是由背後的公式推演出來的。

比如我們有公式c(n+1,k) = c(n,k-1) + c(n,k)

這個公式的含義為從n+1個中選取k個,等價於固定選擇女朋友,從剩餘n中選擇k-1個;或者直接選擇不帶女朋友,從剩餘n中選擇k個。

也就是組合分成兩種情況,選擇了第乙個,或者丟棄第乙個的。所有結果,等於這二者之和。這種方式,兩個分支中,都縮減了問題的規模。故而函式遞迴是可以窮盡的。

這個公式理解最為普遍。大名鼎鼎的楊輝三角,就是按照這個公式來進行推演的。

按照這種理解,我們有haskell**:

comb k (x:xs) = map (x:) (comb (k - 1) xs))     ++ (comb k xs)
(x:xs)為模式匹配,匹配第乙個元素為x,剩餘列表為xs。結果為兩者之和,++,表示兩部分結果合併。前半部分,給comb (k-1) xs的結果,每乙個都新增了x作為頭。後半部分,則在xs中選擇k個。這行**與上面的公式完美對映。

這個公式的含義為在n+1個中選擇k+1個,等於以下情況之和:

按照這個公式,我們利用haskell中的tails函式。這個函式生成序列的每個字尾。

tails [0..3][[0,1,2,3],[1,2,3],[2,3],[3],]
我們對每個字尾序列,都固定選擇其頭部的元素,剩餘的選擇k個。有haskell**如下。f函式,就是固定選擇頭t,剩下的在遞迴到組合函式comb。這樣得到的結果,再全部累積一起,通過concat函式。

comb k xs = concatmap f (tails xs)    where f  =           f (t:ts) = map (t:) (comb (k - 1) ts)
這個公式的意思為將待選列表分為兩部分m和n,然後等於下列情況之和

這種方式的最大的好處是,直接將m+n的問題量級降低到其一半水平。用這種方式,理論上將問題從o(n)的方式,可以轉換為o(logn)。因為我們生成的是全序列,這種差異體現不出來。

這裡我們要注意列表相乘運算,也就是m中選擇的i中情況,與n中選擇k-i中情況,是可以交叉配對的。也就是第乙個結果中的任一乙個列表,可以和後乙個結果中的任乙個列表構成一組新的結果。更形象一點,就是我的選擇i種情況出來的a結果,與你的選擇k-i種情況出來的b結果,都可以組合在一起,然後形成選擇為k個物件的結果。這個結果的個數為a*b=ab。

這等價於排列組合的乘法原理,也等價於笛卡爾積的過程。按照haskell中的實現,我們直接利用liftm2,這個monad輔助函式實現了。

prod :: a -> a -> aprod xs ys = liftm2 (++) xs ys
我們有最終的**:

comb k xs = concatmap               (\i -> prod (comb (k-i) hd) (comb i tl))              [0..k]    where (hd, tl) = halve xs
從hd中選擇k-i個,出來的結果,與tl中選擇i個,乘在一起,最終相concat,構成新的結果。

綜上,我們可以看到在函式式語言中,可以按照數學公式寫出非常優雅的**。而且因為其中的邏輯清晰,不需要關心更多細節的狀態問題,相對更容易做到bug-free。這種書寫**的方式,目前也在和其他程式設計正規化在相互融合。了解下,就當一起玩下吧。

排列組合數學 子串行

題目描述 給定乙個小寫字母字串t 求有多少長度為m的小寫字母字串s滿足,t是s的乙個子串行 不需要連續 輸入描述 第一行乙個字串t 第二行乙個正整數m 輸出描述 輸出答案對109 7取模的值 示例1輸入a2 輸出51 說明長度為2的裡面有a的串有51種 備註 1 t m 105 列舉終點,前面的除了...

c 排列組合 UV機的顏色排列組合形式

隨著近幾年來uv應用的極速發展,也伴隨著大規模的生產使得uv機成本大幅度的下降,uv可謂是 舊時王謝堂前燕,飛入眾多廣告店。uv機以其應用廣泛,遍布無數行業,正是 uv應用範圍廣,尊稱萬能名號響。大到街邊廣告牌,小至手中鑰匙串。屋外門前地腳墊,家中電視背景牆。目之所及皆可見,細心觀察自然現。眾所周知...

排列組合的公式

排列的定義及其計算公式 從n個不同元素中,任取m m n,m與n均為自然數,下同 個元素按照一定的順序排成一列,叫做從n個不同元素中取出m個元素的乙個排列 從n個不同元素中取出m m n 個元素的所有排列的個數,叫做從n個不同元素中取出m個元素的排列數,用符號 a n,m 表示。a n,m n n ...