leecode更新

This commit is contained in:
markilue 2023-02-03 14:03:30 +08:00
parent 5317d93f39
commit 1104f87ef2
3 changed files with 409 additions and 1 deletions

View File

@ -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);
}
}

View File

@ -17,7 +17,7 @@ import java.util.*;
* 每一种解法包含一个不同的 n 皇后问题 的棋子放置方案该方案中 'Q' '.' 分别代表了皇后和空位 * 每一种解法包含一个不同的 n 皇后问题 的棋子放置方案该方案中 'Q' '.' 分别代表了皇后和空位
* @Version: 1.0 * @Version: 1.0
*/ */
public class SolveNQueens { public class T13_1_SolveNQueens {
@Test @Test
public void test() { public void test() {

View File

@ -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;
}
}
}
}