电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

如何用Java實現排列組合算法

瀏覽:2日期:2022-08-11 17:36:09
目錄需求從排列到組合-窮舉從排列到組合-分治分治思想代碼實現直擊本質-位運算思想代碼實現小結需求

我們的數據表有多個維度,任意多個維度組合后進行 group by 可能會產生一些”奇妙”的反應,由于不確定怎么組合,就需要將所有的組合都列出來進行嘗試。

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

要求如下:

組合內的元素數大于 0 小于等于 數組大小; 組合內不能有重復元素,如 [aab] 是不符合要求的組合; 組合內元素的位置隨意,即 [ab] 和 [ba] 視為同一種組合;

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

我遇到的這個需求就是典型的組合,用公式來表示就是從元素個數為 n 的集合中列出種組合。

從排列到組合-窮舉

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

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

被選取的三個元素,每一個都可以是 ABCDE 之一,然后再排除掉形成的集合中有重復元素的,就是 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));// 如果三個元素中有重復的會被 Set 排重,導致 Set 的大小不為 3if (tempCollection.size() == count) { result.add(tempCollection);} }} } return result;}

對于結果組合的排重,我借用了 Java 中 HashSet 的兩個特性:

元素唯一性,選取三個元素放到 Set 內,重復的會被過濾掉,那么就可以通過集合的大小來判斷是否有重復元素了, 元素無序性,Set[A B] 和 Set[B A] 都會被表示成 Set[A B]。 另外又由于元素唯一性,被同時表示為 Set[A B] 的多個集合只會保留一個,這樣就可以幫助將全排列轉為組合。

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

注: 可變層數的循環可以用遞歸來實現。

從排列到組合-分治

窮舉畢竟太過暴力,我們來通過分治思想來重新考慮一下這個問題:

分治思想

分治的思想總的來說就是”大事化小,小事化了”,它將復雜的問題往簡單劃分,直到劃分為可直接解決的問題,再從這個直接可以解決的問題向上聚合,最后解決問題。

從 M 個元素中取出 N 個元素整個問題很復雜,用分治思想就可以理解為:

首先,如果我們已經從 M 中元素取出了一個元素,那么集合中還剩下 M-1 個,需要取的元素就剩下 N-1 個。 還不好解決的話,我們假設又從 M-1 中取出了一個元素,集合中還剩下 M-2 個,需要取的元素只剩下 N-2 個。 直到我們可能取了有 M-N+1 次,需要取的元素只剩下一個了,再從剩余集合中取,就是一個簡單問題了,很簡單,取法有 M-N+1 種。 如果我們解決了這個問題,已經取完最后一次了產生了 M-N+1 種臨時集合,再考慮從 M-N+2 個元素中取一個元素呢,又有 M-N+2 種可能。 將這些可能聚合到一塊,直到取到了 N 個元素,這個問題也就解決了。

還是從 5 個元素中取 3 個元素的示例:

從 5 個元素中取 3 個元素是一個復雜問題,為了簡化它,我們認為已經取出了一個元素,還要再從剩余的 4 個元素中取出 2 個,求解公式為:。 從 4 個元素中取出 2 個依舊不易解決,那我們再假設又取出了一個元素,接下來的問題是如何從 3 個元素中取一個,公式為。 從 3 個元素中取 1 個已經是個簡單問題了,有三種可能,再向上追溯,與四取一、五取一的可能性做乘,從而解決這個問題。代碼實現

用代碼實現如下:

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<>();// 先將問題分解成 五取一、五取二... 等的全排列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<>(); // 在只差一個元素的情況下,遍歷剩余元素為每個臨時集合生成多個滿足條件的集合 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<>();// 差多個元素時,從剩余元素中取出一個,產生多個臨時集合,還需要取 count-- 個元素。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; }}

其實現就是遞歸,關于遞歸和分治,有興趣可以看一下隱藏篇:遞歸和分治。

直擊本質-位運算

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

很多算法都能通過位運算巧秒地解決,其優勢主要有兩點:一者位運算在計算機中執行效率超高,再者由于位運算語義簡單,算法大多直指本質。

組合算法也能通過位運算實現。

思想

再次考慮全組合的需求,從 M 個元素中取任意個元素形成組合,組合內元素不能重復、元素位置無關。

之前的方法都是從結果組合是否滿足要求來考慮問題,考慮組合是否有重復元素、是否已有同樣的組合等條件。如果換種思路,從待選元素上來考慮呢?

對于每個元素來說,它的狀態就簡單得多了,要么被放進組合,要么不放進組合。每個元素都有這么兩種狀態。如果從 5 個元素中任意取 N 個元素形成組合的話,用二進制位來表示每個元素是否被放到組合里,就是:

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

...

看到這里,應該就非常清楚了吧,每種組合都可以拆解為 N 個二進制位的表達形式,而每個二進制組合同時代表著一個十進制數字,所以每個十進制數字都就能代表著一種組合。

十進制數字的數目我們很簡單就能算出來,從00000...到11111...一共有種,排除掉全都不被放進組合這種可能,結果有種。

代碼實現

下面是 Java 代碼的實現:

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<>(); // 依次將數字 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; }}小結

排列和組合算法在實際應用中很常見,而且他們的實現方法也非常具有參考意義。總的來說:排列用遞歸、組合用位運算。

