目录
17.电话号码的字母组合
77.组合
46.全排列
52.N皇后Ⅱ
题意:
给定一个仅包含数字
2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
【输入样例】digits="23"
【输出样例】["ad","ae","af","bd","be","bf","cd","ce","cf"]
class Solution {
public List letterCombinations(String digits) {
List ans = new ArrayList();
if(digits.length() == 0){
return ans;
}
Map phoneMap = new HashMap(){{
put('2',"abc");
put('3',"def");
put('4',"ghi");
put('5',"jkl");
put('6',"mno");
put('7',"pqrs");
put('8',"tuv");
put('9',"wxyz");
}};
findString(ans,phoneMap,digits,0,new StringBuffer());
return ans;
}
public void findString(List ans, Map phoneMap,
String digits,int index,StringBuffer curAns){
if(index == digits.length()){
//证明全部遍历完比
ans.add(curAns.toString());
//把找到的答案转成String类型存到列表中
}else{
char digit = digits.charAt(index);//取出字符,到map中获取对应的值
String letters = phoneMap.get(digit);
for(int i=0;i
时间: 击败了46.35%
内存: 击败了26.39%
题意:
给定两个整数
n
和k
,返回范围[1, n]
中所有可能的k
个数的组合。你可以按 任何顺序 返回答案。
【输入样例】n=4,k=2
【输出样例】
[ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
class Solution {
List> ans = new ArrayList>();
public List> combine(int n, int k) {
findAns(1,n,k,new ArrayList<>());//从1开始找
return ans;
}
public void findAns(int index,int n,int k,List list){
if(k == 0){
//找到正确的答案,添加
ans.add(new ArrayList<>(list));
return;
}
for(int i=index;i<=n-k+1;++i){
list.add(i);
findAns(i+1,n,k-1,list);
list.remove(list.size()-1);
}
}
}
时间: 击败了56.50%
内存: 击败了5.94%
题意:
给定一个不含重复数字的数组
nums
,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
【输入样例】nums=[1,2,3]
【输出样例】[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
解题思路:递归回溯+哈希表
1. 构建一个哈希map,用来存放当前那一些数字可以用,那一些数字不可以用;
2. 递归函数的作用是找到第index位上可以是那个数字,数字是位于数字中,所以对数组进行枚举来获得第i位的值,之后用哈希map判断此位数字是否已经被用过。被用过继续找,没被用过则添加到list中,并修改标志位,继续寻找第index+1位;
3.回溯的时候除了要移开最后一位数字,还需要重新修改标志位。
class Solution {
List> ans = new ArrayList>();
public List> permute(int[] nums) {
//构造map,初始化所有数字现在都可以用
int len = nums.length;
Map useMap= new HashMap();
for(int i=0;i());//从第一位开始找
return ans;
}
public void searchOrder(int index,int[] nums,int len,Map useMap,List list){
if(index == len+1){
//找到正确的答案,添加
ans.add(new ArrayList<>(list));
return;
}
for(int i=0; i < len;++i){
//从第一位到最后一位,可以选择那一些
int num = nums[i];
if(useMap.get(num) == true){
list.add(num);
//修改标志位
useMap.put(num,false);
searchOrder(index+1,nums,len,useMap,list);
list.remove(list.size()-1);
useMap.put(num,true);
}
}
}
}
时间: 击败了78.23%
内存: 击败了48.52%
题意:
n 皇后问题 研究的是如何将
n
个皇后放置在n × n
的棋盘上,并且使皇后彼此之间不能相互攻击。给你一个整数
n
,返回 n 皇后问题 不同的解决方案的数量。
【输入样例】n=4
【输出样例】2
解题思路:递归回溯+布尔数组
为什么是!row[i] && !dia[index-i+n] && !assDia[index+i]?
row[i]:好理解,同一列已经有值
but,dia和assDia中的取值为什么是这样书写的呢?
class Solution {
int ans = 0;
public int totalNQueens(int n) {
//n皇后问题
//任意两个皇后不能在同一横轴,纵轴,对角线上
//三个数组,表示当前纵轴,正对角线,副对角线上是否有值,默认false
boolean[] row = new boolean[n+1];
boolean[] dia = new boolean[2*n+1];
boolean[] assDia = new boolean[2*n+1];
search(1,n,row,dia,assDia);//从第一行开始判断
return ans;
}
private void search(int index,int n, boolean[] row, boolean[] dia, boolean[] assDia){
if(index == n+1){
++ans;
return;
}
//index表示当前查找第几行,所以遍历遍历列就可以了
for(int i=1;i<=n;i++){
if(!row[i] && !dia[index-i+n] && !assDia[index+i]){
row[i] = dia[index-i+n] = assDia[index+i] = true;//已经有值
search(index+1,n,row,dia,assDia);
//回溯
row[i] = dia[index-i+n] = assDia[index+i] = false;
}
}
}
}
时间: 击败了100.00%
内存: 击败了74.08%