这里写目录标题
总结
323.重新安排行程
map:键保存起始地,值装一个优先队列
class Solution {
Map<String, PriorityQueue<String>> map = new HashMap<>();
LinkedList<String> res = new LinkedList<>();
public List<String> findItinerary(List<List<String>> tickets) {
for(List<String> ticket : tickets){
String src = ticket.get(0);
String dst = ticket.get(1);
if(!map.containsKey(src)){
PriorityQueue<String> pq = new PriorityQueue<String>();
map.put(src,pq);
}
//给队列中放入目的地,同一个起源地可能有多个,但是会自动排序
map.get(src).add(dst);
}
dfs("JFK");
return res;
}
private void dfs(String src){
// 知道起源地,取出对应的目的地队列
PriorityQueue<String> pq = map.get(src);
while(pq!=null&&pq.size()!=0){ //通过while循环,找到最后一个目的地
dfs(pq.poll());
}
res.addFirst(src);
}
}
51. N 皇后
class Solution {
List<List<String>> res = new ArrayList<>();
boolean [][] board;
HashSet<Integer> col;
HashSet<Integer> pie,na;
int n;
public List<List<String>> solveNQueens(int n) {
this.n = n;
this.board = new boolean[n][n];
this.col = new HashSet<>();
this.pie = new HashSet<>();
this.na = new HashSet<>();
dfs(0);
return res;
}
private void dfs(int i){
//边界条件 i表示行
if(i == n){
generate();
return; //将结果传入集合中
}
// j是列
for(int j =0;j<n;j++){
if(col.contains(j)||pie.contains(i+j)||na.contains(i-j)) continue;
board[i][j] = true;
col.add(j);
pie.add(i+j);
na.add(i-j);
dfs(i+1);
board[i][j] = false;
col.remove(j);
pie.remove(i+j);
na.remove(i-j);
}
}
// 对应的board的值转换为结果需要返回的list
private void generate(){
ArrayList<String> list = new ArrayList<>();
for(int i=0;i<n;i++){
StringBuilder sb = new StringBuilder();
for(int j =0;j<n;j++){
if(board[i][j]){
sb.append("Q");
}else{
sb.append(".");
}
}
list.add(sb.toString()); // 按照每行添加
}
res.add(new ArrayList<>(list));
}
}
方法二:对其中的col和pie和na都同时表示是否被前面的皇后映射到了,所以就可以用数组表示
class Solution {
List<List<String>> res = new ArrayList<>();
boolean [][] board;
boolean [] col,pie,na;
int n;
public List<List<String>> solveNQueens(int n) {
this.n = n;
this.board = new boolean[n][n];
this.col = new boolean[n];
this.pie = new boolean[n*2];
this.na = new boolean[100];
dfs(0);
return res;
}
private void dfs(int i){
//边界条件 i表示行
if(i == n){
generate();
return; //将结果传入集合中
}
// j是列
for(int j =0;j<n;j++){
if(col[j]||pie[i+j]||na[i-j+n] ) continue;
board[i][j] = true;
col[j] = true;
pie[i+j]= true;
na[i-j+n]= true;
dfs(i+1);
board[i][j] = false;
col[j] = false;
pie[i+j]= false;
na[i-j+n]= false;
}
}
// 对应的board的值转换为结果需要返回的list
private void generate(){
ArrayList<String> list = new ArrayList<>();
for(int i=0;i<n;i++){
StringBuilder sb = new StringBuilder();
for(int j =0;j<n;j++){
if(board[i][j]){
sb.append("Q");
}else{
sb.append(".");
}
}
list.add(sb.toString()); // 按照每行添加
}
res.add(new ArrayList<>(list));
}
}
这个讲的很暴力
函数1:需要dfs回溯(按照行),函数2:需要检查该点的上面的和左上,右上是否有皇后,函数3:把char数组board变成一个list
class Solution {
List<List<String>> res = new ArrayList<>();
char [][] board;
int n;
public List<List<String>> solveNQueens(int n) {
this.n = n;
board = new char[n][n];
for(int i =0;i<n;i++){
Arrays.fill(board[i],'.');
}
dfs(0);
return res;
}
private void dfs(int row){
//边界条件
if(row == n){
generate();
return;
}
for(int i =0;i<n;i++){ //i表示列
if(check(row,i)){
board[row][i] = 'Q';
dfs(row+1);
board[row][i] = '.';
}
}
}
private boolean check(int row,int col){
// 不用检查(row,col)坐标对应的行,因为回溯就是直接从每行开始
// 1.检查该列是否有
for(int i=0;i<row;i++){
if(board[i][col] == 'Q'){ return false;}
}
// 2.检查对角线-2.1左上对角线
int x = row-1,y=col-1;
while(x>=0&&y>=0){
if(board[x][y] == 'Q'){return false;}
x--;
y--;
}
// 2.2检查右上角对角线
x = row-1;
y = col+1;
while(x>=0&&y<n){
if(board[x][y] == 'Q'){return false;}
x--;
y++;
}
return true;
}
private void generate(){
ArrayList<String> list = new ArrayList<>();
for(int i=0;i<n;i++){
list.add(String.valueOf(board[i]));
}
res.add(list);
}
}
数组board变成一个list
// 方法一
private void generate(){
ArrayList<String> list = new ArrayList<>();
for(int i=0;i<n;i++){
list.add(String.valueOf(board[i]));
}
res.add(list);
}
// 方法二
private void generate(){
ArrayList<String> list = new ArrayList<>();
for(int i=0;i<n;i++){
StringBuilder sb = new StringBuilder();
for(int j =0;j<n;j++){
if(board[i][j]){
sb.append("Q");
}else{
sb.append(".");
}
}
list.add(sb.toString()); // 按照每行添加
}
res.add(new ArrayList<>(list));
}
37.数独
1.首先找到’.'的坐标,再依次添加1-9判断是否合法
代码随想录得题解
class Solution {
char[][] board;
public void solveSudoku(char[][] b) {
board = b;
dfs();
}
private boolean dfs(){
for(int i=0;i<9;i++){
for(int j =0;j<9;j++){
if(board[i][j]!='.'){
continue;
}
for(char k ='1';k<='9';k++){
if(check(i,j,k)){
board[i][j] = k;
if(dfs()){
return true;
}
board[i][j] ='.';
}
}
return false;
}
}
return true;
}
private boolean check(int row,int col, char k){
//1.检查(row,col)对应的行是否存在相同值
for (int i = 0; i < 9; i++){
if (board[row][i] == k){
return false;
}
}
//2. 检查对应的列
for (int j = 0; j < 9; j++){
if (board[j][col] == k){
return false;
}
}
//3.检查对应的9宫格
//获取9宫格左上角的左边
int x = (row / 3) * 3;
int y = (col / 3) * 3;
for (int i =x; i < x + 3; i++){
for (int j = y; j < y + 3; j++){
if (board[i][j] == k){
return false;
}
}
}
return true;
}
}