第六天 递归回溯问题
17. 电话号码的字母组合
class Solution {
//一个映射表,第二个位置是"abc“,第三个位置是"def"。。。
private String letterMap[] = {
" ", //0
"", //1
"abc", //2
"def", //3
"ghi", //4
"jkl", //5
"mno", //6
"pqrs", //7
"tuv", //8
"wxyz" //9
};
private ArrayList<String> res= new ArrayList<String>();
public List<String> letterCombinations(String digits) {
//注意边界条件
if(digits.equals(""))
return res;
findCombination(digits, 0, "");
return res;
}
private void findCombination(String digits, int index, String s){
//如果是最后一个字符,直接返回
if(index == digits.length()){
res.add(s);
return;
}
//map_string的下表是从0开始一直到9, c-'0'就可以取到相对的数组下标位置
//比如c=2时候,2-'0',获取下标为2,letter_map[2]就是"abc"
Character c = digits.charAt(index);
String letters = letterMap[c - '0'];
//遍历字符串,比如第一次得到的是2,页就是遍历"abc"
for(int i = 0 ; i < letters.length() ; i ++){
//调用下一层递归
findCombination(digits, index+1, s + letters.charAt(i));
}
}
}
131. 分割回文串
给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。返回 s 所有可能的分割方案。
示例:
输入: “aab”
输出:
[
[“aa”,“b”],
[“a”,“a”,“b”]
]
93. 复原IP地址
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
有效的 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 ‘.’ 分隔。
例如:“0.1.2.201” 和 “192.168.1.1” 是 有效的 IP 地址,但是 “0.011.255.245”、“192.168.1.312” 和 “192.168@1.1” 是 无效的 IP 地址。
示例 1:
输入:s = “25525511135”
输出:[“255.255.11.135”,“255.255.111.35”]
46. 全排列
class Solution {
List<List<Integer>> res = new LinkedList<>();
public List<List<Integer>> permute(int[] nums) {
//用于记录已经选过的数字
LinkedList<Integer> track = new LinkedList<>();
//回溯法
backtarck(nums,track);
return res;
}
private void backtarck(int[] nums,LinkedList<Integer> track){
//递归结束条件
if(track.size() == nums.length){
res.add(new LinkedList<Integer>(track));
}
for(int i = 0;i < nums.length;i++){
//排除已有的数字
if(track.contains(nums[i])){
continue;
}
//选出一个数字
track.add(nums[i]);
//进行下一级的选择
backtarck(nums,track);
//递归结束,添加完成后,将元素一个个删除
//这样才能继续向下找答案
track.removeLast();
}
}
}
47. 全排列 II
给定一个可包含重复数字的序列,返回所有不重复的全排列。
77. 组合
给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
backtrack(new LinkedList<>(),n,k,0);
return res;
}
public void backtrack(LinkedList<Integer> list,int n,int k,int count){
if(list.size() == k){
res.add(new LinkedList(list));
return;
}
for(int i = count+1;i <= n;i++){
list.add(i);
backtrack(list,n,k,i);
list.removeLast();
}
}
}
39. 组合总和
40. 组合总和 II
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明:
所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。
216. 组合总和 III
找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
说明:
所有数字都是正整数。
解集不能包含重复的组合。
78. 子集
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res=new ArrayList<>();
res.add(new ArrayList<>());
for(int i=0;i<nums.length;i++){
int n=res.size();
for(int j=0;j<n;j++){
List<Integer> list=new ArrayList<>(res.get(j));
if (i >0 && nums[i] == nums[i - 1]) {
continue;
}
list.add(nums[i]);
res.add(list);
}
}
return res;
}
}
90. 子集 II
401. 二进制手表
二进制手表顶部有 4 个 LED 代表 小时(0-11),底部的 6 个 LED 代表 分钟(0-59)。
每个 LED 代表一个 0 或 1,最低位在右侧。
例如,上面的二进制手表读取 “3:25”。
给定一个非负整数 n 代表当前 LED 亮着的数量,返回所有可能的时间。
示例:
输入: n = 1
返回: [“1:00”, “2:00”, “4:00”, “8:00”, “0:01”, “0:02”, “0:04”, “0:08”, “0:16”, “0:32”]
提示:
输出的顺序没有要求。
小时不会以零开头,比如 “01:00” 是不允许的,应为 “1:00”。
分钟必须由两位数组成,可能会以零开头,比如 “10:2” 是无效的,应为 “10:02”。
超过表示范围(小时 0-11,分钟 0-59)的数据将会被舍弃,也就是说不会出现 “13:00”, “0:61” 等时间。
79. 单词搜索
给定一个二维网格和一个单词,找出该单词是否存在于网格中。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
class Solution {
public boolean exist(char[][] board, String word) {
char[] words=word.toCharArray();
for(int i=0;i<board.length;i++){
for(int j=0;j<board[0].length;j++){
if(dfs(board,words,i,j,0))
return true;
}
}
return false;
}
public boolean dfs(char[][] board,char[] words,int i,int j,int k){
if(i>=board.length||i<0||j>=board[0].length||j<0||board[i][j]!=words[k]) return false;
if(k==words.length-1) return true;
char temp=board[i][j];
board[i][j]=' ';
boolean res=dfs(board,words,i+1,j,k+1)||dfs(board,words,i-1,j,k+1)||dfs(board,words,i,j+1,k+1)||dfs(board,words,i,j-1,k+1);
board[i][j]=temp;
return res;
}
}
200. 岛屿数量
给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。此外,你可以假设该网格的四条边均被水包围。
130. 被围绕的区域
给定一个二维的矩阵,包含 ‘X’ 和 ‘O’(字母 O)。找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。
示例:
X X X X
X O O X
X X O X
X O X X
运行你的函数后,矩阵变为:
X X X X
X X X X
X X X X
X O X X
417. 太平洋大西洋水流问题
给定一个 m x n 的非负整数矩阵来表示一片大陆上各个单元格的高度。“太平洋”处于大陆的左边界和上边界,而“大西洋”处于大陆的右边界和下边界。
规定水流只能按照上、下、左、右四个方向流动,且只能从高到低或者在同等高度上流动。请找出那些水流既可以流动到“太平洋”,又能流动到“大西洋”的陆地单元的坐标。
提示:
输出坐标的顺序不重要
m 和 n 都小于150
示例:
51. N 皇后