递归与回溯(Leecode17/46/77/79/200/51)

在这里插入图片描述
在这里插入图片描述

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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值