如何确保n位中至少有m位是开的
How to make sure atleast m out of n bits are on?
给定n个集合,需要确保至少有m个集合被选中。我打算处理比特。我的方法是:
for i in [0,(2^n)-1]
convert i to binary
if number of 1s are greater than or equal to m
{ Some calculations requiring which bits are on }
现在,有没有其他方法可以确保on位的个数至少是m ?在我上面的方法中,我将浪费时间将数字转换为二进制,然后检查是否不是。on位的值>=m。有没有办法缩短这个循环?
我猜你需要生成位掩码来从一组"n"个元素中选择至少"m"个元素的子集。
如果我们有一个算法来生成具有恰好"m"位集的所有位掩码,这可以很容易地完成。
#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
// Given "n" and "r", generate all the possible nCr subsets of an array of size "n"
typedef unsigned long long ULL;
// Generate the lowest number bigger than "num" having exactly "r" set bits
// Algorithm (From Cracking The Coding Interview, 5th Edition) -:
// 1. Find the position of the rightmost "non-trailing" zero (such that there is atleast one '1' on its right).
// Let this position be 'p'
// If there does not exist such a zero, the input is already the largest number possible.
// 2. Flip the bit at 'p' to 1 from 0.
// 3. Count the number of zeroes and ones to the right of 'p'.
// Let that number be c0 and c1 respectively.
// 4. Set all the bits to the right of 'p' to 0.
// 5. Set the first (c1-1) bits (starting from the right) to 1.
ULL NextBigger( ULL num )
{
ULL numBak = num;
// Compute c0 and c1
// c0 = Number of zeroes to the right of the rightmost non-trailing zero
size_t c0 = 0;
// c1 = Number of ones to the right of the rightmost non-trailing zero
size_t c1 = 0;
while ( numBak && ( ( numBak & 1 ) == 0 ) )
{
c0++;
numBak >>= 1;
}
while ( ( numBak & 1 ) == 1 )
{
c1++;
numBak >>= 1;
}
// If the input is either 0,
// or of the form "1111..00000",
// then there is no bigger number possible
// Note that for this to work, num should be unsigned
if ( c0 + c1 == 0 || c0 + c1 == ( sizeof( num ) * 8 ) )
{
return 0;
}
// Position of the rightmost non-trailing zero ( starting from the right )
const size_t p = c0 + c1;
// Flip the rightmost non-trailing zero
num |= 1 << p;
// Clear all bits to the right of p
num &= ~( ( 1 << p ) - 1 );
// Insert (c1-1) ones on the right of p
num |= ( 1 << ( c1 - 1 ) ) - 1;
return num;
}
vector<ULL> GenerateSubsets( const size_t& n, const size_t& r )
{
assert( n > 0 );
assert( r > 0 );
assert( n >= r );
vector<ULL> subsets;
// The smallest number having exactly "r" bits set
ULL lowest = ( 1ULL << r ) - 1;
// The biggest number having exactly "r" bits set
ULL highest = lowest << ( n - r );
// The set bits in the binary of "bitMask" denote the positions of the set included in the subset
// This loop should run exactly nCr times
for ( ULL bitMask = lowest; bitMask <= highest; bitMask = NextBigger( bitMask ) )
{
subsets.push_back( bitMask );
}
return subsets;
}
// Extracts the subset indices from the bitmask
vector<size_t> DecodeMask( ULL bitMask )
{
vector<size_t> positions;
size_t i = 0;
while ( bitMask )
{
if ( bitMask & 1 )
{
positions.push_back( i );
}
bitMask >>= 1;
i++;
}
return positions;
}
int main()
{
size_t n = 5;
size_t r = 2;
cout << "Generating subsets of size " << r << "n";
auto vec = GenerateSubsets( n, r );
cout << "Number of subsets = " << vec.size() << "n";
// Print the subset indices
for ( size_t i = 0; i < vec.size(); i++ )
{
auto decode = DecodeMask( vec[i] );
for ( size_t j = 0; j < decode.size(); j++ )
{
cout << decode[j] << " ";
}
cout << "n";
}
}
现在我们可以很容易地修改它,通过应用上述算法同时将"m"增加到"n"来生成具有至少"m"位的所有位掩码。
// Rest of the code same as above
int main()
{
size_t n = 5;
size_t m = 2;
for ( size_t r = m; r <= n; r++ )
{
cout << "Generating subsets of size " << r << "n";
auto vec = GenerateSubsets( n, r );
cout << "Number of subsets = " << vec.size() << "n";
// Print the subset indices
for ( size_t i = 0; i < vec.size(); i++ )
{
auto decode = DecodeMask( vec[i] );
for ( size_t j = 0; j < decode.size(); j++ )
{
cout << decode[j] << " ";
}
cout << "n";
}
cout << "n";
}
}
相关文章:
- 如何确保C++函数在定义之前声明(如override关键字)
- 如何确保在使用基于布尔值的两个方法之一调用方法时避免分支预测错误
- 使用Unique_ptr确保工厂中的对象唯一
- MESI协议和std::atomic-它是否确保所有写入立即对其他线程可见?
- C++需要帮助从用户那里获得一个整数,并确保它在另外两个整数之间
- 确保流程关闭
- 如何确保接受的C++模板类型使运算符重载?
- 确保编译时的特定 std::array 位置
- C++ 确保子类为常量提供自定义值
- 确保内存映射页位于内存中
- 确保套装新鲜度的有效方法
- C ++类型特征:确保子类实现方法
- 是否确保 2 个连续的 std::chrono::steady_clock::now() 不相等?
- 如何确保用户在一行上提示输入一次时输入名字和姓氏?
- 确保无变体的型号安全
- 确保特征将 AVX 矢量化用于特定操作
- 确保所有构造函数调用相同的函数 c++ 设计模式
- 如何确保 Visual C++ 不允许作用域枚举访问?
- 如何确保调用显式构造函数并允许大括号初始化?
- 确保模拟的 GTest 方法覆盖虚拟方法