1.HOT00-第17题:电话号码的字母组合
package Hot100;
import java.util.ArrayList;
import java.util.List;
/**
* leetcode17:电话号码的字母组合
* 题目:给定一个仅包含数字2-9的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
* 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
*
* 输入:digits = "23"
* 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
*
* 输入:digits = ""
* 输出:[]
*
* 输入:digits = "2"
* 输出:["a","b","c"]
* @author dengjie
* @create 2021-04-21 23:41
*/
public class Solution17 {
public static void main(String[] args) {
String letters = "23";
List<String> strings = letterCombinations(letters);
System.out.println(strings);
}
/**
* 方法一:回溯,和排列的做法相同
* @param digits
* @return
*/
static List<String> list = new ArrayList<>();//保存结果
//数字和字母的映射,用map存储也可以
static String[] letter_map = {"","*","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
public static List<String> letterCombinations(String digits){
if (digits == null || digits.length() == 0){
//边界条件,直接返回
return list;
}
StringBuilder builder = new StringBuilder();//用来拼接字符
callback(builder,digits,0);//开始调用递归
return list;
}
public static void callback(StringBuilder builder, String digits, int index){
if (index == digits.length()){
//当digits遍历到最后一位时将拼接好的字符放入list中
list.add(builder.toString());
}else {
//取digits的字符。比如“23”,index=0取2,index=1取3
char c = digits.charAt(index);
//对应的下标
int in = c - '0';
//取下标对应的字母,比如,2-->“abc”
String letters = letter_map[in];
for (int i = 0; i < letters.length(); i++) {
//先拼接1个字符
builder.append(letters.charAt(i));
//递归往后拼接
callback(builder,digits,index+1);
//回溯,删除最后一个字符
builder.deleteCharAt(builder.length() - 1);
}
}
}
}
2.HOT100-第46题:全排列
package Hot100;
import java.util.ArrayList;
import java.util.List;
/**
* leetcode HOT100第46题:全排列
* 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
*
* @author dengjie
* @create 2021-05-23 12:40
*/
public class Solution46 {
public static void main(String[] args) {
int[] nums = new int[]{1,2,3};
Solution46 solution46 = new Solution46();
List<List<Integer>> permute = solution46.permute(nums);
System.out.println(permute);
}
/**
*
*/
int count = 0; //计数
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();//结果集
if (nums == null || nums.length == 0){
return res;
}
List<Integer> sublist = new ArrayList<>();//子列表,动态变化
permuteCore(nums,sublist,res);
System.out.println(count);
return res;
}
/**
*可以使用visited数组标记每个位置是否被访问过,降低时间复杂度
* @param nums
* @param sublist
* @param res
*/
public void permuteCore(int[] nums,List<Integer> sublist,List<List<Integer>> res){
//递归退出条件
if (sublist.size() == nums.length){
// 满足的条件,加入结果集
count++;
// sublist会频繁变化,必须用新的对象记录选择的路径
res.add(new ArrayList<>(sublist));
return;
}
// 遍历当前可选结果
for (int i = 0; i < nums.length; i++) {
//递归
if (!sublist.contains(nums[i])){
// 选择当前阶段其中一个解
sublist.add(nums[i]);
// 选完之后再进入下个阶段遍历
permuteCore(nums,sublist,res);
//回溯,换一个解继续遍历
sublist.remove(sublist.size() - 1);
}
}
}
}
使用boolean数组标记被访问过的位置,降低时间复杂度
class Solution {
int count = 0; //计数
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
if (nums == null || nums.length == 0){
return res;
}
boolean[] flag = new boolean[nums.length];
List<Integer> sublist = new ArrayList<>();
permuteCore(nums, flag,sublist,res);
System.out.println(count);
return res;
}
public void permuteCore(int[] nums, boolean[] flag,List<Integer> sublist,List<List<Integer>> res){
//递归退出条件
if (sublist.size() == nums.length){
count++;
res.add(new ArrayList<>(sublist));
return;
}
for (int i = 0; i < nums.length; i++) {
//递归
if (!flag[i]){
flag[i] = true;
sublist.add(nums[i]);
permuteCore(nums,flag,sublist,res);
//回溯
sublist.remove(sublist.size() - 1);
flag[i] = false;
}
}
}
}