组合
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
List<List<Integer>> res = new ArrayList<>();
List<Integer> temp = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
dfs(n,k,1);
return res;
}
private void dfs(int n, int k, int index) {
if (temp.size() == k){
res.add(new ArrayList<>(temp));
return;
}
for (int i = index; i <= n ; i++) {
temp.add(i);
dfs(n,k,i+1);
temp.remove(temp.size()-1);
}
}
组合总和三
找出所有相加之和为 n 的 k 个数的组合,只使用数字1到9,每个数字只能使用一次
List<List<Integer>> res1 = new ArrayList<>();
LinkedList<Integer> temp1 = new LinkedList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
dfs1(k,n,1,0);
return res1;
}
private void dfs1(int k, int n, int index,int sum) {
if (sum > n){
return;
}
if (temp1.size() == k){
if (sum == n){
res1.add(new ArrayList<>(temp1));
return;
}
}
for(int i = index;i<=9;i++){
temp1.add(i);
sum+=i;
dfs1(k,n,i+1,sum);
sum-=i;
temp1.removeLast();
}
}
电话号码的字母组合
class Solution {
String letterMap[] = {" ", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
ArrayList<String> res;
public List<String> letterCombinations(String digits) {
res = new ArrayList<String>();
if (digits.equals(""))
return res;
dfs(digits, 0, "");
return res;
}
public void dfs(String digits, int index, String s) {
if (index == digits.length()) {
res.add(s);
return;
}
Character c=digits.charAt(index);
String letters=letterMap[c-'0'];
for(int i=0;i<letters.length();i++){
dfs(digits,index+1,s+letters.charAt(i));
}
return;
}
}
组合总和
给定一个数组和target,无限次使用,求能组成的序列
List<List<Integer>> res2 = new ArrayList<>();
LinkedList<Integer> temp2 = new LinkedList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
dfs3(candidates,target,0,0);
return res2;
}
private void dfs3(int[] candidates, int target, int index,int sum) {
if (sum > target){
return;
}
if (sum == target){
res2.add(new ArrayList<>(temp2));
return;
}
for(int i = index;i<candidates.length;i++){
if (sum+candidates[i] > target){
break;
}
temp2.add(candidates[i]);
dfs3(candidates,target,i,sum+candidates[i]);
temp2.removeLast();
}
}
组合总和二
给定一个数组和target,每个数字只能使用一次,求能组成的序列
class Solution {
List<List<Integer>> res2 = new ArrayList<>();
LinkedList<Integer> temp2 = new LinkedList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
dfs3(candidates, target, 0, 0);
return res2;
}
private void dfs3(int[] candidates, int target, int index, int sum) {
if (sum > target) {
return;
}
if (sum == target) {
res2.add(new ArrayList<>(temp2));
return;
}
for (int i = index; i < candidates.length; i++) {
if (i > index && candidates[i] == candidates[i - 1]) {
continue;
}
if (sum + candidates[i] > target) {
break;
}
temp2.add(candidates[i]);
dfs3(candidates, target, i + 1, sum + candidates[i]);
temp2.removeLast();
}
}
}
分割回文串
class Solution {
ArrayList<List<String>> res = new ArrayList<>();
ArrayDeque<String> path = new ArrayDeque<>();
public List<List<String>> partition(String s) {
dfs(s, 0);
return res;
}
public void dfs(String s, int index) {
if (index >= s.length()) {
res.add(new ArrayList<>(path));
return;
}
for (int i = index; i < s.length(); i++) {
if (isPal(s, index, i)) {
String str = s.substring(index, i + 1);
path.add(str);
} else continue;
dfs(s, i + 1);
path.removeLast();
}
}
public boolean isPal(String s, int index, int end) {
for (int i = index, j = end; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j))
return false;
}
return true;
}
}
复原IP地址
List<String> ans = new ArrayList();
public List<String> restoreIpAddresses(String s) {
if (s.length() > 12){
return ans;
}
backTrack(s,0,0);
return ans;
}
private void backTrack(String s, int start, int pointNum) {
if (pointNum == 3) {
if (isvalid(s,start,s.length()-1)){
ans.add(s);
}
return;
}
for (int i = start; i < s.length(); i++) {
if (isvalid(s,start,i)){
s = s.substring(0,i+1)+"."+s.substring(i+1);
pointNum++;
backTrack(s,i+2,pointNum);//有逗号,所以+2
pointNum--;
s = s.substring(0,i+1)+s.substring(i+2);
}else {
break;
}
}
}
private boolean isvalid(String s, int start, int end) {
if (start>end){
return false;
}
if (s.charAt(start)=='0' && start !=end){
return false;
}
int num = 0;
for (int i = start; i <= end; i++) {
if (s.charAt(i)>'9' || s.charAt(i) < '0'){
return false;
}
num = num * 10 +(s.charAt(i) - '0');
if (num > 255){
return false;
}
}
return true;
}
子集
List<List<Integer>> subsets = new ArrayList<>();
List<Integer> subsetsPath = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
subsetsDfs(nums,0);
return subsets;
}
private void subsetsDfs(int[] nums, int index) {
subsets.add(new ArrayList<>(subsetsPath));
if (index >= nums.length){
return;
}
for (int i = index; i < nums.length; i++) {
subsetsPath.add(nums[i]);
subsetsDfs(nums,i+1);
subsetsPath.remove(subsetsPath.size()-1);
}
}
全排列
List<List<Integer>> res = new ArrayList();
ArrayDeque<Integer> path = new ArrayDeque();
boolean[] used;
public List<List<Integer>> permute(int[] nums) {
used = new boolean[nums.length];
dfs(nums);
return res;
}
private void dfs(int[] nums){
if(path.size() == nums.length){
res.add(new ArrayList(path));
return;
}
for(int i = 0;i<nums.length;i++){
if(used[i]){
continue;
}
used[i] = true;
path.add(nums[i]);
dfs(nums);
path.removeLast();
used[i] = false;
}
}
全排列二
给定一个可包含重复数字的序列,要返回所有不重复的全排列。
class Solution {
//存放结果
List<List<Integer>> result = new ArrayList<>();
//暂存结果
List<Integer> path = new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
boolean[] used = new boolean[nums.length];
Arrays.fill(used, false);
Arrays.sort(nums);
backTrack(nums, used);
return result;
}
private void backTrack(int[] nums, boolean[] used) {
if (path.size() == nums.length) {
result.add(new ArrayList<>(path));
return;
}
for (int i = 0; i < nums.length; i++) {
// used[i - 1] == true,说明同⼀树⽀nums[i - 1]使⽤过
// used[i - 1] == false,说明同⼀树层nums[i - 1]使⽤过
// 如果同⼀树层nums[i - 1]使⽤过则直接跳过
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
continue;
}
//如果同⼀树⽀nums[i]没使⽤过开始处理
if (used[i] == false) {
used[i] = true;//标记同⼀树⽀nums[i]使⽤过,防止同一树枝重复使用
path.add(nums[i]);
backTrack(nums, used);
path.remove(path.size() - 1);//回溯,说明同⼀树层nums[i]使⽤过,防止下一树层重复
used[i] = false;//回溯
}
}
}
}