卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章19002本站已运行342

设置最左边未设置的位

设置最左边未设置的位

本文旨在寻找一种设置给定数字最左边未设置位的方法。在最高位设置位之后的第一个未设置位被视为最左边的未设置位。

问题陈述

给定一个数字n,任务是将该数字的二进制展开中未设置的最左边的位设置为1。所有其他位应保持不变。如果原始数字的所有位都已设置,则返回该数字。

Examples

'
Input: 46
'
Output: 62

Explanation

的中文翻译为:

解释

Binary Expansion of 46 = 101110.

最左边未设置的位是 101110。

Upon setting the underlined bit we get, 111110. This is the binary expansion of 62.

Hence answer is 62.

'
Input: 11
'
Output: 15

Explanation

的中文翻译为:

解释

Binary Expansion of 11 = 1011.

最左边未设置的位是 1011。

Upon changing the underlined bit, we get 1111 which is the binary expansion of 15.

'
Input: 30
'
Output: 31

Explanation

的中文翻译为:

解释

Binary Expansion of 30 = 11110.

最左侧未设置的位为 11110。

在设置最左边未设置的位时,我们得到11111,这是31的二进制展开。

'
Input: 7
'
Output: 7

Explanation

的中文翻译为:

解释

Binary Expansion of 7 = 111.

由于所有位都被设置了,没有最左边未设置的位。因此答案与原始数字保持不变。

解决方案方法

  • 检查是否所有的位都被设置。如果是,则返回原始数字作为答案。

  • Find the position of the latest unset bit using bitwise AND operator, and update the counter.

  • 将位设置为与计数器相对应。

  • 显示答案。

查找是否所有位都被设置

The idea here is that by adding one bit, the input number will become a perfect square of 2 if all of its bits are set. Hence, the following expression will determine whether or not all the bits of the number are set: n & (n + 1) == 0;

Let us understand this through an example.

Let the number be 5. We need to check if all the bits of 5 are set or not.

的中文翻译为:
n = 3 n + 1 = 4 n & (n + 1)
011
011 100 000

Thus it is safe to conclude that all the bits of n are already set and we return the number as it is.

找到最左边未设置的位

如果AND操作的输出不等于零,则继续查找最左边未设置的位。首先生成一个位数与给定整数相等的数字。新数字的最左边位最初设置为1。

然后,我们运行一个循环,从最左边的1位开始,向右搜索第一个0,通过对给定数字和新数字进行位与运算来实现。当位与运算的结果为0时,我们返回第一个未设置的最左边位的位置pos。

To Set the Leftmost Unset Bit

Generate a new number in which only the bit corresponding to pos is set. Perform bitwise OR operation between this new number and the original number.

Algorithm

的中文翻译为:

算法

Function all_bits_set()

  • 计算 n & (n + 1)。

  • If result == 0, return true.

  • 否则返回 false。

Function find_leftmost_unset_bit()

  • Initialize m = 1, pos = 0.

  • while (n > m)

    • 左移 m 1 位

  • 将 m 右移 1 位,以使其对应于 n 的最高有效位。

  • while ((n & m) != 0)

    • 将 m 右移 1 位

    • pos++

  • 一旦循环中断,我们就可以得到最高有效位(MSB)中最左边未设置的位的位置。

  • 返回 log2(n) - pos,即从最低有效位开始的位位置。

函数 set_leftmost_unset_bit()

  • 初始化 k = 1

  • Function Call find_leftmost_unset_bit().

  • k = k << pos

  • Compute n | k.

  • Update n.

Function main()

  • 初始化 n

  • Function Call all_bits_set()

  • 函数调用 find_leftmost_unset_bit()

  • 调用函数set_leftmost_unset_bit()

  • 显示 n

示例:C++程序

这个程序通过将输入数字 n 的二进制展开中最左边未设置的位设置为 1 来修改它。它使用位运算符 OR,左移和右移运算符以及位与运算符来实现其目标。

'
// A C++ program to set the left most unset bit of a number. If all the bits of the given number are already set, it returns the number as it is.
#include <iostream>
#include <cmath>
using namespace std;
// function to check if all bits of the given number are already set
// if all bits of n are set, n + 1 will be a power of 2.
bool all_bits_set(int n){
   if ((n & (n + 1)) == 0)    {
      return true;
   }
   return false;
}

// function to find the position of the leftmost unset bit from the LSB.
int find_leftmost_unset_bit(int n){
   int m = 1, pos = 0;
   while (n > m){
      m = m << 1;
   }
   m = m >> 1; // to make the number of digits in m equal to number of digits in n
   
   // the following loop executes till the first zero is encountered, starting from the msb
   while ((n & m) != 0){
      m = m >> 1;
      pos++;
   }
   
   // since pos is the position of the unset bit from the MSB we return log2(n) - pos which is the location of the leftmost unset bit from the LSB.
   return log2(n) - pos;
}

// function to set the leftmost unset bit from the LSB.
void set_leftmost_unset_bit(int &n){
   int k = 1;
   int pos = find_leftmost_unset_bit(n);
   k = k << (pos); // left shift k by pos
   n = n | k; // to set the leftmost unset bit
}

// main function
int main(){
   int n = 46;
   cout << "Input Number: "<< n << endl;
   if (all_bits_set(n))    {
      cout << n << endl;
      return 0;
   }
   set_leftmost_unset_bit(n);
   cout << "Number after setting the Leftmost Unset Bit: " << n << endl; // display the updated number
   return 0;
}

输出

'
Input Number: 46
Number after setting the Leftmost Unset Bit: 62

时间和空间分析

时间复杂度:O(log2(n)),因为在函数find_leftmost_unset_bit()中,我们可能需要遍历二进制展开式的所有log2(n)位数来找到最左边的未设置位。

Space Complexity: O(1), as constant space is always used in the implementation.

Conclusion

本文讨论了一种寻找并设置给定数字最左边未设置位的方法。如果数字的所有位已经设置,我们将返回该数字。否则,为了设置该位,我们使用位左移和右移运算符生成一个新的位模式,并使用位或运算符计算结果。解决方案的概念、多个示例、使用的算法、C++程序解决方案以及时间和空间复杂度分析都被详细解释,以便更深入地理解。

卓越飞翔博客
上一篇: 真正的服务器优化:了解PHP8底层开发原理
下一篇: 返回列表
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