日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

如何用Java實(shí)現(xiàn)排列組合算法

瀏覽:22日期:2022-08-11 17:36:09
目錄需求從排列到組合-窮舉從排列到組合-分治分治思想代碼實(shí)現(xiàn)直擊本質(zhì)-位運(yùn)算思想代碼實(shí)現(xiàn)小結(jié)需求

我們的數(shù)據(jù)表有多個(gè)維度,任意多個(gè)維度組合后進(jìn)行 group by 可能會(huì)產(chǎn)生一些”奇妙”的反應(yīng),由于不確定怎么組合,就需要將所有的組合都列出來(lái)進(jìn)行嘗試。

抽象一下就是從一個(gè)集合中取出任意元素,形成唯一的組合。如[a,b,c]可組合為[a]、[b]、[c]、[ab]、[bc]、[ac]、[abc]。

要求如下:

組合內(nèi)的元素?cái)?shù)大于 0 小于等于 數(shù)組大小; 組合內(nèi)不能有重復(fù)元素,如 [aab] 是不符合要求的組合; 組合內(nèi)元素的位置隨意,即 [ab] 和 [ba] 視為同一種組合;

看到這里,就應(yīng)該想到高中所學(xué)習(xí)的排列組合了,同樣是從集合中取出元素形成一個(gè)另一個(gè)集合,如果集合內(nèi)元素位置隨意,就是組合,從 b 個(gè)元素中取 a 個(gè)元素的組合有種。而如果要求元素順序不同也視為不同集合的話(huà),就是排列,從 m 個(gè)元素取 n 個(gè)元素的排列有種。

我遇到的這個(gè)需求就是典型的組合,用公式來(lái)表示就是從元素個(gè)數(shù)為 n 的集合中列出種組合。

從排列到組合-窮舉

對(duì)于這種需求,首先想到的當(dāng)然是窮舉。由于排列的要求較少,實(shí)現(xiàn)更簡(jiǎn)單一些,如果我先找出所有排列,再剔除由于位置不同而重復(fù)的元素,即可實(shí)現(xiàn)需求。假設(shè)需要從 [A B C D E] 五個(gè)元素中取出所有組合,那么我們先找出所有元素的全排列,然后再將類(lèi)似 [A B] 和 [B A] 兩種集合去重即可。

我們又知道,那么我們先考慮一種情況,假設(shè)是,從 5 個(gè)元素中選出三個(gè)進(jìn)行全排列。

被選取的三個(gè)元素,每一個(gè)都可以是 ABCDE 之一,然后再排除掉形成的集合中有重復(fù)元素的,就是 5 選 3 的全排列了。

代碼是這樣:

