leecode更新
This commit is contained in:
parent
5317d93f39
commit
1104f87ef2
|
|
@ -0,0 +1,207 @@
|
|||
package com.markilue.leecode.backtrace;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.backtrace
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2023-02-03 10:21
|
||||
*@Description:
|
||||
* TODO 力扣332 重新安排行程:
|
||||
* 给你一份航线列表 tickets ,其中 tickets[i] = [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。
|
||||
* 所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始。如果存在多种有效的行程,请你按字典排序返回最小的行程组合。
|
||||
* 例如,行程 ["JFK", "LGA"] 与 ["JFK", "LGB"] 相比就更小,排序更靠前。
|
||||
* 假定所有机票至少存在一种合理的行程。且所有的机票 必须都用一次 且 只能用一次。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T13_0_FindItinerary {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
List<List<String>> tickets = new ArrayList<>();
|
||||
tickets.add(Arrays.asList("MUC", "LHR"));
|
||||
tickets.add(Arrays.asList("JFK", "MUC"));
|
||||
tickets.add(Arrays.asList("SFO", "SJC"));
|
||||
tickets.add(Arrays.asList("LHR", "SFO"));
|
||||
findItinerary(tickets);
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test1() {
|
||||
List<List<String>> tickets = new ArrayList<>();
|
||||
tickets.add(Arrays.asList("JFK", "SFO"));
|
||||
tickets.add(Arrays.asList("JFK", "ATL"));
|
||||
tickets.add(Arrays.asList("SFO", "ATL"));
|
||||
tickets.add(Arrays.asList("ATL", "JFK"));
|
||||
tickets.add(Arrays.asList("ATL", "SFO"));
|
||||
findItinerary1(tickets);
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
List<List<String>> tickets = new ArrayList<>();
|
||||
tickets.add(Arrays.asList("JFK", "KUL"));
|
||||
tickets.add(Arrays.asList("JFK", "NRT"));
|
||||
tickets.add(Arrays.asList("NRT", "JFK"));
|
||||
// tickets.add(Arrays.asList("ATL", "JFK"));
|
||||
// tickets.add(Arrays.asList("ATL", "SFO"));
|
||||
findItinerary1(tickets);
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
|
||||
List<String> cur = new ArrayList<>();
|
||||
List<String> result = new ArrayList<>();
|
||||
List<List<String>> result1 = new ArrayList<>();
|
||||
|
||||
public List<String> findItinerary(List<List<String>> tickets) {
|
||||
Collections.sort(tickets, new Comparator<List<String>>() {
|
||||
@Override
|
||||
public int compare(List<String> o1, List<String> o2) {
|
||||
return o1.get(1).compareTo(o2.get(0));
|
||||
}
|
||||
});
|
||||
backtracking(tickets, 0, "", new boolean[tickets.size()]);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void backtracking(List<List<String>> tickets, int level, String last, boolean[] used) {
|
||||
if (level == tickets.size()) {
|
||||
//所有机票用完了
|
||||
result = new ArrayList<>(cur);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < tickets.size(); i++) {
|
||||
if (level == 0) {
|
||||
if (!"JFK".equals(tickets.get(i).get(0))) {
|
||||
//起始地一定要是JFK
|
||||
continue;
|
||||
}
|
||||
used[i] = true;
|
||||
List<String> lines = tickets.get(i);
|
||||
cur.add(lines.get(0));
|
||||
cur.add(lines.get(1));
|
||||
backtracking(tickets, level + 1, lines.get(1), used);
|
||||
if (result != null) {
|
||||
return;
|
||||
}
|
||||
used[i] = false;
|
||||
cur.clear();
|
||||
} else {
|
||||
if (used[i] || !last.equals(tickets.get(i).get(0))) {
|
||||
continue;
|
||||
}
|
||||
used[i] = true;
|
||||
cur.add(tickets.get(i).get(1));
|
||||
backtracking(tickets, level + 1, tickets.get(i).get(1), used);
|
||||
if (result != null) {
|
||||
return;
|
||||
}
|
||||
used[i] = false;
|
||||
cur.remove(cur.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 代码优化
|
||||
* 速度击败26.88%,内存击败43.82% 15ms
|
||||
* @param tickets
|
||||
* @return
|
||||
*/
|
||||
public List<String> findItinerary1(List<List<String>> tickets) {
|
||||
Collections.sort(tickets, (a, b) -> a.get(1).compareTo(b.get(1)));
|
||||
cur.add("JFK");
|
||||
backtracking1(tickets, 0, "JFK", new boolean[tickets.size()]);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void backtracking1(List<List<String>> tickets, int level, String last, boolean[] used) {
|
||||
if (level == tickets.size()) {
|
||||
//所有机票用完了
|
||||
result = new ArrayList<>(cur);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < tickets.size(); i++) {
|
||||
if (used[i] || !last.equals(tickets.get(i).get(0))) {
|
||||
continue;
|
||||
}
|
||||
used[i] = true;
|
||||
cur.add(tickets.get(i).get(1));
|
||||
backtracking1(tickets, level + 1, tickets.get(i).get(1), used);
|
||||
if (result != null && result.size() != 0) {
|
||||
return;
|
||||
}
|
||||
used[i] = false;
|
||||
cur.remove(cur.size() - 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 官方解法:使用一个优先队列进行排序,好像默认了按字典序就一定能遍历完所有的票
|
||||
* 速度击败98.38%,内存击败5.4% 5ms
|
||||
*/
|
||||
Map<String, PriorityQueue<String>> map = new HashMap<String, PriorityQueue<String>>();
|
||||
List<String> itinerary = new LinkedList<String>();
|
||||
|
||||
public List<String> findItinerary2(List<List<String>> tickets) {
|
||||
for (List<String> ticket : tickets) {
|
||||
String src = ticket.get(0), dst = ticket.get(1);
|
||||
if (!map.containsKey(src)) {
|
||||
map.put(src, new PriorityQueue<String>());
|
||||
}
|
||||
map.get(src).offer(dst);
|
||||
}
|
||||
dfs("JFK");
|
||||
Collections.reverse(itinerary);
|
||||
return itinerary;
|
||||
}
|
||||
|
||||
public void dfs(String curr) {
|
||||
while (map.containsKey(curr) && map.get(curr).size() > 0) {
|
||||
String tmp = map.get(curr).poll();
|
||||
dfs(tmp);
|
||||
}
|
||||
itinerary.add(curr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 官方最快 4ms,不用反转了,进一步优化
|
||||
*/
|
||||
private List<String> resList = new LinkedList<>();
|
||||
|
||||
public List<String> findItinerary3(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<>();
|
||||
map.put(src, pq);
|
||||
}
|
||||
map.get(src).add(dst);
|
||||
}
|
||||
dfs1("JFK");
|
||||
return resList;
|
||||
}
|
||||
|
||||
private void dfs1(String src) {
|
||||
PriorityQueue<String> pq = map.get(src);
|
||||
while (pq != null && !pq.isEmpty()){
|
||||
dfs1(pq.poll());
|
||||
}
|
||||
|
||||
((LinkedList<String>) resList).addFirst(src);
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ import java.util.*;
|
|||
* 每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
|
||||
* @Version: 1.0
|
||||
*/
|
||||
public class SolveNQueens {
|
||||
public class T13_1_SolveNQueens {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
|
@ -0,0 +1,201 @@
|
|||
package com.markilue.leecode.backtrace.second;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*@BelongsProject: Leecode
|
||||
*@BelongsPackage: com.markilue.leecode.backtrace.second
|
||||
*@Author: dingjiawen
|
||||
*@CreateTime: 2023-02-03 12:43
|
||||
*@Description:
|
||||
* TODO 力扣51题 N皇后:
|
||||
* 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。
|
||||
* n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
|
||||
* 给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
|
||||
* 每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
|
||||
*@Version: 1.0
|
||||
*/
|
||||
public class T13_1_SolveNQueens {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
System.out.println(solveNQueens1(4));
|
||||
}
|
||||
|
||||
List<List<String>> result = new ArrayList<>();
|
||||
List<String> cur = new ArrayList<>();
|
||||
|
||||
public List<List<String>> solveNQueens(int n) {
|
||||
backtracking(n, 0, new boolean[n][n]);
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 速度击败41.44%,内存击败78.99% 4ms
|
||||
* @param n
|
||||
* @param level
|
||||
* @param used
|
||||
*/
|
||||
public void backtracking(int n, int level, boolean[][] used) {
|
||||
if (level == n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int j = 0; j < n; j++) {
|
||||
if(used[i][j]){
|
||||
builder.append("Q");
|
||||
}else {
|
||||
builder.append(".");
|
||||
}
|
||||
}
|
||||
cur.add(builder.toString());
|
||||
}
|
||||
result.add(new ArrayList<>(cur));
|
||||
cur.clear();
|
||||
return;
|
||||
}
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < n; i++) {
|
||||
if (isFit(used, level, i)) {
|
||||
used[level][i] = true;
|
||||
backtracking(n, level + 1, used);
|
||||
used[level][i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isFit(boolean[][] used, int row, int col) {
|
||||
|
||||
//看看列
|
||||
for (int i = 0; i < row; i++) {
|
||||
if (used[i][col]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//看看行,行不用看,一定不会
|
||||
//看看斜边
|
||||
for (int i = row - 1, j = col - 1, k = col + 1; i >= 0; i--, j--, k++) {
|
||||
if (j >= 0 && used[i][j]) {
|
||||
return false;
|
||||
}
|
||||
if (k < used.length && used[i][k]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 代码随想录式,不用一个一个append速度提高
|
||||
* 速度击败92.55%,内存击败48.62% 2ms
|
||||
*/
|
||||
List<List<String>> res = new ArrayList<>();
|
||||
|
||||
public List<List<String>> solveNQueens1(int n) {
|
||||
char[][] chessboard = new char[n][n];
|
||||
for (char[] c : chessboard) {
|
||||
Arrays.fill(c, '.');
|
||||
}
|
||||
backTrack(n, 0, chessboard);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
public void backTrack(int n, int row, char[][] chessboard) {
|
||||
if (row == n) {
|
||||
res.add(Array2List(chessboard));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int col = 0;col < n; ++col) {
|
||||
if (isFitWithChar(chessboard,row, col)) {
|
||||
chessboard[row][col] = 'Q';
|
||||
backTrack(n, row+1, chessboard);
|
||||
chessboard[row][col] = '.';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public List Array2List(char[][] chessboard) {
|
||||
List<String> list = new ArrayList<>();
|
||||
|
||||
for (char[] c : chessboard) {
|
||||
list.add(String.copyValueOf(c));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public boolean isFitWithChar(char[][] used, int row, int col) {
|
||||
|
||||
//看看列
|
||||
for (int i = 0; i < row; i++) {
|
||||
if (used[i][col]=='Q') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//看看行,行不用看,一定不会
|
||||
//看看斜边
|
||||
for (int i = row - 1, j = col - 1, k = col + 1; i >= 0; i--, j--, k++) {
|
||||
if (j >= 0 && used[i][j]=='Q') {
|
||||
return false;
|
||||
}
|
||||
if (k < used.length && used[i][k]=='Q') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 官方最快 0ms
|
||||
* 通过大量的位运算,和Arrays.fill加快速度
|
||||
* @param n
|
||||
* @return
|
||||
*/
|
||||
public List<List<String>> solveNQueens2(int n) {
|
||||
List<List<String>> ans=new ArrayList<>();
|
||||
int[] queen=new int[n];
|
||||
Arrays.fill(queen,-1);
|
||||
backtrack(ans,n,queen,0,0,0,0);
|
||||
return ans;
|
||||
}
|
||||
public void backtrack(List<List<String>> ans,int n,int[] queen,int rows,int col,int diagonal1,int diagonal2){
|
||||
if(rows==n){
|
||||
List<String> list=new ArrayList<>();
|
||||
for(int i=0;i<n;i++){
|
||||
char[] row=new char[n];
|
||||
Arrays.fill(row,'.');
|
||||
row[queen[i]]='Q';
|
||||
list.add(new String(row));
|
||||
}
|
||||
ans.add(list);
|
||||
|
||||
}else{
|
||||
int available=((1<<n)-1) & (~(col | diagonal1 | diagonal2));
|
||||
while(available!=0){
|
||||
int position=available&(-available);
|
||||
available=available & (available-1);
|
||||
queen[rows]=Integer.bitCount(position-1);
|
||||
backtrack(ans,n,queen,rows+1,position|col,(position|diagonal1)<<1,(position|diagonal2)>>1);
|
||||
queen[rows]=-1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue