目录
17.电话号码的字母组合
77.组合
46.全排列
52.N皇后Ⅱ
17.电话号码的字母组合
题意:
给定一个仅包含数字
2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
【输入样例】digits="23"
【输出样例】["ad","ae","af","bd","be","bf","cd","ce","cf"]
class Solution {public List<String> letterCombinations(String digits) {List<String> ans = new ArrayList<String>();if(digits.length() == 0){return ans;}Map<Character,String> phoneMap = new HashMap<Character,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");}};findString(ans,phoneMap,digits,0,new StringBuffer());return ans;}public void findString(List<String> ans, Map<Character,String> 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<letters.length();++i){curAns.append(letters.charAt(i));//递归调用,主要是用于找到下一位可能的字符findString(ans,phoneMap,digits,index+1,curAns);//递归回来进行回溯,把当前的字符删掉,寻找更多可能curAns.deleteCharAt(index);}}}
}
时间: 击败了46.35%
内存: 击败了26.39%
77.组合
题意:
给定两个整数
n
和k
,返回范围[1, n]
中所有可能的k
个数的组合。你可以按 任何顺序 返回答案。
【输入样例】n=4,k=2
【输出样例】
[[2,4],[3,4],[2,3],[1,2],[1,3],[1,4], ]
class Solution {List<List<Integer>> ans = new ArrayList<List<Integer>>();public List<List<Integer>> combine(int n, int k) {findAns(1,n,k,new ArrayList<>());//从1开始找return ans;}public void findAns(int index,int n,int k,List<Integer> 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%
46.全排列
题意:
给定一个不含重复数字的数组
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<List<Integer>> ans = new ArrayList<List<Integer>>();public List<List<Integer>> permute(int[] nums) {//构造map,初始化所有数字现在都可以用int len = nums.length;Map<Integer,Boolean> useMap= new HashMap<Integer,Boolean>();for(int i=0;i<len;++i){useMap.put(nums[i],true);}searchOrder(1,nums,len,useMap,new ArrayList<>());//从第一位开始找return ans;}public void searchOrder(int index,int[] nums,int len,Map<Integer,Boolean> useMap,List<Integer> 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%
52.N皇后Ⅱ
题意:
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皇后问题//任意两个皇后不能在同一横轴,纵轴,对角线上//三个数组,表示当前纵轴,正对角线,副对角线上是否有值,默认falseboolean[] 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%