NC刷题笔记9-递归回溯

NC刷题笔记9-递归回溯

    • BM55 没有重复项数字的全排列
    • BM56 有重复项数字的全排列
    • BM57 岛屿数量
    • BM58 字符串的排列
    • BM59 N皇后问题
    • BM60 括号生成
    • BM61 矩阵最长递增路径

本博客文章(学习笔记)导航 (点击这里访问)
NC刷题笔记9-递归回溯_第1张图片

BM55 没有重复项数字的全排列

思路:
	回溯,用一个boolean数组标识是否走过
import java.util. ;

public class Solution {
    ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();
    public ArrayList<ArrayList<Integer>> permute(int[] num) {
        if(num==null||num.length==0) return res;
        boolean[] visited=new boolean[num.length];
        ArrayList<Integer> list=new ArrayList<>();
        backtrace(num,visited,list);
        return res;
    }
    
    public void backtrace(int[] num,boolean[] visited,ArrayList<Integer> list){
        if(list.size()==num.length){
            res.add(new ArrayList<>(list));
            return;
        }
        for(int i=0;i<num.length;i++){
            if(!visited[i]){
                list.add(num[i]);
                visited[i]=true;
                backtrace(num,visited,list);
                list.remove(list.size()-1);
                visited[i]=false;
            }
        }
    }
}

BM56 有重复项数字的全排列

思路:
	1 先求出全排列
	2 treemap 自定义排序
	3 遍历treemap把结果放入list数组
import java.util. ;

public class Solution {
    ArrayList<ArrayList<Integer>> res=new ArrayList<ArrayList<Integer>>();
    public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) {
        boolean[] visited=new boolean[num.length];
        ArrayList<Integer> list=new ArrayList<>();
        backtrace(num,visited,list);

        TreeMap<String,ArrayList<Integer>> set=new TreeMap<String,ArrayList<Integer>>((a,b)->{
            return a.compareTo(b);
        });
        for(int i=0;i<res.size();i++){
            set.put(getString(res.get(i)),res.get(i));
        }
        res=new ArrayList<ArrayList<Integer>>();
        for(Map.Entry<String,ArrayList<Integer>> map:set.entrySet()){
            res.add(map.getValue());
        }
        return res;
    }

    public void backtrace(int[] num,boolean[] visited,ArrayList<Integer> list){
        if(list.size()==num.length){
            res.add(new ArrayList<>(list));
            return;
        }

        for(int i=0;i<num.length;i++){
            if(!visited[i]){
                visited[i]=true;
                list.add(num[i]);
                backtrace(num,visited,list);
                visited[i]=false;
                list.remove(list.size()-1);
            }
        }

    }
    
    public String getString(ArrayList<Integer> list){
        StringBuilder sb=new StringBuilder();
        for(int i:list) {
            sb.append(i+"");
        }
        return sb.toString();
    }
}

BM57 岛屿数量

描述
给一个01矩阵,1代表是陆地,0代表海洋, 如果两个1相邻,那么这两个1属于同一个岛。我们只考虑上下左右为相邻。
岛屿: 相邻陆地可以组成一个岛屿(相邻:上下左右) 判断岛屿个数。

例如:
[[1,1,0,0,0],
[0,1,0,1,1],
[0,0,0,1,1],
[0,0,0,0,0],
[0,0,1,1,1]]
对应的输出为 3

示例1
输入:[[1,1,0,0,0],[0,1,0,1,1],[0,0,0,1,1],[0,0,0,0,0],[0,0,1,1,1]]
返回值:3

示例2
输入:[[0]]
返回值:0
思路:
	1 遍历数组
	2 写一个改变状态的函数
	3 一旦遇见为1的数组,就把和该位置相邻的所有的为1的位置改为2,同时岛屿数量加1
import java.util. ;


public class Solution {
    /  
       判断岛屿数量
       @param grid char字符型二维数组 
       @return int整型
      /
    int num=0;
    public int solve (char[][] grid) {
        // write code here
        for(int i=0;i<grid.length;i++){
            for(int j=0;j<grid[i].length;j++){
                if(grid[i][j]=='1'){
                    num++;
                    changeState(grid,i,j);
                }
            }
        }
        return num;
    }
    
    public void changeState(char[][] grid,int i,int j){
        if(i<0||i>=grid.length||j<0||j>=grid[0].length||grid[i][j]=='0') return;
        if(grid[i][j]=='1'){
            grid[i][j]='2';
            changeState(grid,i,j+1);
            changeState(grid,i,j-1);
            changeState(grid,i+1,j);
            changeState(grid,i-1,j);
        }
    }
}

BM58 字符串的排列

1 先求全排列
2 用hashset去重
3 把set放在list里面
import java.util. ;
public class Solution {
    HashSet<String> set=new HashSet<>();
    public ArrayList<String> Permutation(String str) {
       ArrayList<String> res=new ArrayList<String>();
       if(str==null||str.length()==0) return res;
       boolean[] visited=new boolean[str.length()];
        String s="";
        backtrace(str,visited,s);
       for(String j:set) res.add(j);
        return res;
    }
    
