0017电话号码与数字
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。
package com.Manigoat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Test0017电话号码的数字组合 {
static Map<String, String> phone = new HashMap<String, String>() {{
put("2", "abc");
put("3", "def");
put("4", "ghi");
put("5", "jkl");
put("6", "mno");
put("7", "pqrs");
put("8", "tuv");
put("9", "wxyz");
}};
static List<String>output= new ArrayList<>();
public static void backtrack(String combination, String next_digits) {
if (next_digits.length()==0){
output.add(combination);
return;
}else{
String digit=next_digits.substring(0,1);
String letters=phone.get(digit);
for (int i = 0; i < letters.length() ; i++) {
String letter = letters.substring(i,i+1);
backtrack(combination+letter,next_digits.substring(1));
}
}
}
public static List<String> letterCombinations(String digits) {
output.clear();
if (digits.length() != 0)
backtrack("", digits);
return output;
}
}
0022括号生成
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。
public List<String> generateParenthesis(int n) {
List<String> res = new ArrayList<>();
// 特判
if (n == 0) {
return res;
}
// 执行深度优先遍历,搜索可能的结果
dfs("", n, n, res);
return res;
}
private void dfs(String curStr, int left, int right, List<String> res) {
// 因为每一次尝试,都使用新的字符串变量,所以无需回溯
if (left == 0 && right == 0) {
res.add(curStr);
return;
}
// 剪枝(如图,左括号可以使用的个数严格大于右括号可以使用的个数,才剪枝,注意这个细节)
if (left > right||left<0||right<0) {
return;
}
dfs(curStr + "(", left - 1, right, res);
dfs(curStr + ")", left, right - 1, res);
}
0039组合总和(数字—无数次)
给定一个无重复元素的数组 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。每个数字在每个组合中能使用无数次
public static List<List<Integer>>combineSumList;
public static List<List<Integer>> combinationSum(int[] candidates, int target) {
combineSumList= new LinkedList<>();
backtrace(candidates,target,0, new LinkedList<>());
return combineSumList;
}
public static void backtrace(int candidates[], int target, int start, LinkedList<Integer>list){
if (target<0){
return;
}
if (target==0){
combineSumList.add(new LinkedList<>(list));
return;
}
for (int i = start; i < candidates.length ; i++) {
list.add(candidates[i]);
backtrace(candidates,target-candidates[i],i,list);
list.removeLast();
}
}
0040组合总和(数字—一次)
每个数字在每个组合中只能使用一次,题目输入可以有重复数字,但每个只能用一次
public static List<List<Integer>>combineSum2List;
public static List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
combineSum2List= new LinkedList<>();
backtrace(0,candidates,target,new LinkedList<>());
return combineSum2List;
}
public static void backtrace(int start, int[] candidates, int target, LinkedList<Integer>list){
if (target<0){
return;
}
if (target==0){
combineSum2List.add(new LinkedList<>(list));
}
for (int i = start; i < candidates.length ; i++) {
if (i>start&&candidates[i]==candidates[i-1]){
continue;
}
list.add(candidates[i]);
backtrace(i+1,candidates,target-candidates[i],list);
list.removeLast();
}
}
0077组合
给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
public static List<List<Integer>>combineList;
public static List<List<Integer>> combine(int n, int k) {
combineList= new LinkedList<>();
backtrace(n,k,1,new LinkedList<Integer>());
return combineList;
}
public static void backtrace(int n, int k , int start, LinkedList<Integer>list){
if (list.size()==k){
combineList.add(new LinkedList<>(list));
return;
}
for (int i = start; i <= n ; i++) {
list.add(i);
backtrace(n,k,i+1,list);
list.removeLast();
}
}
0046全排列(无重复数字)
static List<List<Integer>>permuteList;
public List<List<Integer>> permute(int[] nums) {
permuteList= new LinkedList<>();
int visited[]= new int[nums.length];
backtrace(nums,new LinkedList<>(),visited);
return permuteList;
}
public static void backtrace(int nums[], LinkedList<Integer>list, int visited[]){
if (list.size()==nums.length){
permuteList.add(new LinkedList<>(list));
return;
}
for (int i = 0; i < nums.length ; i++) {
if (visited[i]==1){
continue;
}
list.add(nums[i]);
visited[i]=1;
backtrace(nums,list,visited);
list.removeLast();
visited[i]=0;
}
}
0047全排列(有重复数字)
//0047
public List<List<Integer>> result = new LinkedList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
if(nums.length == 0){
return result;
}
//首先给数组排序
Arrays.sort(nums);
int[] visited= new int[nums.length];
findUnique(nums,visited,new LinkedList<Integer>());
return result;
}
public void findUnique(int[] nums, int[] visited,LinkedList<Integer> trace){
//结束条件
if(trace.size() == nums.length){
result.add(new LinkedList(trace));
return ;
}
//选择列表
for(int i = 0; i<nums.length; i++){
//其次,我们已经选择过的不需要再放进去了
if(visited[i]==1) continue;
if(i>0 && nums[i] == nums[i-1] && visited[i-1]==0) continue;
//做出选择
trace.add(nums[i]);
visited[i] = 1;
findUnique(nums,visited,trace);
//撤销选择
trace.removeLast();
visited[i] = 0;
}
}
0090子集 II
题目:给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
//0090子集
public static List<List<Integer>>subsetList;
public static List<List<Integer>> subsetsWithDup(int[] nums) {
if (nums==null){
return null;
}
Arrays.sort(nums);
int n=nums.length;
subsetList= new LinkedList<>();
for (int i = 0; i <=n ; i++) {
backtrace(n,i,0,new LinkedList<>(),nums);
}
return subsetList;
}
public static void backtrace(int n, int k, int start, LinkedList<Integer>list,int nums[]){
if (list.size()==k){
subsetList.add(new LinkedList<>(list));
return;
}
for (int i = start; i <= n-1 ; i++) {
if (i>start&&nums[i-1]==nums[i]){
continue;
}
list.add(nums[i]);
backtrace(n,k,i+1,list,nums);
list.removeLast();
}
}
0113 路径总和 II
题目:给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
static List<List<Integer>>pathSumList;
public static List<List<Integer>> pathSum(TreeNode root, int sum) {
pathSumList= new LinkedList<>();
backtrace(root, sum, new LinkedList<>());
return pathSumList;
}
public static void backtrace(TreeNode root,int sum, LinkedList<Integer>list){
if (root==null){
return;
}
list.add(root.val);
sum-=root.val;
if (sum==0&&root.left==null&&root.right==null){
pathSumList.add(new LinkedList<>(list));
}
backtrace(root.left, sum, list);
backtrace(root.right, sum,list);
list.removeLast();
}