概述
目录
- 前言
- [26.526. 优美的排列](https://leetcode-cn.com/problems/beautiful-arrangement/)
- [27.515. 在每个树行中找最大值](https://leetcode-cn.com/problems/find-largest-value-in-each-tree-row/)
- [31. 1110. 删点成林](https://leetcode-cn.com/problems/delete-nodes-and-return-forest/)
- [32.547. 省份数量](https://leetcode-cn.com/problems/number-of-provinces/)
- [33.947. 移除最多的同行或同列石头](https://leetcode-cn.com/problems/most-stones-removed-with-same-row-or-column/)
- [34. 337. 打家劫舍 III](https://leetcode-cn.com/problems/house-robber-iii/)
- [35. 面试题 16.19. 水域大小](https://leetcode-cn.com/problems/pond-sizes-lcci/)
- [36.117. 填充每个节点的下一个右侧节点指针 II](https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node-ii/)
- [37. 638. 大礼包](https://leetcode-cn.com/problems/shopping-offers/)
- [38.1254. 统计封闭岛屿的数目](https://leetcode-cn.com/problems/number-of-closed-islands/)
- [39. 面试题 04.06. 后继者](https://leetcode-cn.com/problems/successor-lcci/)
- [40. 1306. 跳跃游戏 III](https://leetcode-cn.com/problems/jump-game-iii/)
- [41.面试题34. 二叉树中和为某一值的路径](https://leetcode-cn.com/problems/er-cha-shu-zhong-he-wei-mou-yi-zhi-de-lu-jing-lcof/)
- [42.756. 金字塔转换矩阵](https://leetcode-cn.com/problems/pyramid-transition-matrix/)
- [43. 17. 电话号码的字母组合](https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/)
- [44.491. 递增子序列](https://leetcode-cn.com/problems/increasing-subsequences/)
前言
我又回来啦~
26.526. 优美的排列
题目描述:
假设有从 1 到 N 的 N 个整数,如果从这 N 个数字中成功构造出一个数组,使得数组的第 i 位 (1 <= i <= N) 满足如下两个条件中的一个,我们就称这个数组为一个优美的排列。条件:
第 i 位的数字能被 i 整除
i 能被第 i 位上的数字整除
现在给定一个整数 N,请问可以构造多少个优美的排列?
思路:
定义一个n+1长的free数组,记录有哪些数字已经被使用了;cot记录了当前已经包含了多少个数字.在每次dfs开始之前,一定是选中了一个新的数字,需要修改free数组对应位置,以及cot,在每次dfs结束之后,考虑同一位置的不同可能情况,所以需要把原来的修改撤回.
代码:
class Solution {
int ans = 0;
int n;
public int countArrangement(int n) {
// i 满足, 1 - i-1, i+1, N
this.n = n;
int[] free = new int[n+1];
dfs(free, 0);
return ans;
}
public void dfs(int[] free, int cot){
if(cot==n){
ans++;
return;
}
for(int i = 1;i<free.length;i++){
if(free[i]==0&&check(cot+1, i)){
free[i] = 1;
cot ++;
dfs(free, cot);
free[i] = 0;
cot --;
}
}
}
public boolean check(int idx, int i){
return idx%i==0 || i%idx==0;
}
}
官方答案:回来再看
27.515. 在每个树行中找最大值
题目描述:
您需要在二叉树的每一行中找到最大的值。
思路:维护一个ArrayList num_lst,每一次"depth==num_lst.size()",代表了当前的深度最深,否则更新已存在深度的值.
class Solution {
public List<Integer> num_lst = new ArrayList<Integer>();
public List<Integer> largestValues(TreeNode root) {
dfs(root,0);
return num_lst;
}
public void dfs(TreeNode root,int depth){
if(root==null) return;
if(depth==num_lst.size()){
num_lst.add(root.val);
}else{
num_lst.set(depth, Math.max(num_lst.get(depth), root.val));
}
dfs(root.left, depth+1);
dfs(root.right, depth+1);
}
}
中间的28、29、30漏了~
31. 1110. 删点成林
题目描述:
给出二叉树的根节点 root,树上每个节点都有一个不同的值。
如果节点值在 to_delete 中出现,我们就把该节点从树上删去,最后得到一个森林(一些不相交的树构成的集合)。
返回森林中的每棵树。你可以按任意顺序组织答案。
思路:
把节点加入答案需要有两个条件:
- 节点不被删除
- 节点没有父亲(父亲可能本来就没有(root)或者被删除了)
由于递归的思路,每一个节点既是父亲也是儿子.作为父亲,它需要:1. 判断自己要不要被删除 2. 告诉自己的左右孩子自己的状况(递归) 3. 修改自己和左右孩子的联系(根据递归的结果进行操作) 作为儿子,它需要:1. 结合自己要不要被删除和自己有没有父亲,考虑是否加入答案 2. 告诉自己的父亲自己有没有被删除(递归的结果).
代码:
class Solution {
Set<Integer> TODELETE;
public List<TreeNode> delNodes(TreeNode root, int[] to_delete) {
TODELETE = Arrays.stream(to_delete).boxed().collect(Collectors.toSet());
List<TreeNode> ans = new ArrayList<>();
dfs(root, ans, false);
return ans;
}
public boolean dfs(TreeNode root, List<TreeNode> ans, boolean parentExists){
//作为父亲
if(root==null) return false;
boolean del = TODELETE.contains(root.val);
if(dfs(root.left, ans, !del)){
root.left=null;
}
if(dfs(root.right, ans, !del)){
root.right=null;
}
//作为儿子
if(!del&&!parentExists){
ans.add(root);
}
return del;
}
}
32.547. 省份数量
题目描述:
有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。
省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。
给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。
返回矩阵中 省份 的数量。
思路:并查集
代码:
class Solution {
public int findCircleNum(int[][] isConnected) {
// 并查集yyds!
bcg BCG = new bcg(isConnected.length);
int row = isConnected.length;
int col = isConnected[0].length;
for(int i = 1; i < row; i++){
for(int j = 0; j < i; j++){
if(isConnected[i][j]==1){
BCG.union(i,j);
}
}
}
return BCG.getcot();
}
public class bcg{
private int cot;
private int[] parents;
public bcg(int size){
cot = size;
parents = new int[size];
for(int i=0;i<parents.length;i++){
parents[i] = i;
}
}
public int findroot(int i){
if(parents[i]!=i){
parents[i] = findroot(parents[i]);
}
return parents[i];
}
public void union(int i, int j){
int root_i = findroot(i);
int root_j = findroot(j);
if(root_i==root_j) return;
parents[root_i] = root_j;
cot --;
}
public int getcot(){
return cot;
}
}
}
33.947. 移除最多的同行或同列石头
题目描述:
n 块石头放置在二维平面中的一些整数坐标点上。每个坐标点上最多只能有一块石头。
如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除这块石头。
给你一个长度为 n 的数组 stones ,其中 stones[i] = [xi, yi] 表示第 i 块石头的位置,返回 可以移除的石子 的最大数量。
思路1:并查集yyds,可以移除的石头的最大数量=所有的石头数-连通子图数.
代码1:
class Solution {
public int removeStones(int[][] stones) {
bcg BCG = new bcg(stones.length);
for(int i=0;i<stones.length-1;i++){
for(int j=i+1;j<stones.length;j++){
int[] preArray = stones[i];
int[] nowArray = stones[j];
if(preArray[0]==nowArray[0]||preArray[1]==nowArray[1]){
BCG.union(i,j);
}
}
}
return stones.length - BCG.getcot();
}
public class bcg{
private int cot;
private int[] parents;
public bcg(int size){
cot = size;
parents = new int[size];
for(int i=0;i<parents.length;i++){
parents[i] = i;
}
}
public int findroot(int i){
if(parents[i]!=i){
parents[i] = findroot(parents[i]);
}
return parents[i];
}
public void union(int i, int j){
int root_i = findroot(i);
int root_j = findroot(j);
if(root_i==root_j) return;
parents[root_i] = root_j;
cot --;
}
public int getcot(){
return cot;
}
}
}
思路2:同样是并查集,但是!考虑x坐标是0到10000之间的10001个点,y坐标是10002到20002之间的10001个点,可降低时间复杂度.为了节约空间(吧),官解使用HashMap来定义parents,初始化时parents为空. 每一次union一组(x,y),会首先执行find(x)和find(y),而find函数中首先是把不存在的节点添加进去(连通图数+1),然后再进行合并
代码2:
class Solution {
public int removeStones(int[][] stones) {
findUnion FU = new findUnion(stones.length);
for(int[] stone:stones){
FU.union(stone[0], stone[1]+10001);
}
return stones.length - FU.get_cot();
}
public class findUnion{
private int cot = 0;
private HashMap<Integer, Integer> parents;
public findUnion(int size){
parents = new HashMap<Integer, Integer>(size);
}
public int find(int i){
if(!parents.containsKey(i)){
parents.put(i,i);
cot ++;
}
if(parents.get(i)!=i){
parents.put(i, find(parents.get(i)));
}
return parents.get(i);
}
public void union(int i, int j){
int root_i = find(i);
int root_j = find(j);
if(root_i == root_j) return;
parents.put(root_i, root_j);
cot --;
}
public int get_cot(){
return cot;
}
}
}
34. 337. 打家劫舍 III
题目描述:
在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
思路:
定义steal和notsteal两个状态哈希表,每一个root都有两个选择,如果root偷,那么它的左孩子和右孩子一定不偷;如果root不偷,那么它的左孩子和右孩子可以偷可能不偷.
代码1:
class Solution {
HashMap<TreeNode, Integer> steal = new HashMap<TreeNode, Integer>();
HashMap<TreeNode, Integer> notsteal = new HashMap<TreeNode, Integer>();
public int rob(TreeNode root) {
dfs(root);
return Math.max(steal.getOrDefault(root,0),notsteal.getOrDefault(root,0));
}
public void dfs(TreeNode root){
if(root==null) return;
dfs(root.left);
dfs(root.right);
int left_steal = steal.getOrDefault(root.left,0);
int left_notsteal = notsteal.getOrDefault(root.left,0);
int right_steal = steal.getOrDefault(root.right, 0);
int right_notsteal = notsteal.getOrDefault(root.right,0);
steal.put(root, root.val + left_notsteal + right_notsteal);
notsteal.put(root, Math.max(left_steal, left_notsteal)+Math.max(right_steal, right_notsteal));
}
}
代码2:用数组存储状态
class Solution {
HashMap<TreeNode, Integer> steal = new HashMap<TreeNode, Integer>();
HashMap<TreeNode, Integer> notsteal = new HashMap<TreeNode, Integer>();
public int rob(TreeNode root) {
int[] result = dfs(root);
return Math.max(result[0],result[1]);
}
public int[] dfs(TreeNode root){ // 0偷,1不偷
if(root==null) return new int[2];
int[] result_left = dfs(root.left);
int[] result_right = dfs(root.right);
int[] result_root = new int[2];
result_root[0] = root.val + result_left[1] + result_right[1];
result_root[1] = Math.max(result_left[0],result_left[1]) + Math.max(result_right[0], result_right[1]);
return result_root;
}
}
在这里插入代码片
35. 面试题 16.19. 水域大小
题目描述:
你有一个用于表示一片土地的整数矩阵land,该矩阵中每个点的值代表对应地点的海拔高度。若值为0则表示水域。由垂直、水平或对角连接的水域为池塘。池塘的大小是指相连接的水域的个数。编写一个方法来计算矩阵中所有池塘的大小,返回值需要从小到大排序。
思路1:dfs
代码2:
class Solution {
int[] dx = {0,-1,-1,-1,0,1,1,1};
int[] dy = {-1,-1,0,1,1,1,0,-1};
int width;
int height;
ArrayList<Integer> ans = new ArrayList<>();
public int[] pondSizes(int[][] land) {
this.width = land.length;
this.height = land[0].length;
for(int i = 0; i < width; i++){
for(int j = 0; j<height; j++){
if(land[i][j]==0){
ans.add(dfs(i,j,land));
}
}
}
Collections.sort(ans);
return ans.stream().mapToInt(Integer::valueOf).toArray();
}
public int dfs(int x, int y,int[][] land){
land[x][y] = 1;
int cot = 1;
for(int idx=0;idx<dx.length;idx++){
int nx = x+dx[idx];
int ny = y+dy[idx];
if(in_map(nx,ny)&&land[nx][ny]==0){
cot += dfs(nx,ny,land);
}
}
return cot;
}
public boolean in_map(int x,int y){
return 0<=x&&x<width&&0<=y&&y<height;
}
}
思路2:并查集
代码2:
36.117. 填充每个节点的下一个右侧节点指针 II
题目描述:
填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。
初始状态下,所有 next 指针都被设置为 NULL。
思路:一定要先遍历右子树!
代码:
class Solution {
public Node connect(Node root) {
// 遇到一个节点,判断root是否有左右节点,改变左节点的next为right
// 判断自己有没有next,如果有,判断next有没有left,如果有root.right.next = root.next.left,如果没有,判断next有没有right,如果有..
dfs(root);
return root;
}
public void dfs(Node root){
if(root==null) return;
if(root.left!=null && root.right!=null){
root.left.next = root.right;
}
Node next_root = root.next;
while(next_root!=null&&next_root.left==null&&next_root.right==null){
next_root = next_root.next;
}
if(next_root!=null){
if(root.right!=null){
if(next_root.left!=null){
root.right.next = next_root.left;
}else{
root.right.next = next_root.right;
}
}else{
if(root.left!=null){
if(next_root.left!=null){
root.left.next = next_root.left;
}else{
root.left.next = next_root.right;
}
}
}
}
dfs(root.right);
dfs(root.left);
}
}
37. 638. 大礼包
题目描述:
在LeetCode商店中, 有许多在售的物品。
然而,也有一些大礼包,每个大礼包以优惠的价格捆绑销售一组物品。
现给定每个物品的价格,每个大礼包包含物品的清单,以及待购物品清单。请输出确切完成待购清单的最低花费。
每个大礼包的由一个数组中的一组数据描述,最后一个数字代表大礼包的价格,其他数字分别表示内含的其他种类物品的数量。
任意大礼包可无限次购买。
思路1:
就两种选择:1. 要么我就全买单品 2. 要么我就买部分礼包. 具体怎么买是一个问题,那么我先遍历所有礼包,如果这个礼包我当前可以买,那我就先买了试试,进行递归. 最后比较这两种方案谁比较便宜.
代码1:
class Solution {
public int shoppingOffers(List<Integer> price, List<List<Integer>> special, List<Integer> needs) {
return dfs(price, special, needs);
}
public int dfs(List<Integer> price, List<List<Integer>> special, List<Integer> needs){
int res = 0;
for(int i = 0; i < price.size(); i ++){
res += price.get(i) * needs.get(i);
}
for(List<Integer>one_special:special){
List<Integer> clone = new ArrayList<>(needs);
int i;
for(i = 0;i<needs.size();i++){
int diff = needs.get(i) - one_special.get(i);
if(diff<0) break;
clone.set(i,diff);
}
if(i==needs.size()){
res = Math.min(res, one_special.get(i)+dfs(price, special, clone));
}
}
return res;
}
}
思路2:在思路1的基础上,使用HashMap记录已出现的needs状态节点
代码2:
class Solution {
public int shoppingOffers(List<Integer> price, List<List<Integer>> special, List<Integer> needs) {
HashMap<List<Integer>, Integer> map = new HashMap<>();
return dfs(price, special, needs, map);
}
public int dfs(List<Integer> price, List<List<Integer>> special, List<Integer> needs, HashMap<List<Integer>, Integer> map){
if(map.containsKey(needs)) return map.get(needs);
int res = 0;
for(int i = 0; i < price.size(); i ++){
res += price.get(i) * needs.get(i);
}
for(List<Integer>one_special:special){
List<Integer> clone = new ArrayList<>(needs);
int i;
for(i = 0;i<needs.size();i++){
int diff = needs.get(i) - one_special.get(i);
if(diff<0) break;
clone.set(i,diff);
}
if(i==needs.size()){
res = Math.min(res, one_special.get(i)+dfs(price, special, clone, map));
}
}
if(!map.containsKey(needs)) map.put(needs, res);
return res;
}
}
38.1254. 统计封闭岛屿的数目
题目描述:
有一个二维矩阵 grid ,每个位置要么是陆地(记号为 0 )要么是水域(记号为 1 )。
我们从一块陆地出发,每次可以往上下左右 4 个方向相邻区域走,能走到的所有陆地区域,我们将其称为一座「岛屿」。
如果一座岛屿 完全 由水域包围,即陆地边缘上下左右所有相邻区域都是水域,那么我们将其称为 「封闭岛屿」。
请返回封闭岛屿的数目。
思路:
深度优先搜索遍历连通图,如果连通图里存在边界点,那么该连通图不算做答案.
代码:
class Solution {
int height;
int width;
int[] dx = {0, -1, 0, 1};
int[] dy = {-1, 0, 1, 0};
public int closedIsland(int[][] grid) {
//从每一块0开始深搜,如果有节点在边界上,那么就不是封闭岛
this.height = grid.length;
this.width = grid[0].length;
int final_ans = 0;
for(int i = 0;i <grid.length;i++){
for(int j =0;j<grid[0].length;j++){
if(grid[i][j]==0){
int tmp_ans = dfs(i,j,grid);
if(tmp_ans==0) final_ans++;
}
}
}
return final_ans;
}
public int dfs(int i, int j, int[][] grid){
if(is_boundary(i,j)) return 1;
int ans = 0;
for(int idx=0;idx<dx.length;idx++){
int ni = i + dx[idx];
int nj = j + dy[idx];
if(is_in(ni,nj)&&grid[ni][nj]==0){
grid[ni][nj] = 1;
ans += dfs(ni,nj,grid);
}
}
return ans;
}
public boolean is_in(int i,int j){
return 0<=i&&i<height&&0<=j&&j<width;
}
public boolean is_boundary(int i, int j){
return i==0||i==(height-1)||j==0||j==(width-1);
}
}
思路2:改进:并不需要判断is_in,因为如果一个节点不是boundary,那它就不可能访问到其它节点
代码2:
class Solution {
int height;
int width;
int flag;
int[] dx = {0, -1, 0, 1};
int[] dy = {-1, 0, 1, 0};
public int closedIsland(int[][] grid) {
//从每一块0开始深搜,如果有节点在边界上,那么就不是封闭岛
this.height = grid.length;
this.width = grid[0].length;
int final_ans = 0;
for(int i = 0;i <grid.length;i++){
for(int j =0;j<grid[0].length;j++){
if(grid[i][j]==0){
flag = 1;
dfs(i,j,grid);
final_ans+=flag;
}
}
}
return final_ans;
}
public void dfs(int i, int j, int[][] grid){
if(is_boundary(i,j)){
flag = 0;
return;
}
int ans = 0;
for(int idx=0;idx<dx.length;idx++){
int ni = i + dx[idx];
int nj = j + dy[idx];
if(grid[ni][nj]==0){
grid[ni][nj] = 1;
dfs(ni,nj,grid);
}
}
}
// public boolean is_in(int i,int j){
// return 0<=i&&i<height&&0<=j&&j<width;
// }
public boolean is_boundary(int i, int j){
return i==0||i==(height-1)||j==0||j==(width-1);
}
}
39. 面试题 04.06. 后继者
题目描述:
设计一个算法,找出二叉搜索树中指定节点的“下一个”节点(也即中序后继)。
如果指定节点没有对应的“下一个”节点,则返回null。
思路:
真心不懂
代码:
class Solution {
public TreeNode inorderSuccessor(TreeNode root, TreeNode p) {
return dfs(root,p);
}
public TreeNode dfs(TreeNode root, TreeNode p){
if(root==null||p==null){
return null;
}
if(root.val<=p.val){
return dfs(root.right, p);
}else{
TreeNode left_ans = dfs(root.left,p);
return left_ans == null ? root : left_ans;
}
}
}
40. 1306. 跳跃游戏 III
题目描述:
这里有一个非负整数数组 arr,你最开始位于该数组的起始下标 start 处。当你位于下标 i 处时,你可以跳到 i + arr[i] 或者 i - arr[i]。
请你判断自己是否能够跳到对应元素值为 0 的 任一 下标处。
注意,不管是什么情况下,你都无法跳到数组之外。
思路1:
深度优先搜索,每一个位置最多只去一次,最后重新遍历数组,查看元素值为0的位置,你定义的boolean数组是否是true.一共遍历数组两次.
代码1:
class Solution {
public boolean[] have_visited;
public boolean canReach(int[] arr, int start) {
have_visited = new boolean[arr.length];
dfs(arr, start);
for(int idx=0;idx<arr.length;idx++){
if(arr[idx]==0&&have_visited[idx]==true){
return true;
}
}
return false;
}
public void dfs(int[] arr, int start){
int left_idx = start - arr[start];
if(left_idx>=0&&have_visited[left_idx]==false){
have_visited[left_idx] = true;
dfs(arr, left_idx);
}
int right_idx = start + arr[start];
if(right_idx<arr.length&&have_visited[right_idx]==false){
have_visited[right_idx] = true;
dfs(arr, right_idx);
}
}
}
思路2:
定义一个result,只遍历数组一次
代码2:
class Solution {
boolean res;
boolean[] have_visited;
public boolean canReach(int[] arr, int start) {
have_visited = new boolean[arr.length];
dfs(arr, start);
return res;
}
public void dfs(int[] arr, int start){
if(arr[start]==0) res = true;
if(res) return;//!
int left_idx = start - arr[start];
if(left_idx>=0&&have_visited[left_idx]==false){
have_visited[left_idx] = true;
dfs(arr, left_idx);
}
int right_idx = start + arr[start];
if(right_idx<arr.length&&have_visited[right_idx]==false){
have_visited[right_idx] = true;
dfs(arr, right_idx);
}
}
}
41.面试题34. 二叉树中和为某一值的路径
和113. 路径总和 II一样
42.756. 金字塔转换矩阵
题目描述:
现在,我们用一些方块来堆砌一个金字塔。 每个方块用仅包含一个字母的字符串表示。
使用三元组表示金字塔的堆砌规则如下:
对于三元组(A, B, C) ,“C”为顶层方块,方块“A”、“B”分别作为方块“C”下一层的的左、右子块。当且仅当(A, B, C)是被允许的三元组,我们才可以将其堆砌上。
初始时,给定金字塔的基层 bottom,用一个字符串表示。一个允许的三元组列表 allowed,每个三元组用一个长度为 3 的字符串表示。
如果可以由基层一直堆到塔尖就返回 true ,否则返回 false 。
思路:
参考https://blog.csdn.net/a1439775520/article/details/105553733
首先对所有可行的三元组进行预处理,组成map.递归中,我们定义两个字符串:bottom,now,分别代表当前层上,所需要的所有叶子节点,和目前已有的叶子节点.当两者长度相差1,说明当前层递归完成,特别的,如果,bottom的长度为2,now的长度为1,那么成功.
代码:
class Solution {
public boolean pyramidTransition(String bottom, List<String> allowed) {
HashMap<String, List<String>> map = new HashMap<>();
for(String allow : allowed){
String leaf = allow.substring(0,2);
String root = allow.substring(2,3);
if(!map.containsKey(leaf)){
List<String> root_list = new ArrayList<>();
root_list.add(root);
map.put(leaf, root_list);
}
else{
map.get(leaf).add(root);
}
}
return dfs(bottom, "", map);
}
public boolean dfs(String bottom, String now, HashMap<String, List<String>> map){
if(bottom.length()==2 && now.length()==1){
return true;
}
if(bottom.length() - now.length()==1){
return dfs(now, "", map);
}
int start = now.length();
int end = start + 2;
List<String> root_lst = map.get(bottom.substring(start, end));
if(root_lst==null) return false;
for(String root:root_lst){
if(dfs(bottom, now+root, map)) return true;
}
return false;
}
}
43. 17. 电话号码的字母组合
题目描述:
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
思路描述:深度优先搜索,定义一个StringBuffer来暂存结果
代码:
class Solution {
HashMap<Character, String> str_map = new HashMap<Character, String>();
public List<String> letterCombinations(String digits) {
str_map.put('2',"abc");
str_map.put('3',"def");
str_map.put('4',"ghi");
str_map.put('5',"jkl");
str_map.put('6',"mno");
str_map.put('7',"pqrs");
str_map.put('8',"tuv");
str_map.put('9',"wxyz");
if(digits.length()==0){
return new ArrayList<>();
}
ArrayList<String> ans_lst = new ArrayList<String>();
dfs(ans_lst, 0, digits, new StringBuffer());
return ans_lst;
}
public void dfs(ArrayList<String> ans_lst, int index, String digits, StringBuffer tmp_ans){
if(index == digits.length()){ // learn
ans_lst.add(tmp_ans.toString());
}else{
char d = digits.charAt(index);
String s = str_map.get(d);
for(int i = 0; i < s.length(); i++){
tmp_ans.append(s.charAt(i));
dfs(ans_lst, index+1, digits, tmp_ans);
tmp_ans.deleteCharAt(index);
}
}
}
}
44.491. 递增子序列
之后不会在CSDN上记录了,为了节约时间,直接在leeetcode上写注释
最后
以上就是迷路菠萝为你收集整理的[java]——leetcode刷题(深度优先搜索)(中等??)(TBC)前言26.526. 优美的排列27.515. 在每个树行中找最大值31. 1110. 删点成林32.547. 省份数量33.947. 移除最多的同行或同列石头34. 337. 打家劫舍 III35. 面试题 16.19. 水域大小36.117. 填充每个节点的下一个右侧节点指针 II37. 638. 大礼包38.1254. 统计封闭岛屿的数目39. 面试题 04.06. 后继者40. 1306. 跳跃游戏 III41.面试的全部内容,希望文章能够帮你解决[java]——leetcode刷题(深度优先搜索)(中等??)(TBC)前言26.526. 优美的排列27.515. 在每个树行中找最大值31. 1110. 删点成林32.547. 省份数量33.947. 移除最多的同行或同列石头34. 337. 打家劫舍 III35. 面试题 16.19. 水域大小36.117. 填充每个节点的下一个右侧节点指针 II37. 638. 大礼包38.1254. 统计封闭岛屿的数目39. 面试题 04.06. 后继者40. 1306. 跳跃游戏 III41.面试所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复