class Solution {
private List<String> slist=new ArrayList<String>();
String numtochar[]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
public void findString(String digits, int index, String s){
if(index==digits.length()){
slist.add(s);
return;
}
char c = digits.charAt(index);
String cstring = numtochar[c-'0'];
for(int i=0; i<cstring.length();i++){
findString(digits, index+1,s+cstring.charAt(i));
}
}
public List<String> letterCombinations(String digits) {
if(digits.equals("")) return slist;//digits=="" 不可以
// if(digits.length()==0) return slist;
findString(digits,0,"");
return slist;
}
}
class Solution {
//存储全部的返回集合类型
List<List<Integer>> listall = new ArrayList<>();
//循环时只需要找到未访问的数据,所以设置标记访问/未访问
boolean flag[];
public List<List<Integer>> permute(int[] nums) {
List<Integer> list = new ArrayList<Integer>();
if(nums.length==0) return listall;
//标记数组实例化
flag = new boolean[nums.length];
//初始化标记数组
for(int i = 0;i<nums.length;i++)
flag[i]=false;
//调用递归含糊
sortAll(nums,0,list);
return listall;
}
//nums为数组,num记录当前list中有几个nums中的数据,list为已经遍历的值
public void sortAll(int[]nums, int num, List<Integer> list){
//如果当前list中数据与nums数据个数相同,表示便利完成,将list添加到listall中,并返回
if(nums.length==num){
listall.add(new ArrayList<Integer>(list));
return;
}
//在数组中找第num+1个元素,添加到list中,并不是所有的都添加
for(int i=0; i<nums.length;i++){
if(!flag[i]){
flag[i]=true;
list.add(nums[i]);
sortAll(nums,num+1,list);
//回溯向上返回,将当前list集合中最后一个元素剔除
list.remove(list.get(list.size()-1));
flag[i]=false;
}
}
}
}
class Solution {
List<List<Integer>> listall = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
//边界条件考虑齐全 关于k的容易忽略
if(n<1||k<=0||k>n) return listall;
int nums[]=new int[n+1];
for(int i = 0;i<=n;i++){
nums[i]=i;
}
List<Integer> list = new ArrayList<Integer>();
makecombine(nums,k,1,list);
return listall;
}
public void makecombine(int[] nums,int k, int index, List<Integer> list){
if(list.size()==k){
listall.add(new ArrayList(list));
return;
}
for(int i = index;i<nums.length;i++){
list.add(nums[i]);
//这里的递归从i的下一个开始,而不是index下一个
makecombine(nums,k,i+1,list);
list.remove(list.get(list.size()-1));
}
}
}
对组合问题优化——剪枝
优化循环条件:每个list中已经含有一些数据,只需要找到k-list.size个即可,不需要再多了。所以只需要保证从n向前找 k-list.size 个即可。
循环条件改为:n-(k-list.size())+1个即可
class Solution {
List<List<Integer>> listall = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
if(n<1||k<=0||k>n) return listall;
List<Integer> list = new ArrayList<Integer>();
makecombine(n,k,1,list);
return listall;
}
public void makecombine(int n,int k, int index, List<Integer> list){
if(list.size()==k){
listall.add(new ArrayList(list));
return;
}
for(int i = index;i<=n-(k-list.size())+1;i++){
list.add(i);
makecombine(n,k,i+1,list);//这里的递归从i的下一个开始,而不是index下一个
list.remove(list.get(list.size()-1));
}
}
}
二维平面上的回溯问题:
class Solution {
private int[][] movepoint = {{-1,0},{0,1},{1,0},{0,-1}};
int m,n;
int visited[][];
public boolean exist(char[][] board, String word) {
m = board.length;
n = board[0].length;
//标记访问数组实例化与初始化
visited = new int[m][n];
for(int i=0;i<m;i++){
for(int j = 0;j<n;j++){
visited[i][j]=0;
}
}
//从每一个char开始一次寻找,直到找到一条完整路径返回true
for(int i=0;i<board.length;i++){
for(int j = 0;j<board[0].length;j++){
if(search(board,word,0,i,j))
return true;
}
}
return false;
}
public boolean JudgePoint(char[][] board,int x,int y){
if(x<board.length&&x>=0&&y>=0&&y<board[0].length)
return true;
return false;
}
public boolean search(char[][]board,String word,int index,int pointx,int pointy){
if(index==word.length()-1)
return board[pointx][pointy]==word.charAt(index);
if(board[pointx][pointy]==word.charAt(index)){
visited[pointx][pointy]=1;
//向四个方向查找
for(int i = 0;i<4;i++){
int newx = pointx+movepoint[i][0];
int newy = pointy+movepoint[i][1];
//需要确保新的坐标不超过界限,即将访问的节点未被访问过
if(JudgePoint(board,newx,newy)&&(visited[newx][newy]==0)){
if(search(board,word,index+1,newx,newy))
return true;
}
}
visited[pointx][pointy]=0;
}
return false;
}
}
class Solution {
int visited[][];
int m,n;
int[][] point = {{-1,0},{0,1},{1,0},{0,-1}};
public int numIslands(char[][] grid) {
m = grid.length;
if(m<=0) return 0 ;
n = grid[0].length;
visited = new int[m][n];
int island_count = 0;
for(int i = 0;i<m;i++){
for(int j = 0;j<n;j++){
visited[i][j]=0;
}
}
for(int i = 0;i<m;i++){
for(int j = 0;j<n;j++){
if(grid[i][j]=='1'&&visited[i][j]==0){
//满足该条件说明存在一块陆地
island_count++;
//将该点相连接的所有陆地标记,防止重复就按
dfs(grid,i,j);
}
}
}
return island_count;
}
//从gridxy的位置开始,进行folldfill
public void dfs(char[][] grid,int x,int y){
visited[x][y]=1;
for(int i = 0;i<4;i++){
int newx = x+point[i][0];
int newy = y+point[i][1];
if(inArea(newx,newy)&&visited[newx][newy]==0&&grid[newx][newy]=='1')
dfs(grid,newx,newy);
}
}
public boolean inArea(int x,int y){
return x>=0&&x<m&&y>=0&&y<n;
}
}
class Solution {
List<List<String>> listall = new ArrayList<>();
int rows[],dig1[],dig2[];
//上,下,对角线 不能有 冲突
public List<List<String>> solveNQueens(int n) {
if(n<1) return listall;
List<Integer> list = new ArrayList();
rows = new int[n];//第一行的第一个数为1,则第二行的第第一个数不能为1.设置列标记
dig1 = new int[2*n-1];//↗对角线标记一共有n-1个,观察对角线元素可知。行和列相加从0-n-1。对应数组下标
dig2 = new int[2*n-1];//↘对角线,相减+n01,从0-n-1.对应数组下标
//初始化标记数组
for(int i=0;i<n;i++){
rows[i]=0;
}
for(int i =0;i<2*n-1;i++){
dig2[i]=0;
dig1[i]=0;
}
//递归产生皇后问题
findQ(n,0,list);
return listall;
}
//n为皇后个数,也就是列数。row代表行,在当前行放置一个Q。list存储每一行Q存储的列值。
public void findQ(int n,int row, List<Integer> list){
if(n==row){
List<String> listin = generateQ(n,list);
listall.add(listin);
return;
}
//用i代表列,row代表行。在第row行查找i位置存放Q
for(int i = 0;i<n;i++){
if(rows[i]==0&&dig1[row+i]==0&&dig2[row-i+n-1]==0){
list.add(i);
rows[i]=1;
dig1[row+i]=1;
dig2[row-i+n-1]=1;
findQ(n,row+1,list);//行递增。如果这一行找到放置Q的位置,则在下一层继续寻找
rows[i]=0; //从当前找完的第一行第i列,查找第i+1列。记得将标记清空
dig1[row+i]=0;
dig2[row-i+n-1]=0;
list.remove(list.size()-1);
}
}
//System.out.println(list);
}
//根据给出的list中4个每行Q的位置,生成String
public List<String> generateQ(int n, List<Integer> list){
List<String> relist = new ArrayList<String>();
char[][] sq = new char[n][n];
for(int i=0;i<n;i++){
int index = list.get(i);
for(int j =0;j<n;j++){
if(j==index)
sq[i][j]='Q';
else
sq[i][j]='.';
}
}
for(int i =0;i<n;i++){
String ads = "";
for(int j =0 ;j<n;j++){
ads=ads+sq[i][j];
}
relist.add(ads);
}
return relist;
}
}