栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

子集生成算法

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

子集生成算法

本文介绍生成一个集合子集的两种常见算法,借此从中深入理解搜索问题中常见的两种思路。

递归回溯 思路

对于集合中的每个元素,我们都有选择和不选择两种处理方式,这种思路类似于二叉树的遍历,每种情况都向下衍生出两种情况,最终当遍历到下标 index = nums.size() 时,将生成的子集保存。

由于此处我们使用一个数组的引用来保存子集元素,因此在递归回溯时,我们需要手动将上一步中加入添加的元素去除,来回溯到该元素未被选择的状态。

代码
class Solution {
private:
	std::vector> Sets;
	void search(std::vector& subset, std::vector& nums, int index) {
		if (index == nums.size()) {
			Sets.emplace_back(subset);
			return;
		}
		subset.emplace_back(nums[index]);
		search(subset, nums, index + 1);
		subset.pop_back();
		search(subset, nums, index + 1);
	}
public:
	std::vector> getSubset(std::vector& nums) {
		std::vector subset;
		search(subset, nums, 0);
		return Sets;
	}
};
状态压缩 思路

我们知道,一个集合的非空子集个数为 2n - 1,因此可以将子集状态表示为一个范围在 [1, 2n] 的二进制数。

二进制数位 ai 若为 0,表示第 i 位未被选中;若为 1,表示第 i 位被选中。而要分析一个压缩的状态,即获取表示该状态二进制数各位的值,可以运用位运算的操作。由于一个二进制数和 1 进行按位与(&)操作得到的结果将只由该数的最低位决定,如果最低位为 0,则运算结果为 0,否则为 1. 由此可以想到,将一个状态数依次右移 n 位得到一个以 an 结尾的二进制数,再将该二进制数和 1 进行按位与得到 an 的值。依次遍历所有的右移步数得到该状态的所有信息。

代码
class Solution {
private:
	std::vector> Sets;
public:
	std::vector> getSubset(std::vector& nums) {
		int n = nums.size();
		std::vector subset;
		for (int i = 1; i <= (1 << n); ++i) {
			subset.clear();
			for (int j = 0; j < n; ++j) {
				int isChoosed = i >> j & 1;
				if (isChoosed)
					subset.emplace_back(nums[j]);
			}
			Sets.emplace_back(subset);
		}
		return Sets;
	}
};
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/767840.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号