回溯
This commit is contained in:
parent
17bbb0f3ed
commit
ed50ebaeff
@ -0,0 +1,246 @@
|
||||
package cn.whaifree.leetCode.BackTracking;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
* @Author whai文海
|
||||
* @Date 2024/2/20 10:29
|
||||
* @注释
|
||||
*/
|
||||
public class LeetCode332difficult {
|
||||
@Test
|
||||
public void test() {
|
||||
List<List<String>> tickets = new ArrayList<>();
|
||||
// 加上这一串 [["JFK","SFO"],["JFK","ATL"],["SFO","ATL"],["ATL","JFK"],["ATL","SFO"]]
|
||||
// tickets.add(new ArrayList<String>() {{
|
||||
// add("JFK");
|
||||
// add("SFO");
|
||||
// }});
|
||||
// tickets.add(new ArrayList<String>() {{
|
||||
// add("JFK");
|
||||
// add("ATL");
|
||||
// }});
|
||||
// tickets.add(new ArrayList<String>() {{
|
||||
// add("SFO");
|
||||
// add("ATL");
|
||||
// }});
|
||||
// tickets.add(new ArrayList<String>() {{
|
||||
// add("ATL");
|
||||
// add("JFK");
|
||||
// }});
|
||||
// tickets.add(new ArrayList<String>() {{
|
||||
// add("ATL");
|
||||
// add("SFO");
|
||||
// }});
|
||||
|
||||
String[][] routes = {
|
||||
{"JFK", "SFO"},
|
||||
{"JFK", "ATL"},
|
||||
{"SFO", "JFK"},
|
||||
{"ATL", "AAA"},
|
||||
{"AAA", "BBB"},
|
||||
{"BBB", "ATL"},
|
||||
{"ATL", "AAA"},
|
||||
{"AAA", "BBB"},
|
||||
{"BBB", "ATL"},
|
||||
{"ATL", "AAA"},
|
||||
{"AAA", "BBB"},
|
||||
{"BBB", "ATL"},
|
||||
{"ATL", "AAA"},
|
||||
{"AAA", "BBB"},
|
||||
{"BBB", "ATL"},
|
||||
{"ATL", "AAA"},
|
||||
{"AAA", "BBB"},
|
||||
{"BBB", "ATL"},
|
||||
{"ATL", "AAA"},
|
||||
{"AAA", "BBB"},
|
||||
{"BBB", "ATL"},
|
||||
{"ATL", "AAA"},
|
||||
{"AAA", "BBB"},
|
||||
{"BBB", "ATL"},
|
||||
{"ATL", "AAA"},
|
||||
{"AAA", "BBB"},
|
||||
{"BBB", "ATL"},
|
||||
{"ATL", "AAA"},
|
||||
{"AAA", "BBB"},
|
||||
{"BBB", "ATL"},
|
||||
{"ATL", "AAA"},
|
||||
{"AAA", "BBB"},
|
||||
{"BBB", "ATL"},
|
||||
{"ATL", "AAA"},
|
||||
{"AAA", "BBB"},
|
||||
{"BBB", "ATL"},
|
||||
{"ATL", "AAA"},
|
||||
{"AAA", "BBB"},
|
||||
{"BBB", "ATL"},
|
||||
{"ATL", "AAA"},
|
||||
{"AAA", "BBB"},
|
||||
{"BBB", "ATL"},
|
||||
{"ATL", "AAA"},
|
||||
{"AAA", "BBB"},
|
||||
{"BBB", "ATL"}
|
||||
};
|
||||
|
||||
|
||||
for (String[] route : routes) {
|
||||
tickets.add(Arrays.asList(route));
|
||||
}
|
||||
|
||||
Solution1 solution = new Solution1();
|
||||
solution.findItinerary(tickets).forEach(
|
||||
list -> {
|
||||
System.out.println(list);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 超时
|
||||
*/
|
||||
class Solution {
|
||||
|
||||
List<String> res = new ArrayList<>();
|
||||
private LinkedList<String> path = new LinkedList<>();
|
||||
boolean[] used = null;
|
||||
public List<String> findItinerary(List<List<String>> tickets) {
|
||||
Collections.sort(tickets, new Comparator<List<String>>() {
|
||||
@Override
|
||||
public int compare(List<String> a, List<String> b) {
|
||||
// 两个字符串比较
|
||||
return a.get(1).compareTo(a.get(1));
|
||||
}
|
||||
});
|
||||
// 最后,会按照目的地进行排序["JFK","SFO"],["JFK","ATL"],会变成["JFK","ATL"],["JFK","SFO"]
|
||||
|
||||
path.add("JFK");
|
||||
used = new boolean[tickets.size()];
|
||||
|
||||
// 1. 字典排序选择
|
||||
// 2. 已经走过的标记
|
||||
backTracking(tickets);
|
||||
return res;
|
||||
}
|
||||
|
||||
public void backTracking(List<List<String>> tickets) {
|
||||
if (path.size() == 1 + tickets.size()) {
|
||||
res = new LinkedList(path);
|
||||
return;
|
||||
}
|
||||
|
||||
int size = tickets.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (!used[i] && path.getLast().equals(tickets.get(i).get(0))) {
|
||||
String target = tickets.get(i).get(1);
|
||||
path.add(target);
|
||||
used[i] = true;
|
||||
|
||||
backTracking(tickets);
|
||||
|
||||
used[i] = false;
|
||||
path.removeLast();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// /**
|
||||
// * 在tickets返回未被use的索引,多个索引进行比较
|
||||
// *
|
||||
// * @param tickets
|
||||
// * @return 在tickets中的索引
|
||||
// */
|
||||
// public int compareAndUnUsed(List<List<String>> tickets, String start) {
|
||||
// int res = -1;
|
||||
// for (int i = 0; i < tickets.size(); i++) {
|
||||
// List<String> aPath = tickets.get(i);
|
||||
// String st = aPath.get(0);
|
||||
// if (start.equals(st) && used[i] == false) {
|
||||
// if (res != -1) {
|
||||
// String target = aPath.get(1);
|
||||
// String beforeRes = tickets.get(res).get(1);
|
||||
// if (!compareBeforeIsBetter(beforeRes, target)) {
|
||||
// res = i;
|
||||
// }
|
||||
// }else {
|
||||
// res = i;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return res;
|
||||
// }
|
||||
//
|
||||
// public boolean compareBeforeIsBetter(String before,String after) {
|
||||
// for (int i = 0; i < 3; i++) {
|
||||
// char be = before.charAt(i);
|
||||
// char af = after.charAt(i);
|
||||
// if (be > af) {
|
||||
// return false;
|
||||
// } else if (be < af) {
|
||||
// return true;
|
||||
// }
|
||||
// // 如果字母相同,比较下一个字母
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
class Solution1 {
|
||||
|
||||
List<String> res = new ArrayList<>();
|
||||
private LinkedList<String> path = new LinkedList<>();
|
||||
boolean[] used = null;
|
||||
public List<String> findItinerary(List<List<String>> tickets) {
|
||||
Collections.sort(tickets, new Comparator<List<String>>() {
|
||||
@Override
|
||||
public int compare(List<String> a, List<String> b) {
|
||||
// 两个字符串比较
|
||||
return a.get(1).compareTo(b.get(1));
|
||||
}
|
||||
});
|
||||
// 最后,会按照目的地进行排序["JFK","SFO"],["JFK","ATL"],会变成["JFK","ATL"],["JFK","SFO"]
|
||||
|
||||
path.add("JFK");
|
||||
used = new boolean[tickets.size()];
|
||||
|
||||
// 1. 字典排序选择
|
||||
// 2. 已经走过的标记
|
||||
backTracking(tickets);
|
||||
return res;
|
||||
}
|
||||
|
||||
public boolean backTracking(List<List<String>> tickets) {
|
||||
if (path.size() == 1 + tickets.size()) {
|
||||
res = new LinkedList(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < tickets.size(); i++) {
|
||||
if (!used[i] && path.getLast().equals(tickets.get(i).get(0))) {
|
||||
String target = tickets.get(i).get(1);
|
||||
path.add(target);
|
||||
used[i] = true;
|
||||
|
||||
if (backTracking(tickets)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
used[i] = false;
|
||||
path.removeLast();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package cn.whaifree.leetCode.BackTracking;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
* @Author whai文海
|
||||
* @Date 2024/2/19 11:01
|
||||
* @注释
|
||||
*/
|
||||
public class LeetCode46 {
|
||||
@Test
|
||||
public void test() {
|
||||
new Solution1().permute(new int[]{1, 2, 3}).forEach(
|
||||
list -> {
|
||||
System.out.println(list);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
class Solution {
|
||||
|
||||
List<List<Integer>> res = new ArrayList<>();
|
||||
List<Integer> path = new ArrayList<>();
|
||||
boolean[] used = null;
|
||||
|
||||
|
||||
public List<List<Integer>> permute(int[] nums) {
|
||||
used = new boolean[nums.length];
|
||||
backTracking(nums);
|
||||
return res;
|
||||
}
|
||||
|
||||
public void backTracking(int[] nums) {
|
||||
|
||||
if (path.size() == nums.length) {
|
||||
res.add(new ArrayList<>(path));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nums.length; i++) {
|
||||
if (used[i] == true) {
|
||||
continue;
|
||||
}
|
||||
used[i] = true;
|
||||
path.add(nums[i]);
|
||||
backTracking(nums);
|
||||
used[i] = false;
|
||||
path.remove(path.size() - 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class Solution1 {
|
||||
|
||||
List<List<Integer>> res = new ArrayList<>();
|
||||
List<Integer> path = new ArrayList<>();
|
||||
|
||||
|
||||
public List<List<Integer>> permute(int[] nums) {
|
||||
backTracking(nums);
|
||||
return res;
|
||||
}
|
||||
|
||||
public void backTracking(int[] nums) {
|
||||
|
||||
if (path.size() == nums.length) {
|
||||
res.add(new ArrayList<>(path));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nums.length; i++) {
|
||||
if (path.contains(nums[i])) {
|
||||
continue;
|
||||
}
|
||||
path.add(nums[i]);
|
||||
backTracking(nums);
|
||||
path.remove(path.size() - 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
126
src/main/java/cn/whaifree/leetCode/BackTracking/LeetCode47.java
Normal file
126
src/main/java/cn/whaifree/leetCode/BackTracking/LeetCode47.java
Normal file
@ -0,0 +1,126 @@
|
||||
package cn.whaifree.leetCode.BackTracking;
|
||||
|
||||
import cn.whaifree.leetCode.model.TreeNode;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
* @Author whai文海
|
||||
* @Date 2024/2/19 16:41
|
||||
* @注释
|
||||
*/
|
||||
public class LeetCode47 {
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
new Solution1().permuteUnique(new int[]{1, 1, 2}).forEach(
|
||||
list -> {
|
||||
System.out.println(list);
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用层的set+路径的bool[]
|
||||
*/
|
||||
class Solution {
|
||||
|
||||
List<List<Integer>> res = new ArrayList<>();
|
||||
List<Integer> path = new ArrayList<>();
|
||||
boolean[] used = null;
|
||||
/**
|
||||
* 给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
|
||||
* 相比46题,不重复
|
||||
* @param nums
|
||||
* @return
|
||||
*/
|
||||
public List<List<Integer>> permuteUnique(int[] nums) {
|
||||
used = new boolean[nums.length];
|
||||
|
||||
backTracking(nums);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public void backTracking(int[] nums) {
|
||||
if (path.size() == nums.length) {
|
||||
res.add(new ArrayList<>(path));
|
||||
return;
|
||||
}
|
||||
|
||||
// 这个set用来对每层进行过滤,每层不能重复
|
||||
// used对每个路径进行过滤,没个路径不会出现同一个index,但有可能多个index都是同一个元素
|
||||
HashSet<Integer> set = new HashSet<>();
|
||||
for (int i = 0; i < nums.length; i++) {
|
||||
if (used[i] == true || set.contains(nums[i])) {
|
||||
continue;
|
||||
}
|
||||
set.add(nums[i]);
|
||||
used[i] = true;
|
||||
path.add(nums[i]);
|
||||
backTracking(nums);
|
||||
used[i] = false;
|
||||
path.remove(path.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用排序+used
|
||||
*/
|
||||
class Solution1 {
|
||||
|
||||
List<List<Integer>> res = new ArrayList<>();
|
||||
List<Integer> path = new ArrayList<>();
|
||||
boolean[] used = null;
|
||||
/**
|
||||
* 给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
|
||||
* 相比46题,不重复
|
||||
* @param nums
|
||||
* @return
|
||||
*/
|
||||
public List<List<Integer>> permuteUnique(int[] nums) {
|
||||
used = new boolean[nums.length];
|
||||
Arrays.sort(nums);
|
||||
|
||||
backTracking(nums);
|
||||
return res;
|
||||
}
|
||||
|
||||
public void backTracking(int[] nums) {
|
||||
if (path.size() == nums.length) {
|
||||
res.add(new ArrayList<>(path));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < nums.length; i++) {
|
||||
// used[i - 1] == false,说明同⼀树层nums[i - 1]使⽤过
|
||||
// 如果同⼀树层nums[i - 1]使⽤过则直接跳过
|
||||
// 一层
|
||||
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
|
||||
continue;
|
||||
}
|
||||
// used[i] == true,说明同⼀树⽀nums[i]使⽤过
|
||||
// 这个路径上被使用过
|
||||
// 一条路径
|
||||
if (used[i]) {
|
||||
continue;
|
||||
}
|
||||
used[i] = true;
|
||||
path.add(nums[i]);
|
||||
backTracking(nums);
|
||||
used[i] = false;
|
||||
path.remove(path.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
113
src/main/java/cn/whaifree/leetCode/BackTracking/LeetCode51.java
Normal file
113
src/main/java/cn/whaifree/leetCode/BackTracking/LeetCode51.java
Normal file
@ -0,0 +1,113 @@
|
||||
package cn.whaifree.leetCode.BackTracking;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @version 1.0
|
||||
* @Author whai文海
|
||||
* @Date 2024/2/20 12:03
|
||||
* @注释
|
||||
*/
|
||||
public class LeetCode51 {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
new Solution().solveNQueens(4).forEach(
|
||||
list -> {
|
||||
for (String s : list) {
|
||||
System.out.println(s);
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
class Solution {
|
||||
List<List<String>> res = new ArrayList<>();
|
||||
|
||||
// 地图
|
||||
char[][] chessMap = null;
|
||||
|
||||
/**
|
||||
* 1. 形成棋盘
|
||||
* 2. 选择点进行填充
|
||||
* 填充后,判断该点上列、斜45、45度角是否有被使用过
|
||||
* - 如果有,回溯到上次递归
|
||||
* - 没有,标记该点Q,去下一行row+1进行填充
|
||||
* @param n
|
||||
* @return
|
||||
*/
|
||||
public List<List<String>> solveNQueens(int n) {
|
||||
chessMap = new char[n][n];
|
||||
for (char[] c : chessMap) {
|
||||
Arrays.fill(c, '.');
|
||||
}
|
||||
backTracking(n, 0);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public void backTracking(int n, int row) {
|
||||
if (row == n) {
|
||||
List<String> element = new ArrayList<>();
|
||||
for (char[] chars : chessMap) {
|
||||
StringBuilder s = new StringBuilder();
|
||||
for (char aChar : chars) {
|
||||
s.append(aChar);
|
||||
}
|
||||
element.add(s.toString());
|
||||
}
|
||||
res.add(element);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int col = 0; col < n; col++) {
|
||||
if (isValid(n, col, row)) {
|
||||
|
||||
chessMap[row][col] = 'Q';
|
||||
backTracking(n, row + 1);
|
||||
// 回溯
|
||||
chessMap[row][col] = '.';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否有效
|
||||
*
|
||||
* @param n n皇后
|
||||
* @param col 列
|
||||
* @param row 行
|
||||
* @return
|
||||
*/
|
||||
public boolean isValid(int n, int col, int row) {
|
||||
// 判断某列是否有被使用过的,其实只要该点往上搜索就可以,下面的必定为.
|
||||
for (int i = 0; i < row; i++) {
|
||||
if (chessMap[i][col] == 'Q') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// 判断45度 该点左上搜索
|
||||
for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
|
||||
// 只要让某个点,不断往斜45度向左上检查就可以
|
||||
if (chessMap[i][j] == 'Q') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// 判断斜45、135度 该点右边上搜索
|
||||
for (int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
|
||||
// 只要让某个点,不断往斜45度向左上检查就可以
|
||||
if (chessMap[i][j] == 'Q') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user