private static Set<Set<String>> exhaustion() { List<String> m = Arrays.asList('a', 'b', 'c', 'd', 'e'); Set<Set<String>> result = new HashSet<>(); int count = 3; for (int a = 1; a < m.size(); a++) {for (int b = 0; b < m.size(); b++) { for (int c = 0; c < m.size(); c++) {Set<String> tempCollection = new HashSet<>();tempCollection.add(m.get(a));tempCollection.add(m.get(b));tempCollection.add(m.get(c));// 如果三個(gè)元素中有重復(fù)的會(huì)被 Set 排重,導(dǎo)致 Set 的大小不為 3if (tempCollection.size() == count) { result.add(tempCollection);} }} } return result;}

對(duì)于結(jié)果組合的排重,我借用了 Java 中 HashSet 的兩個(gè)特性:

元素唯一性,選取三個(gè)元素放到 Set 內(nèi),重復(fù)的會(huì)被過(guò)濾掉,那么就可以通過(guò)集合的大小來(lái)判斷是否有重復(fù)元素了, 元素?zé)o序性,Set[A B] 和 Set[B A] 都會(huì)被表示成 Set[A B]。 另外又由于元素唯一性,被同時(shí)表示為 Set[A B] 的多個(gè)集合只會(huì)保留一個(gè),這樣就可以幫助將全排列轉(zhuǎn)為組合。

可以注意得到,上面程序中 count 參數(shù)是寫(xiě)死的,如果需要取出 4 個(gè)元素的話(huà)就需要四層循環(huán)嵌套了,如果取的元素個(gè)取是可變的話(huà),普通的編碼方式就不適合了。

注: 可變層數(shù)的循環(huán)可以用遞歸來(lái)實(shí)現(xiàn)。

從排列到組合-分治

窮舉畢竟太過(guò)暴力,我們來(lái)通過(guò)分治思想來(lái)重新考慮一下這個(gè)問(wèn)題:

分治思想

分治的思想總的來(lái)說(shuō)就是”大事化小,小事化了”,它將復(fù)雜的問(wèn)題往簡(jiǎn)單劃分,直到劃分為可直接解決的問(wèn)題,再?gòu)倪@個(gè)直接可以解決的問(wèn)題向上聚合,最后解決問(wèn)題。

從 M 個(gè)元素中取出 N 個(gè)元素整個(gè)問(wèn)題很復(fù)雜,用分治思想就可以理解為:

首先,如果我們已經(jīng)從 M 中元素取出了一個(gè)元素,那么集合中還剩下 M-1 個(gè),需要取的元素就剩下 N-1 個(gè)。 還不好解決的話(huà),我們假設(shè)又從 M-1 中取出了一個(gè)元素,集合中還剩下 M-2 個(gè),需要取的元素只剩下 N-2 個(gè)。 直到我們可能取了有 M-N+1 次,需要取的元素只剩下一個(gè)了,再?gòu)氖S嗉现腥。褪且粋€(gè)簡(jiǎn)單問(wèn)題了,很簡(jiǎn)單,取法有 M-N+1 種。 如果我們解決了這個(gè)問(wèn)題,已經(jīng)取完最后一次了產(chǎn)生了 M-N+1 種臨時(shí)集合,再考慮從 M-N+2 個(gè)元素中取一個(gè)元素呢,又有 M-N+2 種可能。 將這些可能聚合到一塊,直到取到了 N 個(gè)元素,這個(gè)問(wèn)題也就解決了。

還是從 5 個(gè)元素中取 3 個(gè)元素的示例:

從 5 個(gè)元素中取 3 個(gè)元素是一個(gè)復(fù)雜問(wèn)題,為了簡(jiǎn)化它,我們認(rèn)為已經(jīng)取出了一個(gè)元素,還要再?gòu)氖S嗟?4 個(gè)元素中取出 2 個(gè),求解公式為:。 從 4 個(gè)元素中取出 2 個(gè)依舊不易解決,那我們?cè)偌僭O(shè)又取出了一個(gè)元素,接下來(lái)的問(wèn)題是如何從 3 個(gè)元素中取一個(gè),公式為。 從 3 個(gè)元素中取 1 個(gè)已經(jīng)是個(gè)簡(jiǎn)單問(wèn)題了,有三種可能,再向上追溯,與四取一、五取一的可能性做乘,從而解決這個(gè)問(wèn)題。代碼實(shí)現(xiàn)

用代碼實(shí)現(xiàn)如下:

