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)的更多相关文章

  1. Leetcode之回溯法专题-77. 组合(Combinations)

    Leetcode之回溯法专题-77. 组合(Combinations)   给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合. 示例: 输入: n = 4, k = 2 输 ...

  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 ...

  3. Leetcode——回溯法常考算法整理

    Leetcode--回溯法常考算法整理 Preface Leetcode--回溯法常考算法整理 Definition Why & When to Use Backtrakcing How to ...

  4. 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 ...

  5. LeetCode No.76,77,78

    No.76 MinWindow 最小覆盖子串 题目 给你一个字符串 S.一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串. 示例 输入: S = "ADOBECODEB ...

  6. N-Queens And N-Queens II [LeetCode] + Generate Parentheses[LeetCode] + 回溯法

    回溯法 百度百科:回溯法(探索与回溯法)是一种选优搜索法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步又一次选择,这样的走不通就退回再走的技术为回溯法 ...

  7. Leetcode回溯相关题目Python实现

    1.46题,全排列 https://leetcode-cn.com/problems/permutations/ class Solution(object): def permute(self, n ...

  8. 【LeetCode回溯算法#extra01】集合划分问题【火柴拼正方形、划分k个相等子集、公平发饼干】

    火柴拼正方形 https://leetcode.cn/problems/matchsticks-to-square/ 你将得到一个整数数组 matchsticks ,其中 matchsticks[i] ...

  9. Leetcode 回溯法 典型例题

    那些要求列举所有的情况,或者说所有的情况都要探讨一下的例题,一般都可以考虑回溯法. 当遇到一个可以用到回溯法的时候需要按照如下步骤进行: 1.确定问题一个可以用到回溯法的时候需要按照如下步骤进行: 1 ...

  10. LeetCode 回溯法 别人的小结 八皇后 递归

    #include <iostream> #include <algorithm> #include <iterator> #include <vector&g ...

随机推荐

  1. 推荐免费的svn空间(SVN代码托管)

    推荐免费的svn空间(SVN代码托管) 最近研究了国内和国外的免费svn空间,SVN代码托管,SVN在线,代码托管中心,有所心得. 1.http://www.svn999.com/ [推荐]国内的,免 ...

  2. [最佳实践]配置sshd只允许sftp登录

    sftp 是 Secure File Transfer Protocol 的缩写,即安全文件传送协议,可为传输文件提供一种安全的加密方法. sftp 为 SSH 的一部分,由于这种传输方式使用了加密/ ...

  3. CF1526C2

    与简单版的思路完全一致,只需要改一下范围. 可以去看我简单版本的博客. 题目简化和分析: 给您一个数组,在其中选择若干个数使得: 任意前缀和 \(\ge 0\) 数量尽可能的大 我们可以使用贪心策略, ...

  4. MMKV源码解读与理解

    概述 通过 mmap 技术实现的高性能通用 key-value 组件.同时选用 protobuf 协议,进一步压缩数据存储. 标准 protobuf 不提供增量更新的能力,每次写入都必须全量写入.考虑 ...

  5. 记一次 openSUSE Tumbleweed 下安装 k8s

    出现的问题 因为没有K8s基础的而踩了不少坑. kubeadm kubelet 最好指定版本安装,因为kubelet的版本需要小于等于kubeadm的版本,否则就会报错. 运行 kubeadm ini ...

  6. ASP.NET CORE MVC的一些说明

    1.ASP.NET CORE MVC 是微软公司的Web应用开发框架,结合了MVC架构的高效.简洁等优秀思想并融合了.NET的灵活性. 2.ASP.NET诞生于2002年,当时微软想保持桌面应用程序的 ...

  7. 微信小程序:音乐播放器

    音乐资源使用的是QQ音乐资源.图片资源使用的网易云音乐的专辑图片. HTML: <view class="container"> <div wx:for=&quo ...

  8. Java比赛常用API总结

    1.栈和队列 1.1 栈的常用方法 //1.栈顶插入元素 push(element) //2.返回栈顶元素并弹出栈顶元素 pop() //3.返回栈顶元素但不弹出 peek() //4.清空栈 cle ...

  9. "拍牌神器"是怎样炼成的(一)--- 键鼠模拟之WinAPI

    作为本系列博文的开篇,有必要先做些声明,用于免责.以绝口水: 博文仅围绕已经弃用的.C/S结构的<上海市个人非营业性客车额度竞拍程序>客户端(NetBidClient)进行介绍,对于正在使 ...

  10. Java实现两字符串相似度算法

    1.编辑距离 编辑距离:是衡量两个字符串之间差异的度量,它表示将一个字符串转换为另一个字符串所需的最少编辑操作次数(插入.删除.替换). 2.相似度 计算方法可以有多种,其中一种常见的方法是将编辑距离 ...