字母序靠前排在前面 如何记录映射关系 这是我不会的点
Collections.sort(tickets, (a,b)->a.get(1).compareTo(b.get(1)));
Collections.sort()方法详解
是对数据进行排序的一个方法,根据指定比较器产生的顺序对指定列表进行排序。
Collections.sort() 排序
返回值:return a.compareTo(b) 就排序了,为什么呢?
compareTo() 这个方法,它返回了3种int类型的值:
负整数 : a < b,a排在前面
零 : a = b, 位置不变
正整数 : a > b, a排在后面
剩下的就简单了
需要一个used数组来判断是否选中tickets
class Solution {
private LinkedList<String> path = new LinkedList<>();
private LinkedList<String> res;
public List<String> findItinerary(List<List<String>> tickets) {
Collections.sort(tickets, (a,b)->a.get(1).compareTo(b.get(1)));
path.add("JFK");
boolean[] used = new boolean[tickets.size()];
backtracking(tickets, used);
return res;
}
private boolean backtracking(List<List<String>> tickets, boolean[] used){
if(path.size() == tickets.size() + 1){
res = new LinkedList<>(path);
return true;
}
for(int i = 0; i < tickets.size(); i++){
if(!used[i] && tickets.get(i).get(0).equals(path.getLast())){
path.add(tickets.get(i).get(1));
used[i] = true;
if (backtracking(tickets, used)) {
return true;
}
used[i] = false;
path.removeLast();
}
}
return false;
}
}
第一次做这种棋盘的题目
一开始不知道怎么构建一个棋盘
其实就是一个二维数组
char[][] chessboard = new char[n][n];
for(char[] c : chessboard){
Arrays.fill(c, '.');
}
可以看出,二维矩阵中矩阵的高就是这棵树的高度,矩阵的宽就是树形结构中每一个节点的宽度。
只要搜索到了树的叶子节点,说明就找到了皇后们的合理位置了。
棋盘的宽度就是for循环的长度,递归的深度就是棋盘的高度,这样就可以套进回溯法的模板里了
回顾
String.copyValueOf(c);
copyValueOf()方法返回表示字符数组字符的String 此方法返回一个新的String数组并将字符复制到其中。
static String copyValueOf(char[] data, int offset, int count)
class Solution {
List<List<String>> res = new ArrayList<>();
public List<List<String>> solveNQueens(int n) {
char[][] chessboard = new char[n][n];
for(char[] c : chessboard){
Arrays.fill(c, '.');
}
backtracking(n, 0, chessboard);
return res;
}
private void backtracking(int n, int row, char[][] chessboard){
if(row == n){
res.add(ArrayList2List(chessboard));
return;
}
for(int col = 0; col < n; col++){
if(isValid(n, row, col, chessboard)){
chessboard[row][col] = 'Q';
backtracking(n, row+1, chessboard);
chessboard[row][col] = '.';
}
}
}
private List ArrayList2List(char[][] chessboard){
List<String> list = new ArrayList<>();
for(char[] c : chessboard){
list.add(String.copyValueOf(c));
}
return list;
}
private boolean isValid(int n, int row, int col, char[][] chessboard){
for(int i = 0; i < row; i++){
if(chessboard[i][col] == 'Q'){
return false;
}
}
for(int i = row - 1, j = col - 1; i >=0 && j >=0; i--,j--){
if(chessboard[i][j] == 'Q'){
return false;
}
}
for(int i = row - 1, j = col + 1; i >=0 && j < n ; i--, j++){
if(chessboard[i][j] == 'Q'){
return false;
}
}
return true;
}
}
其实就是遍历棋盘的每一行每一列
当遇到需要填写数字的时候
从1到9选择一个数字 并且判断合法性 然后填入
最终返回棋盘即可
这里递归函数需要返回值
递归函数的返回值需要是bool类型
因为解数独找到一个符合的条件(就在树的叶子节点上)立刻就返回,相当于找从根节点到叶子节点一条唯一路径,所以需要使用bool返回值。
一个for循环遍历棋盘的行,一个for循环遍历棋盘的列,一行一列确定下来之后,递归遍历这个位置放9个数字的可能性!
class Solution {
public void solveSudoku(char[][] board) {
backtracking(board);
}
private boolean backtracking(char[][] board){
for(int i = 0; i < 9; i++){
for(int j = 0; j < 9; j++){
if(board[i][j] != '.'){
continue;
}
for(char c = '1'; c <= '9'; c++){
if(isValid(i, j, c, board)){
board[i][j] = c;
if(backtracking(board)){
return true;
}
board[i][j] = '.';
}
}
return false;
}
}
return true;
}
private boolean isValid(int row, int col, char c, char[][] board){
for(int i = 0; i < 9; i++){
if(board[row][i] == c){
return false;
}
}
for(int i = 0; i < 9; i++){
if(board[i][col] == c){
return false;
}
}
int startRow = (row / 3) * 3;
int startCol = (col / 3) * 3;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
if(board[startRow + i][startCol + j] == c){
return false;
}
}
}
return true;
}
}
9宫格的判断需要学习一下
// 9宫格里是否重复
int startRow = (row / 3) * 3;
int startCol = (col / 3) * 3;
for (int i = startRow; i < startRow + 3; i++){
for (int j = startCol; j < startCol + 3; j++){
if (board[i][j] == val){
return false;
}
}
}