C++如何统计byte类型buffer中连续bit位为1的最大长度

springontime 2017-03-14 11:33:06
例如buffer是2个字节的长度,起二进制内容为1100011110001111 则连续bit位为1的最大长度为4,且这样的连续出现次数有2次。不知道哪位大神能提供比较高效的方案呢,或者有思路也行,我们一起讨论。
...全文
338 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
cxyOOOO 2017-03-23
  • 打赏
  • 举报
回复
思路: int CountBits1(int x) { x = (x & 0x55555555) + ((x >> 1) & 0x55555555); x = (x & 0x33333333) + ((x >> 2) & 0x33333333); x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F); x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF); x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF); return x; } int TurnoffRightContiguous1(int x) { return ((x | (x - 1)) + 1) & x; } unsigned int u = bitset<32>("1100011110001111").to_ulong(); int t; while (u) { t = TurnoffRightContiguous1(u); cout << CountBits1(u) - CountBits1(t) << "\n"; u = t; }
vnvlyp 2017-03-23
  • 打赏
  • 举报
回复
引用 5 楼 cxyOOOO 的回复:
思路: int CountBits1(int x) { x = (x & 0x55555555) + ((x >> 1) & 0x55555555); x = (x & 0x33333333) + ((x >> 2) & 0x33333333); x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F); x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF); x = (x & 0x0000FFFF) + ((x >> 16) & 0x0000FFFF); return x; } int TurnoffRightContiguous1(int x) { return ((x | (x - 1)) + 1) & x; } unsigned int u = bitset<32>("1100011110001111").to_ulong(); int t; while (u) { t = TurnoffRightContiguous1(u); cout << CountBits1(u) - CountBits1(t) << "\n"; u = t; }
这思路牛逼 不过有两个问题 CountBits1应该接受一个无符号的整数CountBits1(unsigned int x),不然你这应该是未指定行为。 不知道这个怎么才能处理超过64位的数据?
  • 打赏
  • 举报
回复
查表法...
vnvlyp 2017-03-15
  • 打赏
  • 举报
回复
如果只是要最大长度的话应该很容易写出一个 时间复杂度Θ(n) 空间复杂度 Θ(1) 的方法吧。 再要优化的话可能也就是检查一下有没有0xFF, 0xFFFF, 0xFFFFFFFF之类的值,但是这样依旧是Θ(n),而且在你数据没有很长的连续串时多余的很多检查可能反倒会很慢。
void foo(void *buffer, size_t size)
{
	const int masks[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

	auto ptr = reinterpret_cast<intptr_t>(buffer);
	auto end = static_cast<intptr_t>(ptr + size);

	int maxLength = 0, len = 0, count = 0;

	while (ptr < end)
	{
		auto val = *reinterpret_cast<uint8_t *>(ptr);
		for (int i = 7; i >= 0; i--)
		{
			if (val & masks[i])
			{
				len++;

				if (len > maxLength)
				{
					maxLength = len;
					count = 1;
				}
				else if (len == maxLength)
				{
					count++;
				}
			}
			else
			{
				len = 0;
			}
		}

		ptr++;
	}


	printf("maxLength = %d, count = %d\n", maxLength, count);
}


uint8_t buffer[] = {0b11000111, 0b10001111, 0b00011111, 0b11110011, 0b11111110, 0b01111111, 0b11000000};

// 输出 maxLength = 9, count = 3
foo(buffer, ARRAYSIZE(buffer));

// 你的例子 输出 maxLength = 4, count = 2
foo(buffer, 2);
vnvlyp 2017-03-15
  • 打赏
  • 举报
回复
引用 1 楼 jianwen0529 的回复:
你数据量不多,就用常规的办法就好了 写了个demo,没测试过

unsigned int u = 0;
u |= buffer[0];
u |= ((unsigned int)buffer[1] << 8);

int j = 0;
bool on = true;

int count[9] = {0};
for(int i = 0; i < 16; i+)
{
	if(u & (1<<i) ) {
		if(on)
			count[j]++;
		else {
			on = true;
			count[++j]++;
		}
	}
	else{
		on = false;
	}
}

for(int i = 0; i < j+1; i++)
{
	//这里判断统计后的个数
}
你这个 j 的处理不对吧。。
幻夢之葉 2017-03-14
  • 打赏
  • 举报
回复
你数据量不多,就用常规的办法就好了 写了个demo,没测试过

unsigned int u = 0;
u |= buffer[0];
u |= ((unsigned int)buffer[1] << 8);

int j = 0;
bool on = true;

int count[9] = {0};
for(int i = 0; i < 16; i+)
{
	if(u & (1<<i) ) {
		if(on)
			count[j]++;
		else {
			on = true;
			count[++j]++;
		}
	}
	else{
		on = false;
	}
}

for(int i = 0; i < j+1; i++)
{
	//这里判断统计后的个数
}

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