【问题标题】:How do I flip part of number/bitset in C++ efficiently?如何有效地翻转 C++ 中的部分数字/位集?
【发布时间】:2021-01-03 20:14:13
【问题描述】:

假设我有一个长度为 6 的数字 100101。我希望从位置 2 开始翻转位到 5,所以我的答案将是 111011。我知道我可以在循环中翻转单个位。但是有没有一种没有 for 循环的有效方法呢?

【问题讨论】:

  • 大概你并不总是试图翻转所有未设置的位?请稍微澄清一下您的输入/输出。您似乎还假设索引从1 开始?它是大端还是小端?
  • @AsteroidsWithWings 我正在尝试解决竞争性编码问题。使用循环增加让我得到一个 Time limit Exceeded 输出。
  • 什么竞争性编码问题?
  • @AsteroidsWithWings Leetcode 995。问题可能有不同的解决方案,但是当我寻找翻转部分 bitset 时,我找不到任何东西

标签: c++ bit-manipulation std-bitset


【解决方案1】:

如果我理解正确,请尝试

namespace {
unsigned flip(unsigned a)
{
   return a ^ 0b011110u;
}
}  // namespace

只需将常量调整为您想要翻转的实际位,方法是在常量中将它们设为 1。

另一方面,如果您只需要更新单个变量,您也可以使用

unsigned value = 0b100101u;
value ^= 0b011110u;
assert(value == 0b111011u);

编辑 这里使用std::bitset<6u> 和C++98 也是一样的:

#include <bitset>
#include <cassert>

int main()
{
   std::bitset<6u> const kFlipBit2to6WithXor(0x1Eu);  // aka 0b011110u
   std::bitset<6u> number(0x25u);                     // aka 0b100101u
   number ^= kFlipBit2to6WithXor;
   assert(number.to_ulong() == 0x3Bu);                // aka 0b111011u
   return 0;
}

【讨论】:

  • XOR 比 OR 更有可能给出 OP 正在寻找的结果
  • 现在做另一个——翻转位,使 0 变为 1,1 变为 0。提示:您只需更改代码中的一个字符。
【解决方案2】:

0b11110b10000-1

constexpr unsigned low_mask(unsigned x){
  return (1u<<x)-1;
}

0b11000b1111-0b11

constexpr unsigned mask(unsigned width, unsigned offset){
  return low_mask(width+offset)-low_mask(offset);
}

然后使用 xor 翻转位。

unsigned result = 0b100001 ^ mask(4,2);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-17
    • 2013-07-25
    • 2020-07-26
    • 2017-07-25
    相关资源
    最近更新 更多