LintCode 425:电话号码的字母组合
https://www.lintcode.com/problem/letter-combinations-of-a-phone-number
描述
给一个不包含0和1的数字字符串,每个数字代表一个字母,请返回其所有可能的字母组合。
下图的手机按键图,就表示了每个数字可以代表的字母。
| 1 | 2 ABC |
3 DEF |
|---|---|---|
| 4 GHI |
5 JKL |
6 MNO |
| 7 PQRS |
8 TUV |
9 WXYZ |
样例
输入: "23"输出: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]解释:'2' 可以是 'a', 'b' 或 'c''3' 可以是 'd', 'e' 或 'f'输入: "5"输出: ["j", "k", "l"]
解题思路
AC代码
public class Solution {// 每个数字代表的字母String[] ss = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};// 存储字母组合List<String> list = new LinkedList<>();public List<String> letterCombinations(String digits) {// 因为测试是用的一个对象,所以list需要清空一下list.clear();if (digits.equals(""))return list;// 深搜得到字母组合assemble(0,digits,"");return list;}private void assemble(int i, String digits, String s) {// 已经找到一个组合,加入list,返回if (i == digits.length()){list.add(s);return;}char ch = digits.charAt(i);String str = ss[((int) ch) - 48];for (int j = 0; j < str.length(); j++) {assemble(i + 1,digits,s + str.charAt(j));}}}
LintCode 10:字符串的不同排列
https://www.lintcode.com/problem/string-permutation-ii
描述
给出一个字符串,找到它的所有排列,注意同一个字符串不要打印两次。
样例
输入:"abb"输出:["abb", "bab", "bba"]输入:"aabb"输出:["aabb", "abab", "baba", "bbaa", "abba", "baab"]
解题思路
AC代码
public class Solution {List<String> list = new ArrayList<>();public List<String> stringPermutation2(String str) {list.clear();if (str == null) { return list; }// 转成字符数组更容易处理char[] ch = str.toCharArray();// 记录当前位置是否已经被选取至组合中boolean[] flag = new boolean[ch.length];// 构造组合StringBuilder sb = new StringBuilder();// 排序,去重考虑Arrays.sort(ch);// 深搜dfs(sb, 0, ch, flag);return list;}private void dfs(StringBuilder sb, int step, char[] ch, boolean[] flag) {// 找到一个组合if (step == ch.length) {list.add(sb.toString());return;}for (int i = 0; i < ch.length; i++) {if (flag[i]) { continue; }// 去重,当有两个相同字母时,在当前层只取一次if (i > 0 && ch[i] == ch[i - 1] && !flag[i - 1]) { continue; }// 标准深搜过程sb.append(ch[i]);flag[i] = true;dfs(sb, step + 1, ch, flag);flag[i] = false;sb.deleteCharAt(step);}}}
LintCode 135:数字组合
https://www.lintcode.com/problem/combination-sum/
描述
给定一个候选数字的集合 candidates 和一个目标值 target. 找到 candidates 中所有的和为 target 的组合.
在同一个组合中, candidates 中的某个数字不限次数地出现.
- 所有数值 (包括
target) 都是正整数. - 返回的每一个组合内的数字必须是非降序的.
- 返回的所有组合之间可以是任意顺序.
- 解集不能包含重复的组合.
样例
```java 输入: candidates = [2, 3, 6, 7], target = 7 输出: [[7], [2, 2, 3]]
输入: candidates = [1], target = 3 输出: [[1, 1, 1]]
<a name="Tzght"></a>#### 解题思路给数字集合排序,深搜<a name="lEvxt"></a>#### AC代码```javapublic class Solution {List<List<Integer>> list = new ArrayList<>();int[] candidates;public List<List<Integer>> combinationSum(int[] candidates, int target) {// 排序Arrays.sort(candidates);List<Integer> li = new ArrayList<>();this.candidates = candidates;dfs( 0, 0, target, li);return list;}private void dfs(int index, int add, int target, List<Integer> li) {if (add == target) {list.add(new ArrayList<>(li));return;}for (int i = index; i < candidates.length; i++) {// 去重if (i > 0 && candidates[i] == candidates[i - 1]) {continue;}if (add + candidates[i] > target) {break;}li.add(candidates[i]);dfs(i, add + candidates[i], target, li);li.remove(li.size() - 1);}}}
LintCode 90:K数和II
https://www.lintcode.com/problem/k-sum-ii
描述
给定n个不同的正整数,整数k(1<= k <= n)以及一个目标数字。
在这n个数里面找出K个数,使得这K个数的和等于目标数字,你需要找出所有满足要求的方案。
样例
输入: [1,2,3,4], k = 2, target = 5输出: [[1,4],[2,3]]输入: [1,3,4,6], k = 3, target = 8输出: [[1,3,4]]
解题思路
AC代码
public class Solution {List<List<Integer>> list = new ArrayList<>();int[] a;public List<List<Integer>> kSumII(int[] A, int k, int target) {Arrays.sort(A);a = A;List<Integer> li = new ArrayList<>();dfs(0, 0, 0, k, target, li);return list;}private void dfs(int index, int level, int add, int k, int target, List<Integer> li) {if (add == target) {if (level == k) {list.add(new ArrayList<>(li));}return;}if (level >= k || index == a.length) {return;}for (int i = index; i < a.length; i++) {if (add + a[i] > target) {break;}li.add(a[i]);dfs(i + 1, level + 1, add + a[i], k, target, li);li.remove(li.size() - 1);}}}
LintCode 132:单词搜索II
https://www.lintcode.com/problem/word-search-ii
描述
给出一个由小写字母组成的矩阵和一个字典。找出所有同时在字典和矩阵中出现的单词。一个单词可以从矩阵中的任意位置开始,可以向左/右/上/下四个相邻方向移动。一个字母在一个单词中只能被使用一次。且字典中不存在重复单词
样例
输入:["doaf","agai","dcan"],["dog","dad","dgdg","can","again"]输出:["again","can","dad","dog"]解释:d o a fa g a id c a n矩阵中查找,返回 ["again","can","dad","dog"]。输入:["a"],["b"]输出:[]解释:a矩阵中查找,返回 []。
解题思路
从矩阵的每个点进行深搜。
优化:深搜到某一层时,如果这个前缀没在字典里出现过,其实就不用继续搜索。
- 用哈希表存储前缀
-
AC代码
public class Solution {List<String> list;// 哈希表存储前缀Map<String, Boolean> prefixes;int count = 0;int[] a = {0, 0, 1, -1};int[] b = {1, -1, 0, 0};int n,m;char[][] board;public List<String> wordSearchII(char[][] board, List<String> words) {if (board == null) return null;if (board.length <1) return null;if (board[0].length == 0) return null;this.board = board;list = new ArrayList<>();prefixes = new HashMap<>();count = 0;// 存储前缀,value值为true代表这是一个单词for (String str : words) {for (int i = 1; i < str.length(); i++) {String prefix = str.substring(0, i);if (!prefixes.containsKey(prefix)) {prefixes.put(prefix, false);}}prefixes.put(str, true);}n = board.length;m = board[0].length;boolean[][] flag = new boolean[n][m];// 从每个点开始dfsfor (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (!prefixes.containsKey(board[i][j] + "")) {continue;}flag[i][j] = true;dfs(flag, i,j,board[i][j]+"");flag[i][j] = false;}}return list;}public void dfs(boolean[][] flag, int x, int y, String s) {if (prefixes.get(s)) {// 去重if (!list.contains(s)) {list.add(s);}}for (int i = 0; i < 4; i++) {int x1 = x + a[i];int y1 = y + b[i];if (x1 < 0 || y1 < 0 || x1 >= n || y1 >= m || flag[x1][y1]) {continue;}if (!prefixes.containsKey(s + board[x1][y1])) {continue;}flag[x1][y1] = true;dfs(flag, x1, y1, s + board[x1][y1]);flag[x1][y1] = false;}}}
