组合(从长度为n的字符串中取m个字符)---java两种实现方法

对于这类组合问题,虽然感觉很简单,但是用java代码实现起来却不是那么容易的。
这其中最容易用到的应该是递归的思想了,这种方法也比较容易理解:
方法一:
递归实现代码:

/**
     * 可能种类在4000万的时候时间效率为7.6s左右
     * @param headIndex:当前所要添加字符在原始字符串中的index
     * @param length:当前字符串长度
     * @param inStr:原始字符串
     * @param res:当前字符串
     * @param n:所要组合的字符串长度
     */
    public static void DiguiZuhe(int headIndex,int length,String inStr,String res,int n){
        String s = res;
        for (int i = headIndex; i < inStr.length() + length - n; i++) {
            if (length <= n) {
                res = res + inStr.substring(i, i + 1); 
                DiguiZuhe(i + 1, length + 1, inStr, res, n);
                if (length == n) {
                    System.out.println(res);
                }
            }else {
                return;
            }
            res = s;
        }
    }
    //-------------------------------分割线-----------------------------
    public static void main(String[] args) {
        String inStr = "abcdefg";
        int n = 3;
        String res = "";
        DiguiZuhe(0, 1, inStr, res, n);
    }

方法二:

/**
     * * 具体思路:将我们的原始的字符串用01数组来代替,0表示没有,1表示有
     * 例如:字符串:abcdefg;01数组:[1110000]->abc;[1010100]->ace
     * 长度为n的字符串,取m个字符
     * 首先会初始化一个01数组,长度为n,前m数字为1,后面n-m个数字为0
     * 然后扫描01数组,每一次发现10的时候,都给它变为01,同时将左边的1都移动到最左边,已经是最左边了就不移动,
     * 继续扫描直到所有的1都移动到了最右边
     * 例如:
     * 1 1 1 0 0
     * 1 1 0 1 0
     * 1 0 1 1 0
     * 0 1 1 1 0
     * 1 1 0 0 1
     * 1 0 1 0 1
     * 0 1 1 0 1
     * 1 0 0 1 1
     * 0 1 0 1 1
     * 0 0 1 1 1
     * 纯算法时间效率:可能种类在4千万左右时间为1.2s左右
     * @param input
     * @param strNum
     * @return
     */
    public static void Combination(String input,int strNum){

        int length = input.length();
        int[] array = new int[length];
        //如果长度相等,就只有一种可能
        if (length == strNum) {
            System.out.println(input);
            return;
        }else {
            //初始化数组
            for (int i = 0; i < length; i++) {
                if (i <= strNum -1) {
                    array[i] = 1;
                }else {
                    array[i] = 0;
                }
            }
        }
        while(isContainOneZero(array)){
            transform(array);
            //将01组成的数组转化为字符串,本来这种算法比较高效的,但是在这里转为String字符串的时候(当数据量特别大的时候)
            //主要时间开销就在这里了
            StringBuffer res = new StringBuffer();
            for (int i = 0; i < array.length; i++) {
                if (array[i] == 1) {
                    //拼接起来
                    res.append(input.charAt(i));
                }
            }
            System.out.println(res.toString());
        }
    }
    /**
     * 验证是否包含10
     * @param array
     * @return
     */
    public static boolean isContainOneZero(int[] array){

        for (int i = 0; i < array.length - 1; i++) {
            if (array[i] == 1 && array[i + 1] == 0) {
                return true;
            }
        }
        return false;
    }
    /**
     * 验证是否所有的1都移到了最左边
     * @param array
     * @param i
     * @return
     */
    public static boolean validate(int[] array,int i){

        for (int j = 0; j < i; j++) {
            if (array[j] == 0 && array[j + 1] == 1) {
                return true;
            }
        }
        return false;
    }
    /**
     * 转换数组
     * @param array
     */
    public static void transform(int[] array){

        for (int i = 0; i < array.length - 1; i++) {
            if (array[i] == 1 && array[i + 1] == 0) {
                swap(array, i, i + 1);
                int n = getOneNum(array, i);
                for (int j = 0; j < i; j++) {
                    if (j <= n - 1) {
                        array[j] = 1;
                    }else {
                        array[j] = 0;
                    }
                }
                return;
            }
        }
    }
    /**
     * 获取1的数量
     * @param array
     * @param i
     * @return
     */
    public static int getOneNum(int[] array,int i){
        int num = 0;
        for (int j = 0; j < i; j++) {
            if (array[j] == 1) {
                num++;
            }
        }
        return num;
    }
    /**
     * 交换方法
     * @param array
     * @param a
     * @param b
     */
    public static void swap(int[] array,int a,int b){

        array[a] = array[a] + array[b];
        array[b] = array[a] - array[b];
        array[a] = array[a] - array[b];     
    }

你可能感兴趣的:(面试题)