例题一:组合总数
给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/combination-sum
输入:candidates = [2,3,6,7], target = 7 输出:[[2,2,3],[7]] 解释: 2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。 7 也是一个候选, 7 = 7 。 仅有这两种组合。
分析:
问题:所有组合和为target的组合排列
所有组合排列,不能重复,同一个数字可重复选取
思路一:dfs
- 对整数数组排升序
- 从低位选取
- nums[i] <target :选用 dfs(target-nums[i])
- 否则不选用,并剪枝(排升序)
- 组合不可重复,数字可重复选取
- 从选取的低位开始遍历,防止组合重复,满足重复选取
class Solution {
List<List<Integer>> ret = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
int len = candidates.length;
int index = 0;
List<Integer> list = new ArrayList<>();
dfs(candidates,0,target,list,index);
return ret;
}
private void dfs(int[] candidates,int start,int target,List<Integer> list,int index){
if(target==0){
ret.add(new ArrayList<Integer>(list));
return;
}
if(target<0)
return;
int len = candidates.length;
for(int i = start;i<len;i++){
if(candidates[i]<=target){
list.add(candidates[i]);
dfs(candidates,i,target-candidates[i],list,index+1);
list.remove(index);
}else{
break;
}
}
}
}
例题二:活字印刷
你有一套活字字模 tiles,其中每个字模上都刻有一个字母 tiles[i]。返回你可以印出的非空字母序列的数目。
注意:本题中,每个活字字模只能使用一次。
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/letter-tile-possibilities
输入:"AAB"
输出:8
解释:可能的序列为 "A", "B", "AA", "AB", "BA", "AAB", "ABA", "BAA"。
分析:
所有非空字母序列数目; dfs
字模使用一次;使用过一次即标记;
可能存在重复字模;去重 set
思路一:dfs
class Solution {
HashSet<String> ret = new HashSet<>();
public int numTilePossibilities(String tiles) {
StringBuffer str = new StringBuffer();
boolean[] flag = new boolean[tiles.length()];
dfs(tiles,str,0,flag);
return ret.size();
}
private void dfs(String tiles,StringBuffer str,int len,boolean[] flag){
if(len!=0)
ret.add(str.toString());
for(int i =0;i<tiles.length();i++){
if(flag[i])
continue;
flag[i] = true;
str.append(tiles.charAt(i));
dfs(tiles,str,len+1,flag);
flag[i] = false;
str.deleteCharAt(str.length()-1);
}
}
}
思路二:计数,dfs
class Solution {
public int numTilePossibilities(String tiles) {
int[] map = new int[26];
for(int idx = 0; idx < tiles.length(); ++idx){
++map[tiles.charAt(idx) - 'A'];
}
return traverse(map);
}
private int traverse(int[] map){
int sum = 0;
for(int idx = 0; idx < map.length; ++idx){
if(map[idx] > 0){
++sum;
--map[idx];
sum += traverse(map);
++map[idx];
}
}
return sum;
}
}
思路三:剪枝思路不同
public class Solution {
int ans;
char[] s;
public int numTilePossibilities(String tiles) {
s = tiles.toCharArray();
Arrays.sort(s);
boolean[] used = new boolean[s.length];
DFS(used);
return ans;
}
public void DFS(boolean[] used) {
char last = '*';
for (int i = 0; i < s.length; i++) {
if (!used[i] && s[i] != last) {
ans++;
used[i] = true;
DFS(used);
used[i] = false;
last = s[i];
}
}
}
}
|