C/C++ 全排练中的回溯算法

回溯算法:适用于不重复的排列组合

题目1:

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例:
在这里插入图片描述

void backtrack(vector<vector<int>>& res, vector<int>& output, int first, int len) {
   // 所有数都填完了
   if (first == len) {
       res.emplace_back(output);
       return;
   }
   for (int i = first; i < len; ++i) { //从first开始而不是first+1开始是因为,第一个与第一个交换表示第一个被使用,即排序数组第一个元素是原来第一个元素,是有意义的
       // 动态维护数组
       swap(output[i], output[first]);
       // 继续递归填下一个数
       backtrack(res, output, first + 1, len);
       // 撤销操作
       swap(output[i], output[first]);
   }
}
//0 1 2
//b((012),0)
//b((012),1),                                                      b((102),1)                                                b((210),1)
//b((012),2)  b((021),2)                                           b((102),2)   b((120),2)                                   b((210),2) b((201),2)

vector<vector<int>> permute(vector<int>& nums) {
   vector<vector<int> > res;
   backtrack(res, nums, 0, nums.size());
   return res;
}

算法的思想为:
从前到后一直不重复的换,如0123
先让0分别和0123互换(0与0互换代表初始状态,也是一种状态,因此有意义)产生0123,1023,2103,3120四种情况。
0是第一位,换过了,因此从第二层递归第二位开始换:
如0123从1开始换:产生0123,0213,0321
第三层递归从第三个数开始换:
如0123从2开始换:产生0123,0132
最后一层递归first=len,因此不用换,到此为止,填充结果:0123,0132
因此共432=24种情况。
情况公式为 n!

题目2:

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

在这里插入图片描述
题目来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/combination-sum

void add(vector<vector<int>>& result, vector<int>& onerst, vector<int>& candidates, int target, int posi,int left) {  //[2,3,6,7],  7
	if (posi >= candidates.size()) {
		return;
	}
	if (left == candidates[posi]) {
		onerst.push_back(candidates[posi]);
		result.push_back(onerst);
		onerst.pop_back(); //注意无论何时插入数据都要记得弹出
        result;
	}
	if (left > 0) {  //不能用else if ,因为即便插入当前数据已经满足要求,也不能保证不插入这个数据不会有其他满足的情况
		add(result, onerst, candidates, target, posi + 1, left);
		onerst.push_back(candidates[posi]);
		add(result, onerst, candidates, target, posi, left-candidates[posi]);
		onerst.pop_back(); //注意无论何时插入数据都要记得弹出
	}

}

vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
	vector<vector<int>> result;
	vector<int> onerst;
	add(result, onerst, candidates, target, 0, target);
	return result;
}

算法思想同上:
1,注意每一步数据插入都会影响之后数据,
2,注意插入数据后记得弹出
3,注意考虑所有情况

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值