证明:每次循环执行i = (i-1)&s可以枚举s表示集合的所有子集i

状态压缩:使用二进制数表示一个集合的情况,第i位为1表示第i元素在集合中,为0表示不在集合中。

已知i表示的集合是s表示的集合的子集,枚举s的所有子集i可以写为

cpp 复制代码
for(int i = s; i != 0; i = (i-1)&s){}

证明:每次循环执行i = (i-1)&s可以枚举s表示集合的所有子集i

使用数学归纳法:

  1. 证明:当s只有1位为1时,每次循环执行i = (i-1)&s可以枚举s表示集合的所有子集i
    s只有1位为1,设s为 2 n 2^n 2n,那么s = 10...(n个0)...0
    第一次循环开始,i为s,i = 10...(n个0)...0
    而后求i = (i-1)&s
    i-1 = 01...(n个1)...1
    (i-1)&s = 0...(n+1个0)...0
    即i = 0...(n+1个0)...0
    i已经取到了s的所有子集。
  2. 已知s有k位1时,每次循环执行i = (i-1)&s可以枚举s表示集合的所有子集i,证明:当s有k+1位1时,每次循环执行i = (i-1)&s可以枚举s表示集合的所有子集i。
    因为s有k+1位1,所以s的1的位数大于等于2。
    设s的形式为10...(a个0)...01X...X,X可以是1也可以是0。从第2个1开始,已知到右端共有k位1。当i中1的位数大于等于2时,在执行i = (i-1)&s后,最高位的1都不会变化,会变化的只有1X...X,也就是有k位1的部分。
    已知一个数有k位1时,每次循环执行i = (i-1)&s可以枚举它表示集合的所有子集,把对1X...X枚举到的每个子集加上最高位1表示的元素,就得到了s的包含最高位1表示的元素的所有子集。
    不断执行i = (i-1)&s枚举1X...X的所有子集后,1X...X会变为0, 即i=10...0。
    再次执行i = (i-1)&s,i = 0...(a+1个0)...1X...X,该数字包含k位1,每次循环执行i = (i-1)&s可以枚举它表示集合的所有子集,对1X...X枚举到的每个子集为s不包含最高位1表示的元素的所有子集。
    因此,当s有k+1位1时,每次循环执行i = (i-1)&s可以枚举s表示集合的所有子集i。
相关推荐
全栈凯哥8 分钟前
Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解
java·算法·leetcode·链表
全栈凯哥11 分钟前
Java详解LeetCode 热题 100(27):LeetCode 21. 合并两个有序链表(Merge Two Sorted Lists)详解
java·算法·leetcode·链表
SuperCandyXu15 分钟前
leetcode2368. 受限条件下可到达节点的数目-medium
数据结构·c++·算法·leetcode
Humbunklung32 分钟前
机器学习算法分类
算法·机器学习·分类
Ai多利41 分钟前
深度学习登上Nature子刊!特征选择创新思路
人工智能·算法·计算机视觉·多模态·特征选择
Q8137574602 小时前
中阳视角下的资产配置趋势分析与算法支持
算法
yvestine2 小时前
自然语言处理——文本表示
人工智能·python·算法·自然语言处理·文本表示
GalaxyPokemon2 小时前
LeetCode - 148. 排序链表
linux·算法·leetcode
iceslime3 小时前
旅行商问题(TSP)的 C++ 动态规划解法教学攻略
数据结构·c++·算法·算法设计与分析
aichitang20243 小时前
矩阵详解:从基础概念到实际应用
线性代数·算法·矩阵