public class Combination { public static void main(String[] args) {List<String> m = Arrays.asList('a', 'b', 'c', 'd', 'e');int n = 5;Set<Set<String>> combinationAll = new HashSet<>();// 先將問(wèn)題分解成 五取一、五取二... 等的全排列for (int c = 1; c <= n; c++) { combinationAll.addAll(combination(m, new ArrayList<>(), c));}System.out.println(combinationAll); } private static Set<Set<String>> combination(List<String> remainEle, List<String> tempCollection, int fetchCount) {if (fetchCount == 1) { Set<Set<String>> eligibleCollections = new HashSet<>(); // 在只差一個(gè)元素的情況下,遍歷剩余元素為每個(gè)臨時(shí)集合生成多個(gè)滿(mǎn)足條件的集合 for (String ele : remainEle) {Set<String> collection = new HashSet<>(tempCollection);collection.add(ele);eligibleCollections.add(collection); } return eligibleCollections;}fetchCount--;Set<Set<String>> result = new HashSet<>();// 差多個(gè)元素時(shí),從剩余元素中取出一個(gè),產(chǎn)生多個(gè)臨時(shí)集合,還需要取 count-- 個(gè)元素。for (int i = 0; i < remainEle.size(); i++) { List<String> collection = new ArrayList<>(tempCollection); List<String> tempRemain = new ArrayList<>(remainEle); collection.add(tempRemain.remove(i)); result.addAll(combination(tempRemain, collection, fetchCount));}return result; }}

其實(shí)現(xiàn)就是遞歸,關(guān)于遞歸和分治,有興趣可以看一下隱藏篇:遞歸和分治。

直擊本質(zhì)-位運(yùn)算

從元素的全排列找全組合,比窮舉略好,但還不是最好的方法,畢竟它”繞了一次道”。

很多算法都能通過(guò)位運(yùn)算巧秒地解決,其優(yōu)勢(shì)主要有兩點(diǎn):一者位運(yùn)算在計(jì)算機(jī)中執(zhí)行效率超高,再者由于位運(yùn)算語(yǔ)義簡(jiǎn)單,算法大多直指本質(zhì)。

組合算法也能通過(guò)位運(yùn)算實(shí)現(xiàn)。

思想

再次考慮全組合的需求,從 M 個(gè)元素中取任意個(gè)元素形成組合,組合內(nèi)元素不能重復(fù)、元素位置無(wú)關(guān)。

之前的方法都是從結(jié)果組合是否滿(mǎn)足要求來(lái)考慮問(wèn)題,考慮組合是否有重復(fù)元素、是否已有同樣的組合等條件。如果換種思路,從待選元素上來(lái)考慮呢?

對(duì)于每個(gè)元素來(lái)說(shuō),它的狀態(tài)就簡(jiǎn)單得多了,要么被放進(jìn)組合,要么不放進(jìn)組合。每個(gè)元素都有這么兩種狀態(tài)。如果從 5 個(gè)元素中任意取 N 個(gè)元素形成組合的話(huà),用二進(jìn)制位來(lái)表示每個(gè)元素是否被放到組合里,就是:

A  B  C  D  E

0  0  0  0  1   [E] = 1

A  B  C  D  E

0  0  0  1  0   [D] = 2

A  B  C  D  E

0  0  0  1  1   [DE] = 3

...

看到這里,應(yīng)該就非常清楚了吧,每種組合都可以拆解為 N 個(gè)二進(jìn)制位的表達(dá)形式,而每個(gè)二進(jìn)制組合同時(shí)代表著一個(gè)十進(jìn)制數(shù)字,所以每個(gè)十進(jìn)制數(shù)字都就能代表著一種組合。

十進(jìn)制數(shù)字的數(shù)目我們很簡(jiǎn)單就能算出來(lái),從00000...到11111...一共有種,排除掉全都不被放進(jìn)組合這種可能,結(jié)果有種。

代碼實(shí)現(xiàn)

下面是 Java 代碼的實(shí)現(xiàn):

public class Combination { public static void main(String[] args) {String[] m = {'A', 'B', 'C', 'D', 'E'};Set<Set<String>> combinationAll = combination(m);System.out.println(combinationAll); } private static Set<Set<String>> combination(String[] m) {Set<Set<String>> result = new HashSet<>();for (int i = 1; i < Math.pow(2, m.length) - 1; i++) { Set<String> eligibleCollections = new HashSet<>(); // 依次將數(shù)字 i 與 2^n 按位與,判斷第 n 位是否為 1 for (int j = 0; j < m.length; j++) {if ((i & (int) Math.pow(2, j)) == Math.pow(2, j)) { eligibleCollections.add(m[j]);} } result.add(eligibleCollections);}return result; }}小結(jié)

排列和組合算法在實(shí)際應(yīng)用中很常見(jiàn),而且他們的實(shí)現(xiàn)方法也非常具有參考意義。總的來(lái)說(shuō):排列用遞歸、組合用位運(yùn)算。

以上就是如何用Java實(shí)現(xiàn)排列組合算法的詳細(xì)內(nèi)容,更多關(guān)于用Java實(shí)現(xiàn)排列組合算法的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
精品一区二区三区中文字幕视频| 亚洲天堂1区| 久久中文欧美| 日韩精品视频网| 美女精品在线观看| 五月天久久777| 久久精品999| 亚洲精品日本| 久久久国产精品一区二区中文| 国产精品网站在线看| 日韩中文字幕麻豆| 免费精品视频最新在线| 久久国产高清| 99国产精品视频免费观看一公开| 成人在线网站| 伊人久久大香线蕉av不卡| 四虎884aa成人精品最新| 天堂а√在线最新版中文在线| 国产一区二区精品久| 久久久亚洲欧洲日产| 亚洲精品成人一区| 模特精品在线| 亚洲涩涩av| 伊人久久大香线蕉av超碰演员| 国产精品成人3p一区二区三区| 亚洲深夜视频| 久久电影tv| 日本高清不卡一区二区三区视频| 欧美xxxx中国| 日韩精品dvd| 亚洲精品一级二级| 欧美影院三区| 日韩中文字幕一区二区三区| 亚洲精品乱码| 欧美天堂一区二区| 麻豆精品新av中文字幕| 欧洲一区二区三区精品| 午夜国产精品视频免费体验区| 日韩精品诱惑一区?区三区| 今天的高清视频免费播放成人| 亚洲激情精品| 少妇精品久久久一区二区三区| 国产免费久久| 六月婷婷综合| 欧美~级网站不卡| 亚洲精品影视| 欧美成a人片免费观看久久五月天| 精品国产一区二区三区av片| 国产一区福利| 伊人久久大香线蕉av不卡| 日韩视频久久| 日本成人在线网站| 国产一区二区三区探花| 亚洲综合在线电影| 免费国产自线拍一欧美视频| 欧美日韩精品一区二区三区视频 | 日韩精品一二三四| 国产一卡不卡| 91精品蜜臀一区二区三区在线| 亚洲香蕉久久| 四虎8848精品成人免费网站| 亚洲专区在线| 国产精品扒开腿做爽爽爽软件| 高清不卡亚洲| 美女黄网久久| 日本天堂一区| 久久精品成人| 天堂av一区| 国产美女高潮在线观看| 亚洲一区二区三区四区五区午夜| 国产毛片精品| 欧美/亚洲一区| 欧美日韩 国产精品| 中文字幕在线高清| 亚洲精品乱码日韩| 日本韩国欧美超级黄在线观看| 日韩高清三区| 久久伦理在线| 国产三级一区| 亚洲综合电影一区二区三区| 青青草国产成人99久久| 欧美aa一级| 日韩av不卡在线观看| 免费视频国产一区| 久久精品国产99国产精品| 日韩中文字幕亚洲一区二区va在线 | 国产精品一区二区三区www| av一区在线| 日本欧美一区| 欧美成人久久| 麻豆成人综合网| 蜜桃91丨九色丨蝌蚪91桃色| 国产精品日本一区二区不卡视频 | 青青伊人久久| 亚洲免费中文| 99精品在线观看| 麻豆精品视频在线观看免费| 亚洲综合五月| 99亚洲视频| 久久精品国产大片免费观看| 欧美激情视频一区二区三区免费 | 91亚洲精品在看在线观看高清| 久久久久99| 精品亚洲成人| 亚洲精品婷婷| 久久国产亚洲| 九九99久久精品在免费线bt| 在线国产一区二区| 欧美sm一区| 久久久久伊人| 国产日韩欧美三级| 日本一区二区三区视频在线看| 日韩午夜av在线| 1024精品一区二区三区| 国产一区二区三区日韩精品 | 免费看日韩精品| 亚洲精品1区| 欧美特黄一级大片| 久久天堂成人| 99久久久久| 精品亚洲美女网站| 日韩欧美午夜| 久久亚洲国产精品一区二区| 亚洲精品日韩久久| 国产精品白丝久久av网站| 国产va免费精品观看精品视频| 91综合网人人| 五月精品视频| 日韩精品久久久久久| 国产精品地址| 亚洲成人国产| 日韩二区在线观看| 老牛影视精品| 日韩中文字幕91| 你懂的亚洲视频| 亚洲黑丝一区二区| 视频一区日韩精品| 91亚洲国产| 日韩制服丝袜av| 精品美女久久| 日韩影院在线观看| 高清日韩中文字幕| 黄页网站一区| 国产精品s色| 欧美在线亚洲| 免费在线观看一区| 午夜在线精品| 国产精品蜜芽在线观看| 午夜一区在线| 欧美黄色一区二区| 模特精品在线| 福利一区在线| 亚洲专区视频| 超碰成人av| 日韩精品免费视频人成| 成人啊v在线| 久久国产尿小便嘘嘘| 夜鲁夜鲁夜鲁视频在线播放| 欧美一区91| 亚洲欧洲一区二区天堂久久| 国产精品一区二区精品视频观看| 欧美日韩中文一区二区| 久久国产免费看| 婷婷综合在线| 久久久久久色 | 亚洲精品在线a| 日韩欧美国产精品综合嫩v| 国产日韩免费| 玖玖精品视频| 首页国产精品| 日本成人在线不卡视频| 欧美a级片一区| 精品成av人一区二区三区| 91免费精品国偷自产在线在线| 欧美.日韩.国产.一区.二区| 久久久久久婷| 国产精品一区2区3区| 久久国产66| 尤物tv在线精品| 日韩美女一区二区三区在线观看| 国产精品调教| 日本亚洲欧洲无免费码在线| 伊人久久成人| 国精品一区二区三区| 高清日韩中文字幕| 国产另类在线| 69精品国产久热在线观看| 免费在线成人网| 国产一级一区二区| 午夜日韩福利| 久久视频精品| 久久一区二区三区喷水| 伊人网在线播放| 红杏一区二区三区| 国产福利一区二区精品秒拍 | 亚洲欧洲一区二区天堂久久| 久久精品国产亚洲夜色av网站| 九九九精品视频| 老牛国内精品亚洲成av人片 | 日韩中文字幕不卡|