算法入门到进阶(三)——搜索技术(子集生成和组合问题)
2023-09-11 14:18:26 时间
前言
上一篇博客中,我们求10个数的排列问题中,如果不需要输出全排列,而是输出组合,即子集(子集内部的元素是没有顺序的),那么该如何做呢?
从以前我们所学的知识中,一个包含n个元素的集合,它的子集有2^n个。
用二进制的概念进行对照是最直观的
例如n=3的集合{a1,a2,a3},它的子集和二进制的对应关系如下
空集:0 0 0
a1: 1 0 0
a2: 0 1 0
a3: 0 0 1
.
.
.
a1,a2,a3:1 1 1
所以,每个子集对应一个二进制数,这个二进制数的每一个都对应这个子集中的某个元素,而且子集中的元素是没有顺序的。
从上面的对应表也可以理解为什么子集的数量是2^n个,因为所有二进制数的总个数是2 ^n。
案例1:打印n位二进制数的所有子集
源码
#include<iostream>
using namespace std;
void print_subset(int n) {
for (int i = 0; i < (1 << n ); i++) {//所以一共就是2^n个子集
//i:0 ~ 2^n,,每个i的二进制数都对应一个子集,一次打印一个子集,最后得到所有子集
for (int j = 0; j <n; j++) {//将1和i的n位中的每一位做与运算,逐个检查
if (i & (1 << j)) {
cout <<"1 ";
}
else {
cout << "0 ";
}
}
cout << endl;
}
}
int main() {
int n;
cout << "n:";
cin >> n;
print_subset(n);
system("pause");
return 0;
}
运行结果
分析
回到上一篇博客的问题3
题目
打印n个数中任意m个数的组合。
思路
对照子集生成的二进制方法,已经知道一个子集对应一个二进制数。那么一个有k个元素的子集,它对应的二进制数中有k个1。所以,问题就转化为查找1的个数为k的二进制数,这些二进制数,就是需要打印的子集。
那么如何判断二进制数中1的个数为k,这里和大家分享一个新方法,就是每次消除最后一个1 公式: kk=kk & (kk-1)。每经过一次这样的与运算,原始数据就少一个1.
如1011
1011 & (1011-1)=1010; 少一个1
1010 & (1010-1)=1000;再少一个1
1000 & (1000-1)=0000; 又少一个1
所以三次操作下来,结果为0,那么原来的数值就有3个1.
源码
#include<iostream>
using namespace std;
//第一步就是生成n个数的所有子集
void print_set(int n, int m) {//
for (int i = 0; i < (1 << n); i++) {//生成所有子集数
int num = 0;
int k = i;
while (k) { //第二步,获取1的个数
k &= (k - 1);
num++;
}
if (num == m) {//如果有m个1,就是一个组合
for (int j = 0; j < n; j++) {//将这个结果i的每一位答应出来
if (i & (1 << j)) {
cout << "1 ";
}
else {
cout << "0 ";
}
}
}
cout << endl;
}
}
int main() {
int n, m;
cout << "n m:";
cin >> n >> m;
print_set(n, m);
system("pause");
return 0;
}
运行结果
分析
总结
排列和组合的区别就是,排列是有序的,组合是无序的
1 2 3, 3 2 1对组合是一样的,对排列就不一样。
同时大家记住这个找1的个数方法哦,在很多时候,用起来都是很好的。
下一篇博客我们分析 BFS(广度优先算法)和队列
相关文章
- Java实现 LeetCode 813 最大平均值和的分组 (DFS+DP记忆化搜索)
- Java实现 LeetCode 235 二叉搜索树的最近公共祖先
- Java实现 LeetCode 99 恢复二叉搜索树
- LIntcode---将二叉搜索树转成较大的树
- Python排序搜索基本算法之归并排序实例分析
- python code practice(二):KMP算法、二分搜索的实现、哈希表
- SAP Cloud for Customer根据模型某字段进行OData的搜索操作
- SAP Cloud for Customer的Opportunity搜索前台实现原理
- Atitit 搜索的艺术 目录 1. 索引基础2 1.1. 单词-文档矩阵2 1.2. 倒排索引基本概念3 2. 建立索引4 2.1. 两遍文档遍历法(2-Pass In-Memory In
- DL之模型调参:深度学习算法模型优化参数之对深度学习模型的超参数采用网格搜索进行模型调优(建议收藏)
- NLP之TEA之NB/GBT:基于朴素贝叶斯(count/tfidf+网格搜索+4fCrva)、梯度提升树(w2c+网格搜索+4fCrva)算法对IMDB影评数据集进行文本情感分析(情感二分类预测)
- 基于粒子群和麻雀搜索的LMS自适应滤波算法 - 附代码
- 基于混沌搜索策略的鲸鱼优化算法-附代码
- 一种全局搜索策略的鲸鱼优化算法-附代码
- 启发式算法(蒙特卡洛算法和差分进化算法)解决设计空间搜索问题
- 算法dfs——二叉搜索树中最接近的值 II
- elasticsearch 索引搜索和索引性能优化配置——思路:去掉不必要的数据,减小数据的磁盘空间占用,同时提升性能
- Lucene in action 笔记 term vector——针对特定field建立的词频向量空间,不存!不会!影响搜索,其作用是告诉我们搜索结果是“如何”匹配的,用以提供高亮、计算相似度,在VSM模型中评分计算
- 数据结构与算法_29 _ 堆的应用:如何快速获取到Top 10最热门的搜索关键词