LeetCode 回溯篇(46、77、78、51)
46. 全排列
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
示例:
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
solution1
class Solution {
List<List<Integer>> res = new LinkedList<>();
public List<List<Integer>> permute(int[] nums) {
LinkedList<Integer> track = new LinkedList<>();
backtrack(nums,track);
return res;
}
public void backtrack(int[] nums, LinkedList<Integer> track){
//满足结束条件
if (track.size() == nums.length){
res.add(new LinkedList(track));
return;
}
for (int i = 0; i < nums.length; i++){
if(track.contains(nums[i])) continue;
// 路径选择
track.add(nums[i]);
backtrack(nums,track);
// 撤销选择
track.removeLast();
}
}
}
//回溯模版 遍历一个回溯树
//result = []
// def backtrack(路径, 选择列表):
// if 满足结束条件:
// result.add(路径)
// return
// for 选择 in 选择列表:
// 做选择
// backtrack(路径, 选择列表)
// 撤销选择
77. 组合
给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。
示例:
输入: n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
solution1
class Solution {
private List<List<Integer>> res = new LinkedList<>();
public List<List<Integer>> combine(int n, int k) {
if (k <= 0 || n <= 0) return res;
backtrack(new LinkedList<>(),1, n, k);
return res;
}
public void backtrack(List<Integer> list, int l, int n, int k){
if (list.size() == k){
res.add(new LinkedList<Integer>(list));
}
for (int i = l; i <= n; i++){
list.add(i);
backtrack(list,i+1,n,k); //i+1,不是l+1,不然会重复出现[2,2]的情况
list.remove(list.size()-1);
}
}
}
78. 子集
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
思路
//递归与回溯(试错)
//思想:将大问题分解为小问题/分层 代码:先终止再 大问题分成小问题/当前层和下一层/不断试错
//1回溯 类似于组括号 nums有多少个就有多少层,每一层生成要加入还是不加两个情况
//2回溯 遍历nums,加入该数后进入该数下一位的挑选,到挑选最后一位跳出递归
//3迭代 n的子集=(n-1的子集)加上(n-1的子集和n的并集),代码由空和1开始不断迭代
solution 1 回溯1
class Solution {
public List<List<Integer>> subsets(int[] nums) {
ArrayList ans = new ArrayList();
if(nums == null) return ans;
dfs(ans,nums,new ArrayList<Integer>(),0);
return ans;
}
public void dfs(List<List<Integer>> ans,int[] nums,List<Integer> l,int index){
//终止条件
if (index == nums.length) {
ans.add(new ArrayList(l));// 引用的加入
return;
}
//大问题分成小问题/当前层和下一层/不断试错
dfs(ans,nums,l,index+1);
l.add(nums[index]);
dfs(ans,nums,l,index+1);
//清理当前层 (递归返回给上一层时必须保证list不变)
l.remove(l.size()-1);
}
}
solution2 回溯2
// 套用回溯模版
class Solution {
private List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
List<Integer> list = new LinkedList<>();
if (nums == null || nums.length == 0) return res;
backtrack(list,nums,0);
return res;
}
public void backtrack(List<Integer> list, int[] nums,int level){
res.add(new LinkedList<Integer>(list));
for(int i = level; i < nums.length; i++){
list.add(nums[i]);
backtrack(list,nums,i+1);//必须为i+1,i++先赋值再自增
list.remove(list.size()-1);
}
}
}
solution3 迭代
//时间复杂度为(N*(2^N))生成子集并复制到输出
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> output = new ArrayList();
output.add(new ArrayList<Integer>());
for (int num:nums){
List<List<Integer>> newSubsets = new ArrayList();
for (List<Integer> curr:output) {
newSubsets.add(new ArrayList<Integer>(curr){{add(num);}}); //新建列表的同时加入对象
}
for (List<Integer> curr:newSubsets){
output.add(curr);
}
}
return output;
}
}
51. N皇后
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
上图为 8 皇后问题的一种解法。
给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
示例:
输入: 4
输出: [
[".Q..", // 解法 1
"...Q",
"Q...",
"..Q."],
["..Q.", // 解法 2
"Q...",
"...Q",
".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。
提示:
皇后,是国际象棋中的棋子,意味着国王的妻子。皇后只做一件事,那就是“吃子”。当她遇见可以吃的棋子时,就迅速冲上去吃掉棋子。当然,她横、竖、斜都可走一到七步,可进可退。(引用自 百度百科 - 皇后 )
思路
//回溯1 先填满'.', 递归放q时,计算该点的对角线是否存在q,存在即回溯
//回溯1 对列、主次对角线的点保存起来,主对角线x+y相等,次对角线x-y相等
//hill 山丘 上升 主对角线
//dale 山谷 下降 次对角线
//List<String> curr = new ArrayList<>(Collections.nCopies(n,"...."));新建填满数的list<String>
//Arrays.fill(charArray, '.');新建填满数的char[]
solution1
class Solution {
public List<List<String>> solveNQueens(int n) {
List<List<String>> res = new ArrayList<>();
char[][] curr = new char[n][n];
for (int i =0;i<n;i++){
for(int j = 0;j<n;j++){
curr[i][j] = '.';
}
}
helper(res,curr,0,n);
return res;
}
public void helper(List<List<String>> res,char[][] curr,int col,int n){
if (col == n){
res.add(construt(curr));
return;
}
for(int row=0; row < n; row++){
if (isValid(curr,row,col,n)){
curr[row][col] = 'Q';
helper(res,curr,col+1,n);
curr[row][col] = '.';
}
}
}
public boolean isValid(char[][] curr,int row,int col,int n){
for (int i = 0;i<=col;i ++) {
if (curr[row][i] == 'Q') return false;
if (row-i>=0 && curr[row-i][col-i] == 'Q') return false;
if (row+i<n && curr[row+i][col-i] == 'Q') return false;
}
// for (int i = 0; i<n; i++){
// for(int j = 0;j < col; j++){
// if (curr[i][j] == 'Q' && (row+col == i+j || row-col == i-j || row==i))
// {return false;}
// }
// }
return true;
}
public List<String> construt(char[][] curr){
List<String> list = new ArrayList<>();
for (int i=0;i<curr.length;i++){
String s = new String(curr[i]);
list.add(s);
}
return list;
}
}
solution2 回溯
class Solution {
private Set<Integer> col = new HashSet<>();
private Set<Integer> hill = new HashSet<>();
private Set<Integer> dale = new HashSet<>();
public List<List<String>> solveNQueens(int n) {
List<List<String>> res = new ArrayList<>();
helper(res,new ArrayList<String>(),0,n);
return res;
}
public void helper(List<List<String>> res,List<String> curr,int y,int n){
if (y == n){
res.add(new ArrayList<>(curr));
return;
}
for (int x = 0;x<n;x++){
if (col.contains(x) || hill.contains(y+x) || dale.contains(x-y)) continue;
//确定行char转string
char[] charArray = new char[n];
Arrays.fill(charArray, '.');
charArray[x] = 'Q';
String str = new String(charArray);
curr.add(str);
//攻击距离
col.add(x);
hill.add(x+y);
dale.add(x-y);
//下一层
helper(res,curr,y+1,n);
//清理当前层(回溯)
curr.remove(curr.size()-1);
col.remove(x);
hill.remove(x+y);
dale.remove(x-y);
}
}
}
37. 解数独
编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 '.' 表示。
Note:
给定的数独序列只包含数字 1-9 和字符 '.' 。
你可以假设给定的数独只有唯一解。
给定数独永远是 9x9 形式的。
solution1
class Solution {
public void solveSudoku(char[][] board) {
backtrack(board,0,0);
}
public boolean backtrack(char[][] board, int i, int j){
int m = 9, n = 9;
//换行
if (j == m){
return backtrack(board,i+1,0);
}
//base case
if (i == n){
return true;
}
// 已填数字
if (board[i][j] != '.'){
return backtrack(board,i,j+1);
}
for (char ch = '1'; ch <= '9'; ch ++){
// 不合法数字跳过
if(!isValid(board,i,j,ch)){
continue;
}
board[i][j] = ch;
if(backtrack(board,i,j+1)){
return true;
}
board[i][j] = '.';
}
return false;
}
public boolean isValid(char[][] board, int i,int j, char ch){
for (int p = 0;p < 9;p++){
if (board[p][j] == ch){
return false;
}
if (board[i][p] == ch){
return false;
}
if (board[(i/3)*3 + p/3][(j/3)*3 + p%3] == ch){
return false;
}
}
return true;
}
}
LeetCode 回溯篇(46、77、78、51)的更多相关文章
- Leetcode之回溯法专题-77. 组合(Combinations)
Leetcode之回溯法专题-77. 组合(Combinations) 给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合. 示例: 输入: n = 4, k = 2 输 ...
- 输入一个正数n,输出所有和为n连续正数序列。例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以输出3个连续序列1-5、4-6和7-8。
输入一个正数n,输出所有和为n连续正数序列.例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以输出3个连续序列1-5.4-6和7-8. #define N 15 void findS ...
- Leetcode——回溯法常考算法整理
Leetcode--回溯法常考算法整理 Preface Leetcode--回溯法常考算法整理 Definition Why & When to Use Backtrakcing How to ...
- LeetCode39/40/22/77/17/401/78/51/46/47/79 11道回溯题(Backtracking)
LeetCode 39 class Solution { public: void dfs(int dep, int maxDep, vector<int>& cand, int ...
- LeetCode No.76,77,78
No.76 MinWindow 最小覆盖子串 题目 给你一个字符串 S.一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串. 示例 输入: S = "ADOBECODEB ...
- N-Queens And N-Queens II [LeetCode] + Generate Parentheses[LeetCode] + 回溯法
回溯法 百度百科:回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步又一次选择,这样的走不通就退回再走的技术为回溯法 ...
- Leetcode回溯相关题目Python实现
1.46题,全排列 https://leetcode-cn.com/problems/permutations/ class Solution(object): def permute(self, n ...
- 【LeetCode回溯算法#extra01】集合划分问题【火柴拼正方形、划分k个相等子集、公平发饼干】
火柴拼正方形 https://leetcode.cn/problems/matchsticks-to-square/ 你将得到一个整数数组 matchsticks ,其中 matchsticks[i] ...
- Leetcode 回溯法 典型例题
那些要求列举所有的情况,或者说所有的情况都要探讨一下的例题,一般都可以考虑回溯法. 当遇到一个可以用到回溯法的时候需要按照如下步骤进行: 1.确定问题一个可以用到回溯法的时候需要按照如下步骤进行: 1 ...
- LeetCode 回溯法 别人的小结 八皇后 递归
#include <iostream> #include <algorithm> #include <iterator> #include <vector&g ...
随机推荐
- Java-网络编程(TCP-UDP)
Java-网络编程(TCP-UDP) 网络基础 网络编程最主要的工作就是在发送端把信息通过规定好的协议进行组装包,在接收端按照规定好的协议把包进行解析,从而提取出对应的信息,达到通信的目的.中间最主要 ...
- UVA10054 The Necklace 题解
好可恶一道题,怎么没人告诉我输出之间有空行( 思路是先抽象成图,然后跑一边dfs记录边的前后顺序. 对于不能成环的情况,只需要再开个数组记录度数判断奇点即可. 若存在奇点则break掉,剩下的跑dfs ...
- 【Unity3D】Shader Graph节点
1 前言 Shader Graph 16.0.3 中有 208 个 Node(节点),本文梳理了 Shader Graph 中大部分 Node 的释义,官方介绍详见→Node-Library. ...
- Typora +Picgo 搭建个人笔记
目录 Typora +Picgo 搭建个人笔记 一.Picgo +Github 搭建图床 1.基础设置 2. 将配置导出,方便下次使用 二.Typora:设置 : 1. 基本设置 2. 导出自动提交 ...
- 揭秘计算机指令执行的神秘过程:CPU内部的绝密操作
计算机指令 从软件工程师的角度来看,CPU是执行计算机指令的逻辑机器.计算机指令可以看作是CPU能够理解的语言,也称为机器语言. 不同的CPU能理解的语言不同.例如,个人电脑使用Intel的CPU,苹 ...
- 产品代码都给你看了,可别再说不会DDD(八):应用服务与领域服务
这是一个讲解DDD落地的文章系列,作者是<实现领域驱动设计>的译者滕云.本文章系列以一个真实的并已成功上线的软件项目--码如云(https://www.mryqr.com)为例,系统性地讲 ...
- calico网络异常,不健康
解决calico/node is not ready: BIRD is not ready: BGP not established withxxx calico有一个没有ready,查了一下是没有发 ...
- [ABC276Ex] Construct a Matrix
没有题解,所以来写一篇. Description 构造一个 \(N\times N\) 的矩阵 \(A\),其中 \(A_{i,j}\in {0,1,2}\),要求同时满足 \(Q\) 条限制. 每条 ...
- 【Qt6】列表模型——几个便捷的列表类型
前面一些文章,老周简单介绍了在Qt 中使用列表模型的方法.很明显,使用 Item Model 在许多时候还是挺麻烦的--要先建模型,再放数据,最后才构建视图.为了简化这些骚操作,Qt 提供了几个便捷类 ...
- Hooks的核心原理梳理
我们前端都在诟病专业版,它的组件,它的耦合嵌套之深,它的性能. 我们希望改善,我们认为,如果--就好了. 如果重构就好了,如果技术栈统一就好了,如果有规范就好了. 其实,不用等,我们只要在写代码,就可 ...