目录

基础复习

回溯法

leetcode 78 子集

leetcode 90 子集 II

leetcode 40 组合总和 II

leetcode 22 括号生成

leetcode 51 N皇后

leetcode 473 火柴拼正方形


回家了,复习不能停!!!加油!!!    

基础复习

回溯法

leetcode 78 子集

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

输入: nums = [1,2,3]
输出:
[[3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], []]

思路:

方法一——回溯法

class Solution {
public:void generate(int i, vector<int>&nums, vector<int>&item, vector<vector<int>>&result){if(i>=nums.size()) return;item.push_back(nums[i]);result.push_back(item);//放i的结果generate(i+1,nums,item,result);item.pop_back();//不放i的结果generate(i+1, nums, item, result);}vector<vector<int>> subsets(vector<int>& nums) {vector<vector<int>>result;vector<int>item;result.push_back(item);generate(0,nums,item,result);return result;}
};

方法二——位运算

每个元素都有放和不放两种决策。因此一共八种情况。针对每一种情况,依次判断每个元素是否在该集合中出现。

class Solution {
public:vector<vector<int>> subsets(vector<int>& nums) {vector<vector<int>>result;int all_set=1<<nums.size(); //1<<n 的值为 2的n次幂for(int i=0; i<all_set; i++){ //i代表集合中的各个情况vector<int>item;//A  100  即 1<<2, B  010 即 1<<1, C 001 即 1<<0 for(int j=0; j<nums.size(); j++){if(i&(1<<j)){ //判断当前元素是否在i集合中出现item.push_back(nums[j]);}}result.push_back(item);}        return result;}
};

leetcode 90 子集 II

给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

输入: [1,2,2]
输出:
[ [2], [1], [1,2,2], [2,2], [1,2], []]

思路:

使用上题的方法获取所有子集之后,使用set去重。

class Solution {
public:vector<vector<int>> subsetsWithDup(vector<int>& nums) {sort(nums.begin(),nums.end());vector<vector<int>>result;int all_set=1<<nums.size(); //1<<n 的值为 2的n次幂for(int i=0; i<all_set; i++){ //i代表集合中的各个情况vector<int>item;//A  100  即 1<<2, B  010 即 1<<1, C 001 即 1<<0 for(int j=0; j<nums.size(); j++){if(i&(1<<j)){ //判断当前元素是否在i集合中出现item.push_back(nums[j]);}}result.push_back(item);}        //利用set去重set<vector<int>>con;for(auto i : result){con.insert(i);}result.clear();for(auto i :con){result.push_back(i);}return result;}
};

leetcode 40 组合总和 II

给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用一次。

说明:

