NC刷题笔记9-递归回溯
-
- BM55 没有重复项数字的全排列
- BM56 有重复项数字的全排列
- BM57 岛屿数量
- BM58 字符串的排列
- BM59 N皇后问题
- BM60 括号生成
- BM61 矩阵最长递增路径
本博客文章(学习笔记)导航 (点击这里访问)
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) {
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) {
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 矩阵最长递增路径
思路:
递归,用二维数组表示走过的地方
遍历每个位置,在每个位置上 上下左右走,遇到走过的地方直接返回结果
public class Solution {
int[][] dp;
public int solve (int[][] matrix) {
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];
}
}