以上就是如何用Java實現排列組合算法的詳細內容,更多關于用Java實現排列組合算法的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
主站蜘蛛池模板: 建筑消防设施检测系统检测箱-电梯**检测仪器箱-北京宇成伟业科技有限责任公司 | 有声小说,听书,听小说资源库-听世界网| 外贸网站建设-外贸网站设计制作开发公司-外贸独立站建设【企术】 | 购买舔盐、舔砖、矿物质盐压块机,鱼饵、鱼饲料压块机--请到杜甫机械 | 四川实木门_成都实木门 - 蓬溪聚成门业有限公司 | 中控室大屏幕-上海亿基自动化控制系统工程有限公司 | 实验室pH计|电导率仪|溶解氧测定仪|离子浓度计|多参数水质分析仪|pH电极-上海般特仪器有限公司 | 袋式过滤器,自清洗过滤器,保安过滤器,篮式过滤器,气体过滤器,全自动过滤器,反冲洗过滤器,管道过滤器,无锡驰业环保科技有限公司 | 塑料造粒机「厂家直销」-莱州鑫瑞迪机械有限公司 | 有机废气处理-rto焚烧炉-催化燃烧设备-VOC冷凝回收装置-三梯环境 | 安平县鑫川金属丝网制品有限公司,声屏障,高速声屏障,百叶孔声屏障,大弧形声屏障,凹凸穿孔声屏障,铁路声屏障,顶部弧形声屏障,玻璃钢吸音板 | 上海地磅秤|电子地上衡|防爆地磅_上海地磅秤厂家–越衡称重 | 权威废金属|废塑料|废纸|废铜|废钢价格|再生资源回收行情报价中心-中废网 | 江苏远邦专注皮带秤,高精度皮带秤,电子皮带秤研发生产 | 家乐事净水器官网-净水器厂家「官方」 | 食品机械专用传感器-落料放大器-低价接近开关-菲德自控技术(天津)有限公司 | 上海单片机培训|重庆曙海培训分支机构—CortexM3+uC/OS培训班,北京linux培训,Windows驱动开发培训|上海IC版图设计,西安linux培训,北京汽车电子EMC培训,ARM培训,MTK培训,Android培训 | 数显恒温油浴-电砂浴-高温油浴振荡器-常州迈科诺仪器有限公司 | 软启动器-上海能曼电气有限公司 真空搅拌机-行星搅拌机-双行星动力混合机-广州市番禺区源创化工设备厂 | 顺景erp系统_erp软件_erp软件系统_企业erp管理系统-广东顺景软件科技有限公司 | led全彩屏-室内|学校|展厅|p3|户外|会议室|圆柱|p2.5LED显示屏-LED显示屏价格-LED互动地砖屏_蕙宇屏科技 | 高清视频编码器,4K音视频编解码器,直播编码器,流媒体服务器,深圳海威视讯技术有限公司 | 柴油机_柴油发电机_厂家_品牌-江苏卡得城仕发动机有限公司 | 板材品牌-中国胶合板行业十大品牌-环保板材-上海声达板材 | 玉米深加工设备-玉米深加工机械-新型玉米工机械生产厂家-河南粮院机械制造有限公司 | PCB接线端子_栅板式端子_线路板连接器_端子排生产厂家-置恒电气 喷码机,激光喷码打码机,鸡蛋打码机,手持打码机,自动喷码机,一物一码防伪溯源-恒欣瑞达有限公司 假肢-假肢价格-假肢厂家-河南假肢-郑州市力康假肢矫形器有限公司 | 丝印油墨_水性油墨_环保油墨油漆厂家_37国际化工 | 广东燎了网络科技有限公司官网-网站建设-珠海网络推广-高端营销型外贸网站建设-珠海专业h5建站公司「了了网」 | 铝合金重力铸造_铝合金翻砂铸造_铝铸件厂家-东莞市铝得旺五金制品有限公司 | 高压管道冲洗清洗机_液压剪叉式升降机平台厂家-林君机电 | 东风体检车厂家_公共卫生体检车_医院体检车_移动体检车-锦沅科贸 | 全自动包衣机-无菌分装隔离器-浙江迦南科技股份有限公司 | 中医中药治疗血小板减少-石家庄血液病肿瘤门诊部 | 餐饮小吃技术培训-火锅串串香培训「何小胖培训」_成都点石成金[官网] | 电动高尔夫球车|电动观光车|电动巡逻车|电动越野车厂家-绿友机械集团股份有限公司 | 上海洗地机-洗地机厂家-全自动洗地机-手推式洗地机-上海滢皓洗地机 | 长沙一级消防工程公司_智能化弱电_机电安装_亮化工程专业施工承包_湖南公共安全工程有限公司 | Safety light curtain|Belt Sway Switches|Pull Rope Switch|ultrasonic flaw detector-Shandong Zhuoxin Machinery Co., Ltd | 安徽集装箱厂-合肥国彩钢结构板房工程有限公司| 磁力抛光机_磁力研磨机_磁力去毛刺机_精密五金零件抛光设备厂家-冠古科技 | 大米加工设备|大米加工机械|碾米成套设备|大米加工成套设备-河南成立粮油机械有限公司 |