(1)电话号码的字母组合
给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
public class CombinationOfTelephoneNumbers {
public List<String> letterCombinations(String digits) {
List<String> list = new ArrayList<String>();
if (digits.length() == 0) {
return list;
}
backtracking("", digits, 0, list);
return list;
}
public static void backtracking(String s, String digits, int flag, List<String> list) {
String[] strings = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };
if (flag >= digits.length()) {
list.add(s);
return; //返回,向上回溯
}
String chars = strings[digits.charAt(flag) - '0'];
for (int i = 0; i < chars.length(); i++) {
backtracking(s+chars.charAt(i),digits,flag+1,list);
}
}
public static void main(String[] args) {
String s = "23";
List<String> la = new CombinationOfTelephoneNumbers().letterCombinations(s);
System.out.println(la);
}
}
百度百科:
回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
(2)生成括号
给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。
例如,给出 n = 3,生成结果为:
[
"((()))",
"(()())",
"(())()",
"()(())",
"()()()"
]
public class Brackets {
public List<String> generateParenthesis(int n) {
List<String> list = new ArrayList<String>();
bracketsCombination("", list, n, n);
return list;
}
public void bracketsCombination(String sublist, List<String> list, int left, int right) {
if (left == 0 && right == 0) {
list.add(sublist);
return;
}
if (left > 0) {
bracketsCombination(sublist + '(', list, left - 1, right);
}
if (right > left) {
bracketsCombination(sublist + ')', list, left, right - 1);
}
}
public static void main(String[] args) {
int n = 2;
List<String> la = new Brackets().generateParenthesis(n);
System.out.println(la);
}
}
(3)全排列
给定一个没有重复数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
public class FullArrangement {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> lists = new ArrayList<List<Integer>>();
List<Integer> list = new ArrayList<Integer>();
backTracking(lists, list, nums);
return lists;
}
public static void backTracking(List<List<Integer>> lists, List<Integer> list, int[] nums) {
if (list.size() == nums.length) {
lists.add(new ArrayList<>(list));
return;
} else {
for (int i = 0; i < nums.length; i++) {
if (list.contains(nums[i]))
continue;
list.add(nums[i]);
backTracking(lists, list, nums);
list.remove(list.size() - 1);
}
}
}
public static void main(String[] args) {
int[] nums = { 1, 2 };
List<List<Integer>> lists = new FullArrangement().permute(nums);
System.out.println(lists);
}
}
(4)子集
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
public class AllSubset {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
List<Integer> temp = new ArrayList<Integer>();
dfs(result, temp, nums, 0);
return result;
}
public static void dfs(List<List<Integer>> result, List<Integer> temp, int nums[], int j){
result.add(new ArrayList<Integer>(temp));//添加到结果集中
for (int i = j; i < nums.length; i++) {
temp.add(nums[i]);//添加第i个数进入temp中
dfs(result,temp,nums,i+1);//将temp添加到结果集中并添加下一个数
temp.remove(temp.size()-1);//把最新添加的一个数删掉继续循环
}//循环完返回上一层递归
}
public static void main(String[] args) {
int[] nums = {1,2,3};
List<List<Integer>> ls = new AllSubset().subsets(nums);
System.out.println(ls);
}
}
(5)单词搜索
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例:
board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
给定 word = "ABCCED", 返回 true.
给定 word = "SEE", 返回 true.
给定 word = "ABCB", 返回 false.
待续。。。
说明:回溯法,感觉没什么经验的挺难想到的,我也是看别人的代码,自己debug看看是怎么个回溯过程,学到了。return比较叼,到底回到之前哪个点的状态,还是自己debug跟踪一下哦!刷题,感觉和考数学似的,分门别类,多写多学多debug,电脑思维和我们还是不一样。做数学题的时候,一般都是先自己看看会不会,不会看看答案,因为有些有技巧的,然后理解了,自己在操作一遍,真真切切的搞懂了,慢慢的会产生思维定式,这样遇到类似的题才会反应速度快了,然后才叫:刷题!
@@刷起来!!@@