  • 所有数字(包括目标数)都是正整数。
  • 解集不能包含重复的组合。

示例 1:

输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[ [1, 7], [1, 2, 5], [2, 6], [1, 1, 6] ]

示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[ [1,2,2], [5] ]

思路:

将数组排序,然后分别考虑每一个元素是否加入到集合,每个元素都有加入集合和不加入集合这两种可能。用一个变量sum来累计集合中的各个元素的总和。使用set来进行去重。

class Solution {
public:void generate(int i, vector<int>&nums, vector<vector<int>>&result, vector<int>&item, set<vector<int>>&res_set, int sum, int target){if(i>=nums.size()||sum>target) return;//剪枝//sum为当前自己item中的元素和sum+=nums[i];item.push_back(nums[i]);if(target==sum && res_set.find(item)==res_set.end()){result.push_back(item);res_set.insert(item);}//放i且sum小于target的时候generate(i+1, nums, result, item, res_set, sum, target);sum-=nums[i];item.pop_back();//不i且sum小于target的时候generate(i+1, nums, result, item, res_set, sum, target);      }vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {sort(candidates.begin(), candidates.end());set<vector<int>>res_set;vector<int>item;vector<vector<int>>result;generate(0, candidates, result, item, res_set, 0, target);return result;}
};

leetcode 22 括号生成

给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。

例如,给出 = 3,生成结果为:

[ "((()))", "(()())", "(())()", "()(())", "()()()" ]

思路:

n组括号,字符串长度为2的n次幂,字符串中每个字符都有两种选择,“(”或者“)”。因此有2*(2的n次幂种)  种可能。

放置的时候,如果当前右括号的数量超过左括号,则该组合不合法。

class Solution {
public:vector<string> generateParenthesis(int n) {vector<string>result;generate("", n, n, result);return result;}
private:void generate(string item, int left, int right, vector<string>&result){//左右括号都放完了,此时递归结束if(left==0 && right==0){result.push_back(item);return;}if(left){generate(item+'(',left-1, right, result);}//保证括号的合法性if(left<right){generate(item+')', left, right-1, result);}}
};

leetcode 51 N皇后

皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。

上图为 8 皇后问题的一种解法。

给定一个整数 n,返回所有不同的 皇后问题的解决方案。

每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。

示例:

输入: 4
输出: [[".Q..",  // 解法 1"...Q","Q...","..Q."],["..Q.",  // 解法 2"Q...","...Q",".Q.."]
]
解释: 4 皇后问题存在两个不同的解法。

思路:

四个皇后的回溯摆放过程:

   

class Solution {
public:void put_down_the_queen(int x, int y, vector<vector<int>>&mark){//方向数组,分别代表 左,右,下,上,左下,左上,右下和右上static const int dx[]={-1,1,0,0,-1,-1,1,1};static const int dy[]={0,0,-1,1,-1,1,-1,1};mark[x][y]=1;//皇后的位置(x,y)//给八个位置都打上1,标记为后续不能放置皇后的位置for(int i=1; i<mark.size(); i++){for(int j=0; j<8; j++){int new_x=x+i*dx[j];int new_y=y+i*dy[j];//判断是否在棋盘内if(new_x>=0 && new_x <mark.size() &&new_y>=0 && new_y<mark.size()){//标记皇后的八个方向mark[new_x][new_y]=1;}}}}//参数k代表第k个皇后,某次的存出结果存入location中,最终结果存入resultvoid generate(int k, int n, vector<string>&location, vector<vector<string>>&result, vector<vector<int>>&mark){//完成了所有皇后的放置任务if(k==n){result.push_back(location);return;}//按顺序尝试第0到第n-1列for(int i=0; i<n; i++){//说明此位置可以放皇后if(!mark[k][i]){//记录回溯前的mark镜像vector<vector<int>>temp_mark=mark;//记录当前皇后位置location[k][i]='Q';//把八个方向做出标记,以后这些位置就不能放皇后了put_down_the_queen(k,i,mark);//考虑第k+1个皇后的放置方式generate(k+1, n, location, result, mark);//说明下一行放置不成功,将mark重置为回溯前的状态mark=temp_mark;//该位置不能放皇后,改为 .location[k][i]='.';}}}vector<vector<string>> solveNQueens(int n) {vector<vector<string>>result;vector<vector<int>>mark;vector<string>location;//初始化一个 n*n的 .  表格for(int i=0; i<n; i++){mark.push_back(vector<int>());for(int j=0; j<n; j++){mark[i].push_back(0);}location.push_back("");location[i].append(n,'.');}//开始考虑各个皇后的放置方式generate(0, n, location, result, mark);return result;                                }
};

leetcode 473 火柴拼正方形

还记得童话《卖火柴的小女孩》吗?现在,你知道小女孩有多少根火柴,请找出一种能使用所有火柴拼成一个正方形的方法。不能折断火柴,可以把火柴连接起来,并且每根火柴都要用到。

输入为小女孩拥有火柴的数目,每根火柴用其长度表示。输出即为是否能用所有的火柴拼成正方形。

示例 1:

输入: [1,1,2,2,2]
输出: true解释: 能拼成一个边长为2的正方形,每边两根火柴。

示例 2:

输入: [3,3,3,3,4]
输出: false解释: 不能用所有火柴拼成一个正方形。

注意:

  1. 给定的火柴长度和在 0 到 10^9之间。
  2. 火柴数组的长度不超过15。

方法一(回溯):

如果传入的数组中的元素个数小于4或者数组总和并不能被4整除,则说明数组拼不出正方形。

调用递归函数,以数组总和的1/4作为目标值,回溯尝试每一个元素。

每一根火柴也有两种情况,放入该边上或者不放入该边上。

class Solution {
public:bool generate(int i, vector<int>&nums, int target, int bucket[]){//说明数组中的元素考察完毕if(i>=nums.size()){return bucket[0]==target && bucket[1]==target && bucket[2]==target && bucket[3]==target;}for(int j=0; j<4; j++){//说明该组合超过了正方形的边长if(bucket[j]+nums[i]>target) continue;bucket[j]+=nums[i];//此次递归的结果返回值为trueif(generate(i+1, nums, target, bucket)){return true;}//此次递归的结果返回值为false,将最后一个元素的值减去,考虑下一个元素的值bucket[j]-=nums[i];}return false;        }bool makesquare(vector<int>& nums) {if(nums.size()<4) return false;int sum=0;for(auto i:nums){sum+=i;}if(sum%4!=0) return false;//从大到小排序sort(nums.rbegin(), nums.rend());int bucket[4]={0};return generate(0, nums, sum/4, bucket);}
};

方法二(位运算):

class Solution {
public:bool makesquare(vector<int>& nums) {if(nums.size()<4) return false;int sum=0;for(auto i:nums)sum+=i;if(sum%4) return false;int target=sum/4;vector<int>ok_subset;vector<int>ok_half;int all=1<<nums.size();//有2的nums.size()种可能性//遍历所有组合情况,找出满足一条边的所有组合for(int i=0; i<all; i++){int sum=0;for(int j=0; j<nums.size(); j++){//如果i情况下与j元素没有交集if(i&(1<<j)){sum+=nums[j];}}if(sum==target){ok_subset.push_back(i);}}//遍历所有一条边的情况,找出所有两条边没有交集的组合for(int i=0; i<ok_subset.size(); i++){for(int j=i+1; j<ok_subset.size(); j++){if((ok_subset[i] & ok_subset[j])==0){ok_half.push_back(ok_subset[i] | ok_subset[j]);}}}//遍历所有的两条边没交集的情况,找出四条边没交集的组合,即为我们要找的结果for(int i=0; i<ok_half.size(); i++){for(int j=0; j<ok_half.size(); j++){//求 & 为 0 ,说明没有交集if((ok_half[i] & ok_half[j])==0){return true;}}}return false;}
};

分门别类刷leetcode——递归和回溯搜索(C++实现)相关推荐

  1. 分门别类刷leetcode——高级数据结构(字典树,前缀树,trie树,并查集,线段树)

    目录 Trie树(字典树.前缀树)的基础知识 字典树的节点表示 字典树构造的例子 字典树的前序遍历 获取字典树中全部单词 字典树的整体功能 字典树的插入操作 字典树的搜索操作 字典树的前缀查询 字典树 ...

  2. 分门别类刷题总结列表 C++ 实现

     目录 输入输出 leetcode 牛客网 算法训练营 SQL shell编程 零七八碎 买的课 真题 输入输出 1 牛客刷题输入输出总结 2 记录各个七七八八的输入 持续更新中 leetcode 1 ...

  3. 【C++】【学习笔记】【递归与回溯问题详解与例题】排列问题;组合问题;二维平面回溯;flood fill问题;搜索问题(八皇后);

    目录 七.递归和回溯 1.回溯 2.回溯应用 - 排列问题 2.回溯应用 - 组合问题 3.回溯应用 - 二维平面 4.回溯应用 - floodfill算法 问题 4.回溯应用 - 搜索问题 - 八皇 ...

  4. ​LeetCode刷题实战81:搜索旋转排序数组 II

    算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试.所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 ! 今天和大家 ...

  5. LeetCode算法题14:递归和回溯2

    文章目录 前言 一.全排列II 仿照全排列(n 叉树) 剪枝(去掉重复的结果) 二.组合总和 一.初始解法(n 叉树): 1,采用 Set 去重 2,在递归搜索的时候去重(推荐解法) 初始解法的遍历过 ...

  6. 机器学习 KD树_递归_回溯_搜索(matlab实现)

    文章目录 思路 效果 待优化 代码 mian Kd_Tree_Create recursive Kd_Tree_Search Kd_Tree_Recall_Search 思路 第一个版本:链接 KD树 ...

  7. LeetCode算法总结-回溯法与深度优先搜索

    转载自  LeetCode算法总结-回溯法与深度优先搜索 回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退 ...

  8. java开发有必要刷leetcode吗_刷 leetcode 需要哪些基础?

    首先要知道 基础的数据结构:数组.字符串.树.堆.栈.队列.哈希表 基础的算法: 枚举遍历, 二分查找,递归,回溯 明白基础的数据结构之后,我们可以发现 leetcode上已经做好了分类, 首先我们要 ...

  9. 手把手带你刷Leetcode力扣 学习总结

    文章目录 1. 总体规划 2. 算法复杂度 2.1 时间复杂度 2.2 空间复杂度 3. 数据结构 3.1 数组[Array] 3.1.1 Python常用操作 3.1.2 Java常用操作 3.1. ...

  10. C++:刷LeetCode踩过的坑

    C++:刷LeetCode踩过的坑 最近在刷Leetcode的时候踩了不少坑,这里列一下提醒自己以后注意. 循环体的条件部分,虽然<C++Primer>说以!=做判断,用各种类型的size ...

最新文章

  1. python解压_python解压缩
  2. GTK+图形化应用程序开发学习笔记
  3. labview将产生数据存入数组 并保存成Excel
  4. 【Linux】一步一步学Linux——ssh-copy-id命令(180)
  5. ​​公众平台测试账号 开通 配置
  6. 虚拟机安装SQLService启用windows功能NetFx3时出错
  7. MongoDB 下载和安装
  8. JAVA子类与继承 实验实列
  9. html5学习开发指南
  10. TCP协议客户端与服务器端一般的通信过程
  11. 从蚂蚁上市看阿里,几点随想
  12. 手机信号不好?真不是套餐原因!4招教你搞定!
  13. Centos下如果是二进制文件,编辑是文本,后缀是sh也无法执行
  14. pandas的行列获取/pandas iloc和loc的使用/如何获取pandas的行和列
  15. 我的理想计算机作文300字,我的理想作文300字(精选12篇)
  16. 在线加密解密网站大全(更新ing)
  17. jQuery获取和计算对象(object)的长度
  18. 图片base64转码,本地和网络图片均可,类对象转map,类对象转键值对字符串
  19. “新角度”学习微积分:阿基米德是如何称出球的体积的?
  20. Server2008 R2上安装 .NetFramework 4.7失败

热门文章

  1. Hdu 1240 Asteroids题解
  2. java pem 签名_如何在Java中验证PEM格式证书
  3. 【降维打击】解决加密视频录屏问题
  4. 三角形周长最短问题_三角形周长最短的动点问题
  5. 计算机组成原理--数制与编码(校验码,CRC,汉明码详解)
  6. 五大数据统计分析软件
  7. 光纤跳线接口_2分钟让你搞懂跳线架和配线架的区别
  8. 【UI设计】零基础带你入门UI设计
  9. Element.closest() 兼容IE
  10. 超有趣的Python实战:将图片转成像素风~