Letter Combinations or a Phone Number
分析:
- 用graph search来做,BFS/DFS,adjacency matrix
- adajacency matrix时间复杂度之前是O(n2),因为2是重复次数。n是节点数也就是一次里有多少种可能性。在这道题里呢,包含2-9的字符串,所以最多重复8次,每次有最多4个字母的可能性,也就是O (4n),n is the length of the input.
DFS
- 当题目中出现所有符合题目的解用搜索算法进行解题
- 自顶向下的递归实现深搜
- 定义子问题,如果是tree就是对子树,如果字符串就是substring,剩余字符串的问题
- 在当前递归层结合子问题解决原问题
数组是键值为非负整数的散列表。
class Solution {
public List<String> letterCombinations(String digits) {
// 定义返回值
List<String> result = new ArrayList<String>();
// check if the input is empty
if(digits.length() == 0){
return result;
}
// if input is not empty
// 定义电话号码和字母的映射 - 多种方法
// HashMap - Java单双引号的区别
Map<Character,String> phoneBook = 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");
}};
// 第二种方法: String[]
// String[] phoneBook = new String[]{"", "", "abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
//input not empty: implement DFS algorithm
dfs(phoneBook, digits, 0, result, new StringBuilder());
return result;
}
private void dfs(Map<Character,String> phoneBook, String digits, int index, List<String> result, StringBuilder sb){
//check boundary condition
// when the DFS ends
if(index == digits.length()){
// 把Stringbuilder的值传回给result
result.add(sb.toString());
return;
}
// 首先根据phoneBook根据数字得到映射的字母字符串
String letters = phoneBook.get(digits.charAt(index));
// String letters = phoneBook(Character.getNumericValue(digits.charAt(index))) - 如果是String[] phoneBook
// 遍历每个字母
for (int i = 0; i < letters.length(); i++){
// 首先加到sb里
sb.append(letters.charAt(i));
// 继续向下implement DFS
dfs(phoneBook, digits, index + 1, result, sb);
// 每次dfs结束后清除sb最后一位
sb.deleteCharAt(index);
}
}
}
- 分析时间复杂度
对于每次输入,最坏的可能性是每个数字对应4个字母。一共有n次输入,n is the length of the input, time complexity takes O(4n) - Space Complexity
space为递归的stack space。因为有n个stack所以递归的时候有n层。O(n + 4n). - 做题总结:像这样DFS是每一次把参数加到结果里最后返回一个conbinations的情况,并不需要dfs有返回值,void就可以。
BFS
BFS是逐层递归,对于这道题,先遍历2的字母"abc"再3 - “def” = [(a,b,c)] x [(d,e,f)]
- Time Complexity: O(4n)
- Space Complexity: O(4n)
class Solution {
public List<String> letterCombinations(String digits) {
List<String> result = new ArrayList<String>();
if(digits.length() == 0){return result;}
String[] phoneBook = new String[]{"", "", "abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
// 先给result添加空字符串
result.add("");
// 对于数字字符串里的每个数字 - 把String转化为charArray
for (char digit: digits.toCharArray()){
// 构造一个新的临时数组变量, 储存第i+1层
List<String> tmp = new ArrayList<String>();
for (String s: result){ //初始状态为空,空字符串也可以被遍历到
//储存目前这一位数字所对应字母string
String str = phoneBook[Character.getNumericValue(digit)];
for(int i = 0; i < str.length(); i++){
tmp.add(s+str.charAt(i)); //这时候tmp=[a,b,c]
}
}
result = tmp;
}
return result;
}
}
从这道题里学到的事
- 有关char的运用
- String和Char之数组间的转换:String[].toCharArray()
- String得到第i位的具体char:String.charAt(i)
- String删除第i位char: String.deleteCharAt(i)
- Char -> int: Character.getNumericValue(char)
- Java单双引号有区别
- 单引号包括char值
- 双引号包含String值
- StringBuilder和StringBuffer是String的同伴类,可以随意增添修改字符串
- StringBuilder不是线程安全的
- StringBuffer是线程安全的
- if - else另种写法
if condition:
do A
else if:
do B
if condition:
do A
return
do B
- 在每个函数前面应该首先考虑边界条件
- 针对这道题,DFS比BFS快,储存phoneMap,HashMap比String[]快