📜  竞争编程的按位技巧

📅  最后修改于: 2021-06-26 22:37:43             🧑  作者: Mango

建议先参考有关按位运算符的有趣事实。

1.如何在数字“ num”中设置一位:

如果我们想在数字“ num”中的第n个位置设置一位,则可以使用“或”运算符(|)来完成。

  • 首先我们通过(1 << n)左移’1’到n位
  • 然后,使用’OR’运算符将位设置在该位置。使用’OR’运算运算符是因为即使先前在数字’num’的二进制表示中未设置该位,也会设置该位。
#include
using namespace std;
// num is the number and pos is the position 
// at which we want to set the bit.
void set(int & num,int pos)
{
     // First step is shift '1', second
     // step is bitwise OR
     num |= (1 << pos);
}
int main()
{
     int num = 4, pos = 1;
     set(num, pos);
     cout << (int)(num) << endl;
     return 0;
}

输出:

6

我们通过“按引用调用”传递了参数,以永久更改号码。

2.如何取消设置/清除数字“ num”中第n个位置的位:

假设我们想在数字’num’的第n个位置取消设置位,那么我们必须在’AND’(&)运算符的帮助下进行设置。

  • 首先,我们通过(1 << n)左移’1’到n位置,而不是使用按位NOT运算符’〜’来取消设置此移位的’1’。
  • 现在,清除此左移的“ 1”即使其变为“ 0”后,我们将对“ AND”(&)与数字“ num”进行设置,该数字将在第n个位置取消设置。
#include 
using namespace std;
// First step is to get a number that  has all 1's except the given position.
void unset(int &num,int pos)
{
    //Second step is to bitwise and this  number with given number
    num &= (~(1 << pos));
}
int main()
{
    int num = 7;
    int  pos = 1;
    unset(num, pos);
    cout << num << endl;
    return 0;
}

输出:

5

3.在第n个位置切换:

切换意味着如果先前将其设为“off”(0),则将其设为“on”(1),如果先前将其设为“on”(1),则将其变为“off”(0)。我们将在此处使用“XOR”运算符是这个“ ^”。 “ XOR”运算符背后的原因是由于其属性。

  • ‘XOR’运算符的属性。
    • 1 ^ 1 = 0
    • 0 ^ 0 = 0
    • 1 ^ 0 = 1
    • 0 ^ 1 = 1
  • 如果两个位不同,则“ XOR”运算符将返回一个设置位(1),否则将返回一个未设置的位(0)。
#include 
using namespace std;
// First step is to shift 1,Second step is to XOR with given number
void toggle(int &num,int pos)
{
    num ^= (1 << pos);
}
int main()
{
    int num = 4;
    int pos = 1;
    toggle(num, pos);
    cout << num << endl;
    return 0;
}

输出:

6

4.检查第n个位置的位是否已设置或未设置:

使用’AND’运算符很容易做到。

  • 左移’1’到给定位置,然后左移’AND’(’&’)。
#include 
using namespace std;
  
bool at_position(int num,int pos)
{
    bool bit = num & (1<

输出:

1

观察到我们首先左移了“ 1”,然后使用“ AND”运算符在该位置获取了位。因此,如果“ num”中位置“ pos”的位置为“ 1”,则在“ AND”之后,变量“ bit”将存储“ 1”,否则如果数字“ num”中位置“ pos”的位置为“ 0”比“与”之后我们的变量位将存储“ 0”。

一些更快速的技巧:

  • 反转数字/ 1的补码的每一位:

    如果我们想反转数字的每一位,即将位“ 0”更改为“ 1”,将位“ 1”更改为“ 0”。我们可以借助“〜”运算符。例如:如果number为num = 00101100(二进制表示),则’〜num’将为’11010011’。

这也是“ 1的数字补码”。

#include 
using namespace std;
int main()
{
    int num = 4;
  
    // Inverting every bit of number num
    cout << (~num);
    return 0;
}
Output:
 -5
  • 数字的二进制补码:数字的2的补码为1的补码+ 1。

因此,我们可以通过找到1s补码并将1加到结果即(〜num + 1)来正式获得2的补码,否则我们可以做的就是使用’-‘运算符。

#include 
using namespace std;
int main()
{
    int num = 4;
    int twos_complement = -num;
    cout << "This is two's complement " << twos_complement << endl;
    cout << "This is also two's complement " << (~num+1) << endl;
    return 0;
}

输出:

This is two's complement -4
This is also two's complement -4
  • 剥离最低设置位:

在许多情况下,我们希望剥离最低的设置位,例如在Binary Indexed树数据结构中,将一个设置位的数量计数。

我们做这样的事情:

X = X & (X-1)

但是它怎么工作呢?

让我们来看一个例子,让X = 1100。

(X-1)将所有位取反,直到遇到最低位’1’,并且也将最低位’1’取反。

X-1变为1011。将X与X-1“与”后,我们将剥离掉最低的设置位。

#include 
using namespace std;
void strip_last_set_bit(int &num)
{
    num = num & (num-1);
}
int main()
{
    int num = 7;
    strip_last_set_bit(num);
    cout << num << endl;
    return 0;
}

输出:

6
  • 获取数字的最低设置位:

这是通过使用表达式’X&(-X)’完成的,让我们看一个例子:让X =00101100。因此〜X(1的补码)为’11010011’,2的补码为(〜X + 1或-X),即“ 11010100”。因此,如果我们将原始数字“ X”与两个补码“ -X”进行“与”运算,则会得到最低的设置位。

00101100
& 11010100
-----------
00000100
#include 
using namespace std;
int lowest_set_bit(int num)
{
    int ret = num & (-num);
    return ret;
}
int main()
{
    int num = 10;
    int ans = lowest_set_bit(num);
    cout << ans << endl;
    return 0;
}

输出:

2

竞争编程的位技巧

有关Bit Hacks的更多文章,请参阅BitWise运营商文章。

如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。