位运算(2)-- 集合中的位运算
来源:互联网 发布:淘宝客服要开通管理 编辑:程序博客网 时间:2024/06/16 11:15
一、基本概念
当集合元素个数较少时,可以用二进制来表示。集合{0, 1, ..., n - 1}
的子集S
可以用如下方法编码成整数:
本质就是用每一个二进制位来表示某个元素是否出现。
- 空集
ϕ :0
- 只含有第
i
个元素的集合{i}
:1 << i
- 含有全部
n
个元素的集合{0, 1, ..., n - 1}
:(1 << n) - 1
- 判断第
i
个元素是否属于集合S
:S >> i & 1
,orS & (1 << i)
- 向集合中加入第
i
个元素S U {i}
:S | 1 << i
- 向集合中去除第
i
个元素S \ {i}
:S & ~(1 << i)
- 集合
S
和T
的并集S∪T :S | T
- 集合
S
和T
的交集S∩T :S & T
- 枚举全集
S
的所有子集:for(int s = 0; s < (1 << n); s++) {/* 处理子集 */}
二、固定集合的子集遍历
问题:给定一个含有若干元素的集合s
(s是一个二进制数),枚举该集合的所有子集,含有n个元素的集合共有
分析:找到s
中1的个数和位置,然后通过删除若干个1来获得s
的所有子集。为了获得所有的子集可能需要对之前删掉的1进行二次访问,可以通过和原始集合s
进行与操作实现对之前删掉的1的二次访问。伪代码如下:
int subset = s;do{ // 处理子集 subset = (subset - 1) & s;}while(subset != s); // 当subset为-1的时候说明所有的子集已经遍历完
三、集合的K元素子集
问题:遍历一个集合的所有k
元素子集。例如,含有4个元素的所有子集为:00001111->00010111->00011011->...->11110000
分析:分四步解决:以00010111 --> 00011011
为例
1. 求出从最低位的1开始的连续的1的区间 (00010111 --> 00000111
)
2. 将此区间全部变为0,并将区间左侧的那个0变为1 (00010111 --> 00011000
)
3. 将第1步取出的区间右移,直到剩下的1的个数减少一个 (00000111 --> 00000011
)
4. 将第2步和第3步的结果异或 (00011000 | 00000011 = 00011011)
伪代码描述:
int comb = (1 << k) - 1; // 最小的 k 元素子集while(comb < (1 << n)){ // 处理子集 /* 得到下一个子集 */ int x = comb & -comb; // x 表示最低位1的位置 int y = comb + x; // y 表示第2步操作的结果 comb = (((comb & ~y) / x) >> 1) | y;}
python代码
#!/usr/bin/python# -*- coding: utf-8 -*-def subset(k, n): comb = (1 << k) - 1 while comb < (1 << n): print("next set: ", comb, bin(comb)[2:]) x = comb & -comb y = comb + x comb = ((int((comb & ~y) * 1.0 / x)) >> 1) | ysubset(4, 8)
四、子集生成
问题:给定一个集合,枚举所有可能的子集。
实现:
// 枚举子集for(int s = 0; s < (1 << n); ++s){ // 输出子集S对应的各个元素 for(int i = 0; i < n; ++i){ if(s & (1 << i)) // or (s >> i) & 1 printf("%d ", i + 1); } printf("\n");}
1 0
- 位运算(2)-- 集合中的位运算
- 位运算(2)
- 位运算(2)
- 位运算中的左移右移运算
- 位运算中的符号运算
- Java 中的位运算
- JAVA 中的位运算
- Java 中的位运算
- C# 中的位运算
- C#中的位运算
- java中的位运算
- Java 中的位运算
- Java 中的位运算
- JAVA中的位运算
- Java中的位运算
- Android中的位运算
- Java 中的位运算
- JAVA中的位运算
- Android开发——减小APK大小
- linux read 用法
- Android Studio中关联SVN进行版本控制(三)如何更改文件名
- Leetcode之 largest divisible set
- Java -- 常用的JNI接口函数简介(一)
- 位运算(2)-- 集合中的位运算
- swift 当需要改变cell的内容布局时
- 123452345678
- 小方法1——CountChar--统计一个字符串中每个字符出现的次数
- Hibernate关联映射之一对多,多对一以及双向一对多
- 量化分析师的Python日记
- lintcode178. graph valid tree 图是否是树
- POJ 1753 Flip Game 棋盘状态搜索
- JUnit4学习笔记