    public void backtrace(String str,boolean[] visited,String s){
        if(s.length()==str.length()) set.add(s);
        for(int i=0;i<str.length();i++){
            if(!visited[i]){
                visited[i]=true;
                s=s+str.charAt(i);
                backtrace(str,visited,s);
                s=s.substring(0,s.length()-1);
                visited[i]=false;
            }
        }
    }
}

BM59 N皇后问题

思路:
	1 一行一行的判断
	2 回溯
import java.util. ;

public class Solution {
    int answer=0;
    public int Nqueen (int n) {
        // write code here
        char[][] chess=new char[n][n];
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                chess[i][j]='.';
            }
        }
        backtrace(chess,0);
        return answer;
    }
    
    public void backtrace(char[][] chess , int row){
        if(row==chess.length){
            answer++;
            return;
        }
        for(int i=0;i<chess.length;i++){
            if(valid(chess,row,i)){
                chess[row][i]='Q';
                backtrace(chess,row+1);
                chess[row][i]='.';
            }
        }
    }
    
    public boolean valid(char[][] chess,int i,int j){
        if(chess[i][j]=='Q') return false;
        
        for(int y=0;y<=i;y++){
            if(chess[y][j]=='Q') return false;
        }
        
        for(int x=i,y=j;x>=0&&y>=0;x--,y--){
            if(chess[x][y]=='Q') return false;
        }
        
        for(int x=i,y=j;x>=0&&y<chess.length;x--,y++){
            if(chess[x][y]=='Q') return false;
        }
        
        return true;
    }
}

BM60 括号生成

描述
给出n对括号,请编写一个函数来生成所有的由n对括号组成的合法组合。
例如,给出n=3,解集为:"((()))", "(()())", "(())()", "()()()", "()(())"
数据范围:0≤n≤10
要求:空间复杂度 O(n!),时间复杂度O(n!)

示例1
输入:1
返回值:["()"]

示例2
输入:2
返回值:["(())","()()"]
思路:
1 全排列
2 判断是否合法
3 去重
import java.util. ;

public class Solution {
    HashSet<String> set=new HashSet<>();
    public ArrayList<String> generateParenthesis (int n) {
        ArrayList<String> res=new ArrayList<String>();
        backtrace(n,n,"",n);
        for(String s:set) res.add(s);
        return res;
    }
    
    public void backtrace(int left,int right,String res,int n){
        if(res.length()==2 n && judge(res)){
            set.add(res);
            return;
        }
        if(left!=0){
            left--;
            res=res+'(';
            backtrace(left,right,res,n);
            res=res.substring(0,res.length()-1);
            left++;
        }
        if(right!=0){
            right--;
            res=res+')';
            backtrace(left,right,res,n);
            res=res.substring(0,res.length()-1);
            right++;
        }
    }
    
    
    public boolean judge(String str){
        if(str==null||str.equals("")) return true;
        if(str.length()%2==1) return false;
        Stack<Character> stack=new Stack<>();
        for(int i=0;i<str.length();i++){
            char c=str.charAt(i);
            if(c=='('){
                stack.push(c);
            }else{
                if(stack.isEmpty()) return false;
                if(!stack.isEmpty() && stack.peek()=='('){
                    stack.pop();
                }
            }
        }
        return stack.isEmpty();
    }
}

BM61 矩阵最长递增路径

NC刷题笔记9-递归回溯_第2张图片

思路:
	递归,用二维数组表示走过的地方
	遍历每个位置,在每个位置上 上下左右走,遇到走过的地方直接返回结果
public class Solution {
    int[][] dp;
    public int solve (int[][] matrix) {
        // write code here
        if(matrix==null||matrix.length==0) {
            return 0;
        }
        int result=0;
        int row=matrix.length;
        int collum=matrix[0].length;
        dp=new int[row][collum];
        for(int i=0;i<row;i++){
            for(int j=0;j<collum;j++){
                result=Math.max(result,dfs(matrix,i,j,Integer.MIN_VALUE));
            }
        }
        return result;
    }

    public int dfs(int[][] matrix,int i,int j,int pre){
        if(i<0||i>=matrix.length||j<0||j>=matrix[0].length) {
            return 0;
        }
        if(matrix[i][j]<=pre) {
            return 0;
        }
        if(dp[i][j]!=0) {
            return dp[i][j];
        }
        int up=dfs(matrix,i-1,j,matrix[i][j]);
        int down=dfs(matrix,i+1,j,matrix[i][j]);
        int left=dfs(matrix,i,j-1,matrix[i][j]);
        int right=dfs(matrix,i,j+1,matrix[i][j]);
        dp[i][j]=Math.max(Math.max(up,down),Math.max(right,left))+1;
        return dp[i][j];
    }
}

你可能感兴趣的:(算法,数据结构,linux)