文章目录
leetcode刷题笔记13——回溯算法3
子集Ⅱ
题目
示例
思路
代码
public class SubsetsWithDup {
LinkedList<Integer> path = new LinkedList<>();
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
backtrack(nums, 0);
return result;
}
public void backtrack(int[] nums,int start) {
result.add(new ArrayList<>(path));
for(int i = start;i<nums.length;i++) {
if(i>start&&nums[i]==nums[i-1])
continue;//树层去重
path.add(nums[i]);
backtrack(nums, i+1);
path.removeLast();
}
}
}
递增子序列
题目
示例
思路
代码
public class FindSubsequences {
LinkedList<Integer> path = new LinkedList<>();
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
backtrack(nums, 0);
return result;
}
public void backtrack(int[] nums, int start) {
if (path.size() >= 2) {// 子序列的长度要大于2
result.add(new ArrayList<>(path));
}
int[] used = new int[201];
for (int i = start; i < nums.length; i++) {
if ((!path.isEmpty() && nums[i] < path.peekLast()) || used[nums[i] + 100] == 1) {
continue;// 非递增或者有重复的则跳过
}
used[nums[i] + 100] = 1;
path.add(nums[i]);
backtrack(nums, i + 1);
path.removeLast();
}
}
public static void main(String[] args) {
int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 1, 1, 1, 1 };
System.out.println(new FindSubsequences().findSubsequences(nums));
}
}
全排列
题目
示例
思路
代码
public class Permute {
LinkedList<Integer> path = new LinkedList<Integer>();
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> permute(int[] nums) {
backtrack(nums);
return result;
}
public void backtrack(int[] nums) {
if(path.size()==nums.length) {
result.add(new ArrayList<>(path));
}
//下标从0开始
for(int i = 0;i<nums.length;i++) {
if(path.contains(nums[i])) {
continue;
}//path中不能重复
path.add(nums[i]);
backtrack(nums);
path.removeLast();
}
}
}
全排列Ⅱ
题目
示例
思路
代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class PermuteUnique {
LinkedList<Integer> path = new LinkedList<>();
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> permuteUnique(int[] nums) {
Arrays.sort(nums);// 排序
boolean[] used = new boolean[nums.length];
backtrack(nums, used);
return result;
}
public void backtrack(int[] nums, boolean[] used) {
if (path.size() == nums.length) {
result.add(new ArrayList<>(path));
}
for (int i = 0; i < nums.length; i++) {
// used[i - 1] == true,说明同一树枝nums[i - 1]使用过
// used[i - 1] == false,说明同一树层nums[i - 1]使用过
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {
continue;
} // 去重
if (used[i] == false) {
used[i] = true;
path.add(nums[i]);
backtrack(nums, used);
path.removeLast();
used[i] = false;
}
}
}
public static void main(String[] args) {
int[] nums = { 1, 1, 2 };
System.out.println(new PermuteUnique().permuteUnique(nums));
}
}
N皇后
题目
示例
思路
代码
public class SolveNQueens {
List<List<String>> result = new ArrayList<>();
public List<List<String>> solveNQueens(int n) {
char[][] chessboard = new char[n][n];
for (char[] c : chessboard) {
Arrays.fill(c, '.');
}
backtrack(chessboard, 0, n);
return result;
}
public void backtrack(char[][] chessboard, int row, int n) {
if (row == n) {//深度是行
result.add(arrayToList(chessboard));
return;
}
for (int col = 0; col < n; col++) {//层是列
if (place(row, col, n, chessboard)) {
chessboard[row][col] = 'Q';
backtrack(chessboard, row + 1, n);
chessboard[row][col] = '.';
}
}
}
public boolean place(int row, int col, int n, char[][] chessboard) {
for (int i = 0; i < row; i++) {
if (chessboard[i][col] == 'Q')
return false;
}//判断列
for (int i = 0; i < row; i++) {
for (int j = 0; j < n; j++) {
if (chessboard[i][j] == 'Q' && j != col && (Math.abs(i - row) == Math.abs(j - col))) {
return false;
}
}
}//判断对角线
return true;
}
//将棋盘转换为list
public List<String> arrayToList(char[][] chessboard) {
List<String> list = new ArrayList<>();
for (char[] c : chessboard) {
list.add(String.copyValueOf(c));
}
return list;
}
public static void main(String[] args) {
System.out.println(new SolveNQueens().solveNQueens(1));
}
}
参考资料
代码随想录
子集 II
递增子序列
全排列
全排列 II
N 皇后