1. 程式人生 > >傻瓜方法求集合的全部子集問題(java版)

傻瓜方法求集合的全部子集問題(java版)

post 分解 ipp targe 找到 creat dojo class length

給定隨意長度的一個集合。用一個數組表示,如{"a", "b","c"},求它的全部子集。結果是{ {a}, {b}, {c}, {a,b}, {a,c}, {b,c}, {a,b,c}}和一個空集。

以下講的就是怎樣用一個原始的傻瓜方法(非算法)求它的全部子集。

首先我們知道是它的子集個數是2^length,假設長度是3,那子集就共同擁有2的3次方=8個,包含空集。

求子集,我的做法是對不論什麽一項做推斷,有或者無,用1和0來相應表示。

那麽像這樣的長度為3的,用二進制來表示就是000、001、010……

事實上就是從0-2^3,用2進制表示出來就是所以的子集了。然後把0相應的子項給拿掉。譬如010相應的就是b,011相應的就是bc。

僅僅須要從0到2^3-1做一個循環。然後把0-7之間的數用二進制表示出來,再與原集合進行對照。

把0相應位置的字符去掉,這樣就得到了全部子集。

原理非常easy,以下是代碼

package huisu;

/**
 * Created by wolf on 2016/3/22.
 */
public class GetSet {
    private String[] origin = {"a", "b", "c"};

    private String[] targetArray;

    public static void main(String[] args) {
          new GetSet().doJob();
    }
    
    private void doJob() {
        //獲取將要分解的字符串假設轉為2進制最大是幾
        //如字符串是3位。就是2^3。

從[0 0 0]到[1 1 1] int maxLength = (int) Math.pow(2, origin.length); targetArray = new String[maxLength]; for (int i = 0; i < targetArray.length; i++) { //十進制轉2進制 targetArray[i] = Integer.toBinaryString(i); } buling(); print(); } /** * 給空位補0,湊齊位數 */ private void buling() { for (int i = 0; i < targetArray.length; i++) { //位數是完整的,不須要補0 if (targetArray[i].length() == origin.length) { continue; } String temp = ""; //0,1,10,11,111 for (int j = 0; j < origin.length - targetArray[i].length(); j++) { temp += "0"; } targetArray[i] = temp + targetArray[i]; } } private void print(){ for (int i = 0; i < targetArray.length; i++) { String s = targetArray[i];//如000,001,010 for (int j = 0; j < s.length(); j++) { char item = s.charAt(j); if (item == '1') { System.out.print(origin[j]); } } System.out.println(); } } }

在第23行是將10進制的0-7轉成二進制,轉之後例如以下圖

技術分享

這裏就有個問題,那就是位數並不滿。像0、10之類的,將來和原始數組做相應推斷的時候有點小麻煩,所以我做了個處理,把位數補齊。保持和原始數組位數一樣。

調用了buling(原諒我想不起來用什麽英語來表示補零)方法。把位數不足的前面全補上0.然後就變成了000,001,010……這樣就能夠非常方便的去推斷了,僅僅打印1所在的位數即可了。參考print方法。

總結:這樣的做法比較簡單易懂。也能適應隨意長度的求子集問題。

依據這樣的做法,還能解決另外一個問題——01背包問題(有編號分別為a,b,c,d,e的五件物品。它們的重量各自是2,2,6,5,4,它們的價值各自是6,3,5,4,6。如今給你個承重為10的背包。怎樣讓背包裏裝入的物品具有最大的價值總和?)相信非常easy能看出來,上面的方法求出來了全部子集,那麽對於01背包問題。就是依據全部的子集。先砍掉全部超重的子集。然後去計算剩余的子集的價值,找到最大的就OK了。



傻瓜方法求集合的全部子集問題(java版)