组合问题
前几天学习的时候,看到一个问题,大概是这样的:
一共有m种颜色的糖果,在m种糖果里面选n种糖果,m,n都由用户输入,不考虑顺序,计算所有可能的组合,存入数据库。
首先我们要想到这类问题要用到递归,因为循环的层数是不固定的,并且在每层for都对应一个不同的起始位置,不同的次数。拿3选2为例,让大家更清晰的理解我说的是什么意思
1 for(int i=0;i<3;i++){ 2 for(int j=1;j<3-1;j++){ 3 for(int k=2;k<3-2;k++){ 4 5 } 6 } 7 }
通过上面的例子,我们可以看出来,某一层的起始位置都是上一层起始位置+1,层数则是上一层-1
那么我们大概就有一个思路了吧,废话不多说,贴代码
1 private static List<String> combineArr = new ArrayList<String>();//存组合的名称,但是一次只能存一个组合的名称 2 private static Integer showNum = 1;//组合的数量 3 4 public void creatCourseCombine(int moduleType, int needNum, String[] courseIdArr) { 5 generateCombine(0,needNum,courseIdArr); 6 } 7 8 /** 9 * 递归产生科目组合 10 * @param index:index从0开始,并且每层的i都是上一层i+1 11 * @param needNum:被选择的科目数量(控制循环的层数) 12 * @param courseArr:可以选择的课程(id) 13 */ 14 public void generateCombine(int index,int needNum,String []courseArr) { 15 if(needNum == 1){ //当needNum=1时,表示循环到最里层 16 for (int i = index; i < courseArr.length; i++) { //最里层,即组合的最后一位 17 combineArr.add(courseArr[i]); 18 startSavaCombine(combineArr,showNum);//组合的id 19 showNum++; 20 combineArr.remove((Object)courseArr[i]); //移除后新的课程才可以被塞进来 21 } 22 }else if(needNum > 1){ 23 for (int i = index; i <= courseArr.length - needNum; i++) { 24 combineArr.add(courseArr[i]); 25 generateCombine(i + 1,needNum - 1, courseArr); 26 combineArr.remove((Object)courseArr[i]); 27 } 28 }else{ 29 return; 30 } 31 } 32 33 /** 34 * 开始保存组合 35 * @param combineCourseArr 36 * @param showCombineNum 37 */ 38 public void startSavaCombine(List<String> combineCourseArr, Integer showCombineNum) { 39 CombineDTO CombineDTO = newCombineDTO(); 40 CombineDTO.setShowNum(showCombineNum); 41 CombineDAO.createNewDto(CombineDTO); 42 String combineId = CombineDTO.getId(); 43 for(String cid:combineCourseArr){ 44 CombineCourseDTO CombineCourseDTO = new CombineCourseDTO(); 45 CombineCourseDTO.setCombineId(combineId); 46 CombineCourseDTO.setCourseId(cid); 47 CombineCourseDAO.creatNewCombineCourseDto(CombineCourseDTO); 48 } 49 }
如果有问题的话,可以留言,大家一起讨论~