剑指Offer面试题28及其扩展:求字符的所有组合

题目描述:

如果不是求字符的所有排列,而是求字符的所有组合。比如,输入三个字符a,b,c,则它们的组合有a,b,c,ab,ac,bc,abc。当交换字符串中的两个字符时,虽然能得到两个不同的排列,但却是同一个组合,比如ab和ba是不同的排列,但只算一个组合

思路分析:

如果输入n个字符,则这n个字符能构成长度为1的组合,长度为2的组合,……..,长度为n的组合。在求n个字符长度的为m(1<=m<=n)的时候,我们把这n个字符分为两部分,第一个字符和其余的所有字符。如果组合里包括第一个字符,那么就从其余的字符里选取m-1个字符;如果组合里不包括第一个字符,那么就从其余字符里选取m个字符。
也就是说,我们可以把求n个字符组成长度为m的组合的问题分解成两个子问题:
1.求n-1个字符串中长度为m-1的组合
2.求n-1个字符串中长度为m的组合

package swordoffer.chapter4;

import java.util.ArrayList;

public class Interview28Extension {
    public static void main(String[] args){
        char[] str = {'a','b'};
        Interview28Extension ii = new Interview28Extension();
        ArrayList<Character> result = new ArrayList<>();
        for (int i = 1;i <= str.length;i++)
            ii.Combination(str,0,i,result);  //从数组中第一个字符开始,依次取num个,num >=1 && num <= 数组长度
    }
    /**
     * @param str    待排列组合的数组
     * @param begin  待取的下一个字符的在数组的起始位置索引
     * @param num    表示还需要取的字符的个数
     * @param result 保存每一种组合的字符
     */
    public void Combination(char[] str,int begin, int num, ArrayList<Character> result){
        if (str == null || str.length == 0)
            //注意:begin > str.length - 1这个条件不能放在这里一起判断
            // 因为有时候当num为0的时候,begin也满足begin>str.len-1,但是这时候我们已经在result中的字符是一种组合,应该保证先输出再返回
            return;
        if (num == 0){   //如果num为0,说明已经凑够了num个字符,直接输出并返回
            System.out.println(result);
            return;
        }
        if (begin > str.length-1)
            return;
        result.add(str[begin]);    //当前的字符被选中
        Combination(str,begin+1,num-1,result);   //则从索引位置为begin+1的位置开始选择剩下的num-1个字符
        result.remove(result.size()-1);    //当前的字符未被选中
        Combination(str,begin+1,num,result);   //则从索引位置为begin+1的位置继续选择num个字符
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值