题目: Combinations
1-n个数字中找k个数字的所有不同组合。
思路:从1-k开始,每次从k开始,让最后面的元素加1,超过了,就让前面一个元素加1,后面一个元素变为前面一个元素的值加1.
循环知道所有元素都没有超过,则是一种不同的情况。
例如:n = 6,k = 4;
1234->1235->1236->1245->1246->1256->1345->1346->1356->1456
->2345->...->3456
package com.example.medium; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; public class Combinations { public List<List<Integer>> combine(int n, int k) { List<List<Integer>> list = new LinkedList<>(); int indexs[] = new int[k]; int j = 0; for(int i = 0;i < k;i++){ indexs[i] = i; } while(indexs[0] <= n - k){ List<Integer> item = new ArrayList<Integer>(k); for(int i = 0;i <k;i++){//添加当前的k个元素 item.add(i, indexs[i] + 1); } list.add(item); j = k - 1; indexs[j]++;//最后一个元素加一 while(indexs[j] >= n - k + j + 1){//超过了n则倒数第二个元素加一,然后判断是否超过n,如此循环 j--; if(j < 0)break; indexs[j]++; } for(;j >= 0 && j < k - 1;j++) indexs[j + 1] = indexs[j] + 1; } return list; } public static void main(String[] args) { // TODO Auto-generated method stub List<List<Integer>> list = new Combinations().combine(17, 5); Iterator<List<Integer>> iterator = list.iterator(); while(iterator.hasNext()){ List<Integer> item = iterator.next(); for(int i = 0;i < item.size();i++) System.out.print(item.get(i) + " "); System.out.println(); } } }
题目:Subsets
找到给定数组的所有子集;数组中每个元素都不同
思路:
和上面一样,不过这次没有固定的k值。
让k从0开始一直加到n(数组长度),然后按照上面的方法找到所有子集。
package com.example.medium; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; public class Subsets { public List<List<Integer>> subsets(int[] nums) { List<List<Integer>> list = new LinkedList<>(); int index[] = new int[nums.length];//存储元素下标 int i = 0,k = 0; while (i <= nums.length) { List<Integer> item = new ArrayList<>(i); for (int j = 0; j < i; j++) {//添加子集 item.add(j, nums[index[j]]); } list.add(item); k = i - 1;//k减一 if(k < 0){//元素个数为i的子集找完了 i++; continue; } index[k]++;//最后一个元素的下标加一 while(index[k] > nums.length - i + k){ k--;// if(k < 0)break; index[k]++; } if(k < 0){//元素个数为i的子集找完了 i++; if(i > nums.length)break; for (int j = 0; j < i; j++) {//当i增加时,重新初始化 index[j] = j; } }else{ for(;k < i - 1;k++) index[k + 1] = index[k] + 1; } } return list; } public static void main(String[] args) { // TODO Auto-generated method stub List<List<Integer>> list = new Subsets().subsets(new int[]{1,2,3,4,5,6}); Iterator<List<Integer>> iterator = list.iterator(); while(iterator.hasNext()){ List<Integer> item = iterator.next(); for(int i = 0;i < item.size();i++) System.out.print(item.get(i) + " "); System.out.println(); } } }
题目:SubsetsII
找到给定数组的所有子集;数组中有相同元素。
思路:
和上面的相同,但是在查找前先排序,然后每次跳过元素之相同的元素。
package com.example.medium; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.LinkedList; import java.util.List; /** * Given a collection of integers that might contain duplicates, nums, return all possible subsets. * * Note: The solution set must not contain duplicate subsets. * * For example, * If nums = [1,2,2], a solution is: * * [ * [2], * [1], * [1,2,2], * [2,2], * [1,2], * [] * ] * @author qfp * */ public class SubSets2 { public List<List<Integer>> subsetsWithDup(int[] nums) { List<List<Integer>> list = new LinkedList<List<Integer>>(); Arrays.sort(nums); int[] index = new int[nums.length];//记录当前情况的下标 int i = 0,k = 0;//i表示子集中元素的个数 while(i <= nums.length){ List<Integer> item = new ArrayList<Integer>(i); for (int j = 0; j < i; j++) {//将当前情况添加进去 item.add(j, nums[index[j]]); } list.add(item); k = i - 1;//更新当前子集个数为i时,新的可能的子集 if(k < 0){//当i = 0时,只有一个空集 i++; continue; } //先更新id最大的元素,去重 while(index[k] < nums.length - 1 && nums[index[k]] == nums[index[k] + 1])index[k]++; index[k]++; while(index[k] > nums.length - i + k){ k--;// if(k < 0)break;//k小于0时,表示个数为i的子集全部找到了 while(index[k] < nums.length - 1 && nums[index[k]] == nums[index[k] + 1])index[k]++; index[k]++; } if(k < 0){ i++; if(i > nums.length)break; for (int j = 0; j < i; j++) {//当i增加时,重新初始化 index[j] = j; } }else{ for(;k < i - 1;k++) index[k + 1] = index[k] + 1; } } return list; } public static void main(String[] args) { // TODO Auto-generated method stub List<List<Integer>> list = new SubSets2().subsetsWithDup(new int[]{1,2,2,1,1}); Iterator<List<Integer>> iterator = list.iterator(); while(iterator.hasNext()){ List<Integer> item = iterator.next(); for(int i = 0;i < item.size();i++) System.out.print(item.get(i) + " "); System.out.println(); } } }