逛奔的蜗牛

我不聪明,但我会很努力

   ::  :: 新随笔 ::  ::  :: 管理 ::

/**

 * 求 N 个元素中 M 个元素的组合算法:

 * 1. 创建一个大小为 N 个元素的数组,前 M 个元素为1,后面的 N-M 个元素为0

 * 2. 从左向右找到 10 的元素(前一个元素是1,下一个元素是0), 交换这两个元素;

 *    把此元素前面的所有1都移动到数组的最前面,此为一个组合,输出.

 * 3. 直到前 N-M 个元素都为0,则结束,否则继续第2步直到结束.

 */

public class Combinatory {

    public static void produceCombination(String str, int size) {

        if (size > str.length()) { throw new IllegalArgumentException("Size is to large."); }


        // 创建一个数组,前size个元素全是1

        int[] digit = new int[str.length()];

        for (int i = 0; i < size; ++i) {

            digit[i] = 1;

        }


        // 输出第一组

        printCombination(str, digit);


        while (!end(digit, digit.length - size)) {

            for (int i = 0; i < digit.length - 1; ++i) {

                if (digit[i] == 1 && digit[i + 1] == 0) {

                    // i上是1,i + 1是0,交换

                    int temp = digit[i];

                    digit[i] = digit[i + 1];

                    digit[i + 1] = temp;


                    // 移动i前面的所有1到最左端

                    int count = countOf1(digit, i);

                    for (int j = 0; j < count; ++j) {

                        digit[j] = 1;

                    }


                    for (int j = count; j < i; ++j) {

                        digit[j] = 0;

                    }


                    printCombination(str, digit);


                    break;

                }

            }

        }

    }


    // 在下标end前1的个数

    private static int countOf1(int[] digit, int end) {

        int count = 0;

        for (int i = 0; i < end; ++i) {

            if (digit[i] == 1) {

                ++count;

            }

        }


        return count;

    }


    // 数组中为1的下标对应的字符需要输出

    private static void printCombination(String str, int[] digit) {

        StringBuffer sb = new StringBuffer();

        for (int i = 0; i < digit.length; ++i) {

            if (digit[i] == 1) {

                sb.append(str.charAt(i));

            }

        }


        System.out.println(sb);

    }


    // 结束条件:前 size 个元素都是0

    private static boolean end(int[] digit, int size) {

        int sum = 0;


        for (int i = 0; i < size; ++i) {

            sum += digit[i];

        }


        return sum == 0 ? true : false;

    }


    public static void main(String[] args) {

        Combinatory.produceCombination("0123456789", 8);

    }

}


===============================================


import java.util.HashSet;

import java.util.Set;


/**

 * 求 N 个元素的全排列算法:

 * 1. 创建一个大小为 N 个元素的数组.

 * 2. 利用 N 进制,满 N 加 1的原则,对数组的第0个元素加 1,满 N 了,则下一个元素值加 1.

 * 3. 检查数组中的元素是否有重复的,如果没有,则是一个排列.

 * 4. 直到数组中的元素为0, 1, 2, ..., N - 1,则结束,否则继续第2步直到结束.

 */

public class Arrangement {

    public static void produceArrangement(String str) {

        int[] digit = new int[str.length()];

        int base = str.length();

        

        while (!end(digit)) {

            ++digit[0]; // 第1个元素值加1

            

            // 满N进1

            for (int i = 0; i < digit.length; ++i) {

                if (digit[i] == base) {

                    digit[i] = 0;

                    ++digit[i + 1];

                } else {

                    break;

                }

            }

            

            if (isArrangement(digit)) {

                printArrangement(str, digit);

            }

        }

    }

    

    // 数组中每个元素都不同,则是排列中的一个

    private static boolean isArrangement(int[] digit) {

        int sum = 0;

        int endSum = (0 + digit.length - 1) * digit.length / 2;

        

        for (int i = 0; i < digit.length; ++i) {

            sum += digit[i];

        }

        

        // 为了减少创建Set,所以判断一下数组中元素的和是不是结束时元素的和,如果是才再继续判断.

        if (sum != endSum) {

            return false;

        } else {

            Set<Integer> is = new HashSet<Integer>();

            for (int i : digit) {

                is.add(i);

            }

            

            if (is.size() != digit.length) {

                return false;

            } else {

                return true;

            }

        }

    }

    

    private static void printArrangement(String str, int[] digit) {

        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < digit.length; ++i) {

            sb.append(str.charAt(digit[i]));

        }

        

        System.out.println(sb);

    }


    // 如果数组中的元素是 0, 1, 2, ..., digit.length - 1,则结束

    private static boolean end(int[] digit) {

        for (int i = 0; i < digit.length; ++i) {

            if (digit[i] != i) {

                return false;

            }

        }

        

        return true;

    }

    

    public static void main(String[] args) {

        Arrangement.produceArrangement("012345");

    }

}


===============================================

/**

 * 使用递归求组合

 * 找到第i个元素后面的count - 1个元素的组合

 */

import java.util.ArrayList;

import java.util.Arrays;

import java.util.Collection;

import java.util.Iterator;

import java.util.List;


public class IterativeCombinatory {

    private List result;

    private String data;


    public IterativeCombinatory(String data, int count) {

        this.data = data;

        this.result = new ArrayList();


        buildCombinatory(0, count);

    }


    // 使用递归求组合

    public void buildCombinatory(int index, int count) {

        for (int i = index; i < data.length(); i++) {

            result.add("" + data.charAt(i));


            if (1 == count) {

                System.out.println(StringUtil.join(result, "+"));

            } else if (i + 1 < data.length()) {

                buildCombinatory(i + 1, count - 1); // 在i后面找count-1个的组合

            }


            result.remove("" + data.charAt(i)); // 满足一个后移除最后一个

        }

    }


    public static void main(String[] args) {

        String str = "123456";


        for (int count = 2; count <= str.length(); count++) {

            new IterativeCombinatory(str, count);

            System.out.println();

        }

    }

}


class StringUtil {

    public static String join(Object[] arr, String separator) {

        return join(Arrays.asList(arr), separator);

    }


    public static String join(Collection collection, String separator) {

        StringBuilder sb = new StringBuilder();

        separator = separator == null ? "" : separator;


        Iterator iter = collection.iterator();

        while (iter.hasNext()) {

            sb.append(iter.next());

            if (iter.hasNext()) {

                sb.append(separator);

            }

        }


        return sb.toString();

    }

}


 

posted on 2010-12-24 02:47 逛奔的蜗牛 阅读(713) 评论(0)  编辑 收藏 引用 所属分类: Java

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理