332.重新安排行程
题目链接:332.重新安排行程
如果存在多种有效的行程,请你按字符自然排序返回最小的行程组合。例如,行程 [“JFK”, “LGA”] 与 [“JFK”, “LGB”] 相比就更小,排序更靠前
所有的机场都用三个大写字母表示(机场代码)。
假定所有机票至少存在一种合理的行程。
所有的机票必须都用一次 且 只能用一次。
示例 1:
输入:[[“MUC”, “LHR”], [“JFK”, “MUC”], [“SFO”, “SJC”], [“LHR”, “SFO”]]
输出:[“JFK”, “MUC”, “LHR”, “SFO”, “SJC”]
示例 2:
输入:[[“JFK”,“SFO”],[“JFK”,“ATL”],[“SFO”,“ATL”],[“ATL”,“JFK”],[“ATL”,“SFO”]]
输出:[“JFK”,“ATL”,“JFK”,“SFO”,“ATL”,“SFO”]
解释:另一种有效的行程是 [“JFK”,“SFO”,“ATL”,“JFK”,“ATL”,“SFO”]。但是它自然排序更大更靠后。
题目难点:
1.一个行程中,如果航班处理不好容易变成一个圈,成为死循环
2.有多种解法,字母序靠前排在前面,让很多同学望而退步,如何该记录映射关系呢 ? 难点在于容器的选择与使用
3.使用回溯法(也可以说深搜) 的话,那么终止条件是什么呢?
4.搜索的过程中,如何遍历一个机场所对应的所有机场。
代码如下:
//超时 需使用Map降低搜索时间
class Solution {
private LinkedList<String> res;
private LinkedList<String> path = new LinkedList<>();
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((ArrayList) tickets, used);
return res;
//如何返回字典序最小的组合,排序后已经达到效果 字典序小的被先找到
}
public boolean backTracking(ArrayList<List<String>> tickets, boolean[] used) {
//遇到的机场个数,如果达到了(航班数量+1),那么我们就找到了一个行程
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;
//回溯
//为什么返回值是bool类型
//因为并不需要遍历整棵树 其遇到一个结果就返回
if (backTracking(tickets, used)) {
return true;
}
used[i] = false;
path.removeLast();
}
}
return false;
}
}
超时 如何使用Map降低搜索时间
51.N皇后
题目链接:N皇后
解题思路:是一个二维回溯 注意判断是否合法的逻辑
class Solution {
private List<List<String>> res=new ArrayList<>();
public List<List<String>> solveNQueens(int n) {
if(n==1){
res.add(new ArrayList<>(Arrays.asList("Q")));
return res;
}
if(n==2||n==3){
return res;
}
char[][] arr = new char[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
arr[i][j] = '.';
}
}
backtracking( arr,n, 0);
return res;
}
//index表示当前是第几个皇后
void backtracking(char[][] arr,int n,int index){
//收集结果 最后一行的有效性什么时候判断 当有3行的时候 index=2是判断第三行 判断之后 index=3
if(n==index){
res.add(Array2List(arr));
return;
}
for(int i=0;i<n;i++){
if(isVaild(index,i,arr,n)){
arr[index][i] = 'Q';
backtracking( arr,n, index+1);
arr[index][i] = '.';
}
}
}
//新建二维数组
public List Array2List(char[][] chessboard) {
List<String> list = new ArrayList<>();
for (char[] c : chessboard) {
list.add(String.copyValueOf(c));
}
return list;
}
//判断当前位置是否有效
boolean isVaild(int row, int col, char[][] arr, int n){
for (int i = 0; i < row; i++) { // 这是一个剪枝
if (arr[i][col] == 'Q') {
return false;
}
}
//斜角
for (int i = row - 1, j = col - 1; i >=0 && j >= 0; i--, j--) {
if (arr[i][j] == 'Q') {
return false;
}
}
for(int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
if (arr[i][j] == 'Q') {
return false;
}
}
return true;
}
}
解数独
题目链接:37. 解数独