📌  相关文章
📜  具有相同置位位数的最近(或下一个)较小和较大的数字

📅  最后修改于: 2021-04-24 16:08:41             🧑  作者: Mango

给定一个正整数n,请打印在其二进制表示形式中具有相同的1位数字的下一个最小和前一个最大数字。

例子 :

Input : n = 5
Output : Closest Greater = 6
         Closest Smaller = 3
Note that 5, 6 and 3 have same number of 
set bits. 

Input : n = 11
Output : Closest Greater = 13
         Closest Smaller = 7

蛮力法
一种简单的方法就是蛮力:计算n中1的数量,然后递增(或递减)直到找到相同的1。

最佳方法
让我们从getNext的代码开始,然后继续进行getPrev。

获取下一个数字的位操作方法
如果我们考虑下一个数字应该是什么,我们可以观察到以下内容。给定数字13948,二进制表示形式如下:

1   1   0   1   1  0  0  1  1  1  1  1  0  0
13  12  11  10  9  8  7  6  5  4  3  2  1  0

我们希望使这个数字更大(但不要太大)。我们还需要保持相同数量。
观察:给定一个数字n和两个比特位置i和j,假设我们将比特i从1翻转到0,将比特j从0翻转到1。如果i> j,则n将减少。如果i

我们知道以下内容:

  • 如果将0翻转为1,则必须将1翻转为零。
  • 该数字(两次翻转后)将更大,且仅当零比一位在一位至零位的左侧时才如此。
  • 我们希望使数字更大,但不必不必要地更大。因此,我们需要将最右边的零翻转为零。

换句话说,我们将最右边的非尾随零翻转。也就是说,使用上面的示例,尾随零在第0和第1点。最右边的非拖尾零在位7处。我们将此位置称为p。

p ==> Position of rightmost non-trailing 0.

步骤1:翻转最右边的非尾随零

1    1   0   1  1  0  1  1  1  1  1  1  0  0
13  12  11  10  9  8  7  6  5  4  3  2  1  0

通过此更改,我们增加了n的1的数量。我们可以通过将所有位重新排列到位p的右边来缩小数字,以使0在左边,而1在右边。这样做时,我们想用0代替1中的一个。

一种相对简单的方法是计算p右边的个数,清除从0到p的所有位,然后加回c1-1。令c1是p右边的1的数目,而c0是p右边的零的数目。

让我们通过一个例子来完成这个过程。

c1 ==> Number of ones to the right of p
c0 ==> Number of zeros to the right of p.
p = c0 + c1

步骤2:清除p右侧的位。从之前开始,c0 =2。c1=5。p= 7。

1    1   0   1  1  0  1  0  0  0  0  0  0  0
13  12  11  10  9  8  7  6  5  4  3  2  1  0

要清除这些位,我们需要创建一个掩码,该掩码为一串序列,后跟p个零。我们可以这样做,如下所示:

// all zeros except for a 1 at position p.
a = 1 << p; 

// all zeros, followed by p ones.
b = a - 1;                       

// all ones, followed by p zeros.
mask = ~b;                       

// clears rightmost p bits.
n = n & mask;                

Or, more concisely, we do:
n &= ~((1 << p) - 1).

步骤3:添加一个c1-1。

1   1   0   1   1  0  1  0  0  0  1  1  1  1
13  12  11  10  9  8  7  6  5  4  3  2  1  0

要在右侧插入c1 – 1,我们执行以下操作:

// 0s with a 1 at position c1– 1
a = 1 << (c1 - 1);    

// 0s with 1s at positions 0 through c1-1
b = a - 1;                

// inserts 1s at positions 0 through c1-1
n = n | b;                

Or, more concisely:
n | = (1 << (c1 - 1)) - 1;  

现在,我们得出了具有相同数目的大于n的最小数目。 getNext的代码实现如下

C++
// C++ implementation of  getNext with
// same number of bits 1's is below
#include 
using namespace std;
  
// Main Function to find next smallest
// number bigger than n
int getNext(int n)
{
    /* Compute c0 and c1 */
    int c = n;
    int c0 = 0;
    int c1 = 0;
  
    while (((c & 1) == 0) && (c != 0))
    {
        c0 ++;
        c >>= 1;
    }
    while ((c & 1)==1)
    {
        c1++;
        c >>= 1;
    }
  
    // If there is no bigger number with the
    // same no. of 1's
    if (c0 +c1 == 31 || c0 +c1== 0)
        return -1;
  
    // position of rightmost non-trailing zero
    int p = c0 + c1;
  
    // Flip rightmost non-trailing zero
    n |= (1 << p);
  
    // Clear all bits to the right of p
    n &= ~((1 << p) - 1);
  
    // Insert (c1-1) ones on the right.
    n |= (1 << (c1 - 1)) - 1;
  
    return n;
}
  
// Driver Code
int main()
{
    int n = 5;   // input 1
    cout << getNext(n) << endl;
  
    n = 8;     // input 2
    cout << getNext(n);
    return 0;
}


Java
// Java implementation of 
// getNext with same number 
// of bits 1's is below
import java.io.*;
  
class GFG 
{
      
    // Main Function to find next
    // smallest number bigger than n
    static int getNext(int n)
    {
          
        /* Compute c0 and c1 */
        int c = n;
        int c0 = 0;
        int c1 = 0;
      
        while (((c & 1) == 0) && 
                (c != 0))
        {
            c0++;
            c >>= 1;
        }
        while ((c & 1) == 1)
        {
            c1++;
            c >>= 1;
        }
      
        // If there is no bigger number 
        // with the same no. of 1's
        if (c0 + c1 == 31 || 
            c0 + c1 == 0)
            return -1;
      
        // position of rightmost 
        // non-trailing zero
        int p = c0 + c1;
      
        // Flip rightmost 
        // non-trailing zero
        n |= (1 << p);
      
        // Clear all bits  
        // to the right of p
        n &= ~((1 << p) - 1);
      
        // Insert (c1-1) ones 
        // on the right.
        n |= (1 << (c1 - 1)) - 1;
      
        return n;
    }
      
      
    // Driver Code
    public static void main (String[] args) 
    {
      
        int n = 5; // input 1
        System.out.println(getNext(n));
      
        n = 8; // input 2
        System.out.println(getNext(n));
    }
}
  
// This code is contributed by aj_36


Python 3
# Python 3 implementation of getNext with
# same number of bits 1's is below
  
# Main Function to find next smallest
# number bigger than n
def getNext(n):
  
    # Compute c0 and c1 
    c = n
    c0 = 0
    c1 = 0
  
    while (((c & 1) == 0) and (c != 0)):
        c0 += 1
        c >>= 1
      
    while ((c & 1) == 1):
        c1 += 1
        c >>= 1
  
    # If there is no bigger number with 
    # the same no. of 1's
    if (c0 + c1 == 31 or c0 + c1== 0):
        return -1
  
    # position of rightmost non-trailing zero
    p = c0 + c1
  
    # Flip rightmost non-trailing zero
    n |= (1 << p)
  
    # Clear all bits to the right of p
    n &= ~((1 << p) - 1)
  
    # Insert (c1-1) ones on the right.
    n |= (1 << (c1 - 1)) - 1
  
    return n
  
# Driver Code
if __name__ == "__main__":
      
    n = 5 # input 1
    print(getNext(n))
  
    n = 8     # input 2
    print(getNext(n))
  
# This code is contributed by ita_c


C#
// C# implementation of getNext with
// same number of bits 1's is below
using System;
  
class GFG {
      
    // Main Function to find next
    // smallest number bigger than n
    static int getNext(int n)
    {
          
        /* Compute c0 and c1 */
        int c = n;
        int c0 = 0;
        int c1 = 0;
      
        while (((c & 1) == 0) && (c != 0))
        {
            c0++;
            c >>= 1;
        }
        while ((c & 1) == 1)
        {
            c1++;
            c >>= 1;
        }
      
        // If there is no bigger number 
        // with the same no. of 1's
        if (c0 + c1 == 31 || c0 + c1== 0)
            return -1;
      
        // position of rightmost 
        // non-trailing zero
        int p = c0 + c1;
      
        // Flip rightmost non-trailing
        // zero
        n |= (1 << p);
      
        // Clear all bits to the right 
        // of p
        n &= ~((1 << p) - 1);
      
        // Insert (c1-1) ones on the
        // right.
        n |= (1 << (c1 - 1)) - 1;
      
        return n;
    }
      
    // Driver Code
    static void Main()
    {
        int n = 5; // input 1
        Console.WriteLine(getNext(n));
      
        n = 8; // input 2
        Console.Write(getNext(n));
      
    }
}
  
// This code is contributed by Anuj_67


PHP
>= 1;
    }
    while (($c & 1) == 1)
    {
        $c1++;
        $c >>= 1;
    }
  
    // If there is no bigger
    // number with the
    // same no. of 1's
    if ($c0 + $c1 == 31 || 
        $c0 + $c1== 0)
        return -1;
  
    // position of rightmost 
    // non-trailing zero
    $p = $c0 + $c1;
  
    // Flip rightmost non - 
    // trailing zero
    $n |= (1 << $p);
  
    // Clear all bits to 
    // the right of p
    $n &= ~((1 << $p) - 1);
  
    // Insert (c1-1) ones
    // on the right.
    $n |= (1 << ($c1 - 1)) - 1;
  
    return $n;
}
  
    // Driver Code
    // input 1
    $n = 5; 
    echo getNext($n),"\n";
      
    // input 2
    $n = 8; 
    echo getNext($n);
  
// This code is contributed by ajit
?>


C++
// C++ Implementation of  getPrev in
// Same number of bits 1's is below
#include 
using namespace std;
  
// Main Function to find next Bigger number
// Smaller than n
int getPrev(int n)
{
    /* Compute c0 and c1  and store N*/
    int temp = n;
    int c0 = 0;
    int c1= 0;
  
    while ((temp & 1) == 1)
    {
        c1++;
        temp = temp >> 1;
    }
  
    if (temp == 0)
        return -1;
  
    while (((temp & 1) == 0) && (temp!= 0))
    {
        c0++;
        temp  = temp >> 1;
    }
  
    // position of rightmost non-trailing one.
    int p = c0 + c1;
  
    // clears from bit p onwards
    n = n & ((~0) << (p + 1));
  
    // Sequence of (c1+1) ones
    int mask = (1 << (c1 + 1)) - 1;
  
    n = n | mask << (c0 - 1);
  
    return n;
}
  
// Driver Code
int main()
{
    int n = 6;   // input 1
    cout << getPrev(n);
  
    n = 16;     // input 2
    cout << endl;
    cout << getPrev(n);
  
    return 0;
}


Java
// Java Implementation of  
// getPrev in Same number
// of bits 1's is below
import java.io.*;
  
class GFG 
{
      
// Main Function to find 
// next Bigger number 
// Smaller than n
static int getPrev(int n)
{
    // Compute c0 and 
    // c1 and store N
    int temp = n;
    int c0 = 0;
    int c1= 0;
  
    while((temp & 1) == 1)
    {
        c1++;
        temp = temp >> 1;
    }
  
    if(temp == 0)
        return -1;
  
    while(((temp & 1) == 0) && 
           (temp!= 0))
    {
        c0++;
        temp = temp >> 1;
    }
  
    // position of rightmost
    // non-trailing one.
    int p = c0 + c1;
  
    // clears from bit p onwards
    n = n & ((~0) << (p + 1));
  
    // Sequence of (c1+1) ones
    int mask = (1 << (c1 + 1)) - 1;
  
    n = n | mask << (c0 - 1);
  
    return n;
}
  
// Driver Code
public static void main(String[] args) 
{
    int n = 6; // input 1
    System.out.println(getPrev(n));
  
    n = 16; // input 2
    System.out.println(getPrev(n));
}
}
  
// This code is contributed by aj_36


C#
// C# Implementation of 
// getPrev in Same number
// of bits 1's is below
using System;
  
class GFG
{
  
// Main Function to find 
// next Bigger number 
// Smaller than n
static int getPrev(int n)
{
    // Compute c0 and 
    // c1 and store N
    int temp = n;
    int c0 = 0;
    int c1 = 0;
  
    while((temp & 1) == 1)
    {
        c1++;
        temp = temp >> 1;
    }
  
    if(temp == 0)
        return -1;
  
    while(((temp & 1) == 0) && 
           (temp != 0))
    {
        c0++;
        temp = temp >> 1;
    }
  
    // position of rightmost
    // non-trailing one.
    int p = c0 + c1;
  
    // clears from 
    // bit p onwards
    n = n & ((~0) << (p + 1));
  
    // Sequence of 
    // (c1+1) ones
    int mask = (1 << (c1 + 1)) - 1;
  
    n = n | mask << (c0 - 1);
  
    return n;
}
  
// Driver Code
static public void Main ()
{
    int n = 6; // input 1
    Console.WriteLine(getPrev(n));
  
    n = 16; // input 2
    Console.WriteLine(getPrev(n));
}
}
  
// This code is contributed by ajit


PHP
> 1;
    }
  
    if ($temp == 0)
        return -1;
  
    while ((($temp & 1) == 0) && 
            ($temp!= 0))
    {
        $c0++;
        $temp = $temp >> 1;
    }
  
    // position of rightmost
    // non-trailing one.
    $p = $c0 + $c1;
  
    // clears from bit p onwards
    $n = $n & ((~0) << ($p + 1));
  
    // Sequence of (c1 + 1) ones
    $mask = (1 << ($c1 + 1)) - 1;
  
    $n = $n | $mask << ($c0 - 1);
  
    return $n;
}
  
// Driver Code
  
// input 1
$n = 6; 
echo getPrev($n);
  
// input 2
$n = 16;     
echo " \n" ;
echo getPrev($n);
  
// This code is contributed by Ajit
?>


C++
// C++ Implementation of getNext with
// Same number of bits 1's is below
#include 
using namespace std;
  
// Main Function to find next smallest number
// bigger than n
int getNext(int n)
{
    /* Compute c0 and c1 */
    int c = n;
    int c0 = 0;
    int c1 = 0;
  
    while (((c & 1) == 0) && (c != 0))
    {
        c0 ++;
        c >>= 1;
    }
    while ((c & 1)==1)
    {
        c1++;
        c >>= 1;
    }
  
    // If there is no bigger number with the
    // same no. of 1's
    if (c0 +c1 == 31 || c0 +c1== 0)
        return -1;
  
    return n + (1 << c0) + (1 << (c1 - 1)) - 1;
}
  
// Driver Code
int main()
{
    int n = 5; // input 1
    cout << getNext(n);
  
    n = 8;     // input 2
    cout << endl;
    cout << getNext(n);
    return 0;
}


Java
// Java Implementation of getNext with
// Same number of bits 1's is below
import java.io.*;
  
class GFG 
{
      
// Function to find next smallest 
// number bigger than n
static int getNext(int n)
{
    /* Compute c0 
    and c1 */
    int c = n;
    int c0 = 0;
    int c1 = 0;
  
    while (((c & 1) == 0) && (c != 0))
    {
        c0 ++;
        c >>= 1;
    }
    while ((c & 1) == 1)
    {
        c1++;
        c >>= 1;
    }
  
    // If there is no bigger number 
    // with the same no. of 1's
    if (c0 + c1 == 31 || c0 + c1 == 0)
        return -1;
  
    return n + (1 << c0) + 
               (1 << (c1 - 1)) - 1;
}
  
// Driver Code
public static void main (String[] args) 
{
int n = 5; // input 1
System.out.println(getNext(n));
  
n = 8; // input 2
System.out.println(getNext(n));
}
}
  
// This code is contributed by ajit


C#
// C# Implementation of getNext 
// with Same number of bits 
// 1's is below
using System;
  
class GFG
{
      
// Function to find next smallest 
// number bigger than n
static int getNext(int n)
{
    /* Compute c0 
    and c1 */
    int c = n;
    int c0 = 0;
    int c1 = 0;
  
    while (((c & 1) == 0) && 
            (c != 0))
    {
        c0 ++;
        c >>= 1;
    }
    while ((c & 1) == 1)
    {
        c1++;
        c >>= 1;
    }
  
    // If there is no bigger
    // number with the same
    // no. of 1's
    if (c0 + c1 == 31 ||
        c0 + c1 == 0)
        return -1;
  
    return n + (1 << c0) + 
               (1 << (c1 - 1)) - 1;
}
  
// Driver Code
static public void Main ()
{
    int n = 5; // input 1
    Console.WriteLine(getNext(n));
  
    n = 8; // input 2
    Console.WriteLine(getNext(n));
    }
}
  
// This code is contributed by m_kit


PHP
>= 1;
    }
    while (($c & 1) == 1)
    {
        $c1++;
        $c >>= 1;
    }
  
    // If there is no bigger 
    // number with the
    // same no. of 1's
    if ($c0 + $c1 == 31 || 
        $c0 + $c1 == 0)
        return -1;
  
    return $n + (1 << $c0) + 
                (1 << ($c1 - 1)) - 1;
}
  
// Driver Code
$n = 5; // input 1
echo getNext($n);
  
$n = 8; // input 2
echo "\n";
echo getNext($n);
  
// This code is contributed by ajit
?>


C++
// C++ Implementation of Arithmetic Approach to
// getPrev with Smae number of bits 1's is below
#include 
using namespace std;
  
// Main Function to find next Bigger number
// Smaller than n
int getPrev(int n)
{
    /* Compute c0 and c1  and store N*/
    int temp = n;
    int c0 = 0;
    int c1 = 0;
  
    while ((temp & 1) == 1)
    {
        c1++;
        temp = temp >> 1;
    }
  
    if (temp == 0)
        return -1;
  
    while (((temp & 1) == 0) && (temp!= 0))
    {
        c0++;
        temp  = temp >> 1;
    }
  
    return n - (1 << c1) - (1 << (c0 - 1)) + 1;
}
  
// Driver Code
int main()
{
    int n = 6;   // input 1
    cout << getPrev(n);
  
    n = 16;     // input 2
    cout << endl;
    cout << getPrev(n);
  
    return 0;
}


Java
// Java Implementation of Arithmetic
// Approach to getPrev with Same
// number of bits 1's is below
import java.io.*;
  
class GFG 
{
      
// Main Function to find next 
// Bigger number Smaller than n
static int getPrev(int n)
{
    /* Compute c0 and 
    c1 and store N*/
    int temp = n;
    int c0 = 0;
    int c1 = 0;
  
    while ((temp & 1) == 1)
    {
        c1++;
        temp = temp >> 1;
    }
  
    if (temp == 0)
        return -1;
  
    while (((temp & 1) == 0) && 
            (temp!= 0))
    {
        c0++;
        temp = temp >> 1;
    }
  
    return n - (1 << c1) - 
               (1 << (c0 - 1)) + 1;
}
  
// Driver Code
public static void main (String[] args) 
{
  
    int n = 6; // input 1
    System.out.println (getPrev(n));
  
    n = 16; // input 2
    System.out.println(getPrev(n));
      
}
}
  
// This code is contributed by akt_mit


Python3
# Python3 Implementation of Arithmetic Approach to
# getPrev with Smae number of bits 1's is below
  
# Main Function to find next Bigger 
# number Smaller than n
def getPrev(n):
      
    # Compute c0 and c1 and store N
    temp = n
    c0 = 0
    c1 = 0
  
    while ((temp & 1) == 1):
        c1 += 1
        temp = temp >> 1
    if (temp == 0):
        return -1
  
    while (((temp & 1) == 0) and (temp != 0)):
        c0 += 1
        temp = temp >> 1
  
    return n - (1 << c1) - (1 << (c0 - 1)) + 1
  
# Driver Code
if __name__ == '__main__':
    n = 6 # input 1
    print(getPrev(n))
  
    n = 16     # input 2
    print(getPrev(n))
  
# This code is contributed 
# by PrinciRaj1992


C#
// C# Implementation of Arithmetic
// Approach to getPrev with Same
// number of bits 1's is below
using System;
  
class GFG
{
      
// Main Function to find next 
// Bigger number Smaller than n
static int getPrev(int n)
{
    /* Compute c0 and 
    c1 and store N*/
    int temp = n;
    int c0 = 0;
    int c1 = 0;
  
    while ((temp & 1) == 1)
    {
        c1++;
        temp = temp >> 1;
    }
  
    if (temp == 0)
        return -1;
  
    while (((temp & 1) == 0) && 
            (temp!= 0))
    {
        c0++;
        temp = temp >> 1;
    }
  
    return n - (1 << c1) - 
               (1 << (c0 - 1)) + 1;
}
  
// Driver Code
static public void Main ()
{
    int n = 6; // input 1
    Console.WriteLine(getPrev(n));
  
    n = 16; // input 2
    Console.WriteLine(getPrev(n));
}
}
  
// This code is contributed by ajit


PHP


输出:

6
16

获取上一个号码的最佳位处理方法
要实现getPrev,我们遵循非常相似的方法。

  • 计算c0和c1。请注意, c1是尾随的1的数量,而c0是尾随的1左侧紧随其后的零块的大小。
  • 将最右边的非拖尾的1翻转为零。这将在位置p = c1 + c0处。
  • 清除位p右边的所有位。
  • 在位置p的右边立即插入c1 + 1。

请注意,第2步将位p设置为零,而第3步将位0到p-1设置为零。我们可以合并这些步骤。

让我们通过一个例子来完成这个过程。

c1 ==> number of trailing ones
c0 ==> size of the block of zeros immediately 
       to the left of the trailing ones.
p = c1 + c0

步骤1:初始编号:p =7。c1=2。c0= 5。

1   0   0   1   1  1  1  0  0  0  0  0  1  1
13  12  11  10  9  8  7  6  5  4  3  2  1  0

步骤2和3:清除位0到p。

1   0   0   1   1  1  0  0  0  0  0  0  0  0
13  12  11  10  9  8  7  6  5  4  3  2  1  0

我们可以这样做,如下所示:

// Sequence of 1s
int a = ~0;               

// Sequence of 1s followed by p + 1 zeros.
int b = a << (p + 1);     

// Clears bits 0 through p.
n & = b;                  

步骤4:在位置p的右边立即插入c1 + 1。

1   0   0   1   1  1  0  1  1  1  0  0  0  0
13  12  11  10  9  8  7  6  5  4  3  2  1  0

请注意,由于p = c1 + c0,因此(c1 + 1)后面将是(c0 – 1)零。

我们可以这样做,如下所示:

// 0s with 1 at position (c1 + 1)
int a = 1 << (c1 + 1);    

// 0s followed by c1 + 1 ones       
int b = a - 1;                  

// c1 + 1 ones followed by c0 - 1 zeros.
int c = b << (c0 - 1);           
n |= c;

下面是实现此目的的代码。

C++

// C++ Implementation of  getPrev in
// Same number of bits 1's is below
#include 
using namespace std;
  
// Main Function to find next Bigger number
// Smaller than n
int getPrev(int n)
{
    /* Compute c0 and c1  and store N*/
    int temp = n;
    int c0 = 0;
    int c1= 0;
  
    while ((temp & 1) == 1)
    {
        c1++;
        temp = temp >> 1;
    }
  
    if (temp == 0)
        return -1;
  
    while (((temp & 1) == 0) && (temp!= 0))
    {
        c0++;
        temp  = temp >> 1;
    }
  
    // position of rightmost non-trailing one.
    int p = c0 + c1;
  
    // clears from bit p onwards
    n = n & ((~0) << (p + 1));
  
    // Sequence of (c1+1) ones
    int mask = (1 << (c1 + 1)) - 1;
  
    n = n | mask << (c0 - 1);
  
    return n;
}
  
// Driver Code
int main()
{
    int n = 6;   // input 1
    cout << getPrev(n);
  
    n = 16;     // input 2
    cout << endl;
    cout << getPrev(n);
  
    return 0;
}

Java

// Java Implementation of  
// getPrev in Same number
// of bits 1's is below
import java.io.*;
  
class GFG 
{
      
// Main Function to find 
// next Bigger number 
// Smaller than n
static int getPrev(int n)
{
    // Compute c0 and 
    // c1 and store N
    int temp = n;
    int c0 = 0;
    int c1= 0;
  
    while((temp & 1) == 1)
    {
        c1++;
        temp = temp >> 1;
    }
  
    if(temp == 0)
        return -1;
  
    while(((temp & 1) == 0) && 
           (temp!= 0))
    {
        c0++;
        temp = temp >> 1;
    }
  
    // position of rightmost
    // non-trailing one.
    int p = c0 + c1;
  
    // clears from bit p onwards
    n = n & ((~0) << (p + 1));
  
    // Sequence of (c1+1) ones
    int mask = (1 << (c1 + 1)) - 1;
  
    n = n | mask << (c0 - 1);
  
    return n;
}
  
// Driver Code
public static void main(String[] args) 
{
    int n = 6; // input 1
    System.out.println(getPrev(n));
  
    n = 16; // input 2
    System.out.println(getPrev(n));
}
}
  
// This code is contributed by aj_36

C#

// C# Implementation of 
// getPrev in Same number
// of bits 1's is below
using System;
  
class GFG
{
  
// Main Function to find 
// next Bigger number 
// Smaller than n
static int getPrev(int n)
{
    // Compute c0 and 
    // c1 and store N
    int temp = n;
    int c0 = 0;
    int c1 = 0;
  
    while((temp & 1) == 1)
    {
        c1++;
        temp = temp >> 1;
    }
  
    if(temp == 0)
        return -1;
  
    while(((temp & 1) == 0) && 
           (temp != 0))
    {
        c0++;
        temp = temp >> 1;
    }
  
    // position of rightmost
    // non-trailing one.
    int p = c0 + c1;
  
    // clears from 
    // bit p onwards
    n = n & ((~0) << (p + 1));
  
    // Sequence of 
    // (c1+1) ones
    int mask = (1 << (c1 + 1)) - 1;
  
    n = n | mask << (c0 - 1);
  
    return n;
}
  
// Driver Code
static public void Main ()
{
    int n = 6; // input 1
    Console.WriteLine(getPrev(n));
  
    n = 16; // input 2
    Console.WriteLine(getPrev(n));
}
}
  
// This code is contributed by ajit

的PHP

> 1;
    }
  
    if ($temp == 0)
        return -1;
  
    while ((($temp & 1) == 0) && 
            ($temp!= 0))
    {
        $c0++;
        $temp = $temp >> 1;
    }
  
    // position of rightmost
    // non-trailing one.
    $p = $c0 + $c1;
  
    // clears from bit p onwards
    $n = $n & ((~0) << ($p + 1));
  
    // Sequence of (c1 + 1) ones
    $mask = (1 << ($c1 + 1)) - 1;
  
    $n = $n | $mask << ($c0 - 1);
  
    return $n;
}
  
// Driver Code
  
// input 1
$n = 6; 
echo getPrev($n);
  
// input 2
$n = 16;     
echo " \n" ;
echo getPrev($n);
  
// This code is contributed by Ajit
?>

输出 :

5
8

获取下一个数字的算术方法

如果c0是尾随零的数量,c1是紧随其后的1个块的大小,并且p = c0 + c1,我们可以从更早的时候形成我们的解决方案,如下所示:

  1. 将第p位设置为1。
  2. 将p之后的所有位设置为0。
  3. 将位0到c1 – 2设置为1。这将总计c1 – 1。

一种执行步骤1和2的快速方法是将尾随零设置为1(给我们p尾随p),然后加1。加一将翻转所有尾随的0,所以我们在p位的末尾为1 p零。我们可以算术地执行此操作。

//将尾随0设置为1,为我们提供尾随1的p。
n + = 2 c0 – 1;

//将第一个p ls翻转为0s,并在p位置放置1。
n + = 1;

现在,要算术执行步骤3,我们只需执行以下操作:

//将尾随的c1 – 1零设置为1。
n + = 2 c1 – 1 – 1;

该数学公式简化为:
下一个= n +(2 c0 – 1)+ 1 +(2 c1 – 1 – 1)
= n + 2 c0 + 2 c1 – 1 – 1

最好的部分是,通过一点点操作,编写起来很简单。

C++

// C++ Implementation of getNext with
// Same number of bits 1's is below
#include 
using namespace std;
  
// Main Function to find next smallest number
// bigger than n
int getNext(int n)
{
    /* Compute c0 and c1 */
    int c = n;
    int c0 = 0;
    int c1 = 0;
  
    while (((c & 1) == 0) && (c != 0))
    {
        c0 ++;
        c >>= 1;
    }
    while ((c & 1)==1)
    {
        c1++;
        c >>= 1;
    }
  
    // If there is no bigger number with the
    // same no. of 1's
    if (c0 +c1 == 31 || c0 +c1== 0)
        return -1;
  
    return n + (1 << c0) + (1 << (c1 - 1)) - 1;
}
  
// Driver Code
int main()
{
    int n = 5; // input 1
    cout << getNext(n);
  
    n = 8;     // input 2
    cout << endl;
    cout << getNext(n);
    return 0;
}

Java

// Java Implementation of getNext with
// Same number of bits 1's is below
import java.io.*;
  
class GFG 
{
      
// Function to find next smallest 
// number bigger than n
static int getNext(int n)
{
    /* Compute c0 
    and c1 */
    int c = n;
    int c0 = 0;
    int c1 = 0;
  
    while (((c & 1) == 0) && (c != 0))
    {
        c0 ++;
        c >>= 1;
    }
    while ((c & 1) == 1)
    {
        c1++;
        c >>= 1;
    }
  
    // If there is no bigger number 
    // with the same no. of 1's
    if (c0 + c1 == 31 || c0 + c1 == 0)
        return -1;
  
    return n + (1 << c0) + 
               (1 << (c1 - 1)) - 1;
}
  
// Driver Code
public static void main (String[] args) 
{
int n = 5; // input 1
System.out.println(getNext(n));
  
n = 8; // input 2
System.out.println(getNext(n));
}
}
  
// This code is contributed by ajit

C#

// C# Implementation of getNext 
// with Same number of bits 
// 1's is below
using System;
  
class GFG
{
      
// Function to find next smallest 
// number bigger than n
static int getNext(int n)
{
    /* Compute c0 
    and c1 */
    int c = n;
    int c0 = 0;
    int c1 = 0;
  
    while (((c & 1) == 0) && 
            (c != 0))
    {
        c0 ++;
        c >>= 1;
    }
    while ((c & 1) == 1)
    {
        c1++;
        c >>= 1;
    }
  
    // If there is no bigger
    // number with the same
    // no. of 1's
    if (c0 + c1 == 31 ||
        c0 + c1 == 0)
        return -1;
  
    return n + (1 << c0) + 
               (1 << (c1 - 1)) - 1;
}
  
// Driver Code
static public void Main ()
{
    int n = 5; // input 1
    Console.WriteLine(getNext(n));
  
    n = 8; // input 2
    Console.WriteLine(getNext(n));
    }
}
  
// This code is contributed by m_kit

的PHP

>= 1;
    }
    while (($c & 1) == 1)
    {
        $c1++;
        $c >>= 1;
    }
  
    // If there is no bigger 
    // number with the
    // same no. of 1's
    if ($c0 + $c1 == 31 || 
        $c0 + $c1 == 0)
        return -1;
  
    return $n + (1 << $c0) + 
                (1 << ($c1 - 1)) - 1;
}
  
// Driver Code
$n = 5; // input 1
echo getNext($n);
  
$n = 8; // input 2
echo "\n";
echo getNext($n);
  
// This code is contributed by ajit
?>

输出 :

6
16

获取上一个数字的算术方法
如果c1是尾随的个数,c0是紧随其后的零块的大小,并且p = c0 + c1,我们可以用以下方式写出初始getPrev解决方案:

  1. 将pth位设置为0
  2. 将p之后的所有位设置为1
  3. 将位0到c0 – 1设置为0。

我们可以如下算术实现。为了示例清楚起见,我们假设n =10000011。这使c1 = 2和c0 = 5。

// Removes trailing 1s. n is now 10000000.
n -= 2c1 – 1;    

// Flips trailing 0s. n is now 01111111.
n -= 1;    

// Flips last (c0-1) 0s. n is now 01110000.
n -= 2c0 - 1 - 1;    

This reduces mathematically to:
next = n - (2c1 - 1) - 1 - ( 2c0-1 - 1) .
     = n - 2c1 - 2c0-1 + 1;

同样,这很容易实现。

C++

// C++ Implementation of Arithmetic Approach to
// getPrev with Smae number of bits 1's is below
#include 
using namespace std;
  
// Main Function to find next Bigger number
// Smaller than n
int getPrev(int n)
{
    /* Compute c0 and c1  and store N*/
    int temp = n;
    int c0 = 0;
    int c1 = 0;
  
    while ((temp & 1) == 1)
    {
        c1++;
        temp = temp >> 1;
    }
  
    if (temp == 0)
        return -1;
  
    while (((temp & 1) == 0) && (temp!= 0))
    {
        c0++;
        temp  = temp >> 1;
    }
  
    return n - (1 << c1) - (1 << (c0 - 1)) + 1;
}
  
// Driver Code
int main()
{
    int n = 6;   // input 1
    cout << getPrev(n);
  
    n = 16;     // input 2
    cout << endl;
    cout << getPrev(n);
  
    return 0;
}

Java

// Java Implementation of Arithmetic
// Approach to getPrev with Same
// number of bits 1's is below
import java.io.*;
  
class GFG 
{
      
// Main Function to find next 
// Bigger number Smaller than n
static int getPrev(int n)
{
    /* Compute c0 and 
    c1 and store N*/
    int temp = n;
    int c0 = 0;
    int c1 = 0;
  
    while ((temp & 1) == 1)
    {
        c1++;
        temp = temp >> 1;
    }
  
    if (temp == 0)
        return -1;
  
    while (((temp & 1) == 0) && 
            (temp!= 0))
    {
        c0++;
        temp = temp >> 1;
    }
  
    return n - (1 << c1) - 
               (1 << (c0 - 1)) + 1;
}
  
// Driver Code
public static void main (String[] args) 
{
  
    int n = 6; // input 1
    System.out.println (getPrev(n));
  
    n = 16; // input 2
    System.out.println(getPrev(n));
      
}
}
  
// This code is contributed by akt_mit

Python3

# Python3 Implementation of Arithmetic Approach to
# getPrev with Smae number of bits 1's is below
  
# Main Function to find next Bigger 
# number Smaller than n
def getPrev(n):
      
    # Compute c0 and c1 and store N
    temp = n
    c0 = 0
    c1 = 0
  
    while ((temp & 1) == 1):
        c1 += 1
        temp = temp >> 1
    if (temp == 0):
        return -1
  
    while (((temp & 1) == 0) and (temp != 0)):
        c0 += 1
        temp = temp >> 1
  
    return n - (1 << c1) - (1 << (c0 - 1)) + 1
  
# Driver Code
if __name__ == '__main__':
    n = 6 # input 1
    print(getPrev(n))
  
    n = 16     # input 2
    print(getPrev(n))
  
# This code is contributed 
# by PrinciRaj1992

C#

// C# Implementation of Arithmetic
// Approach to getPrev with Same
// number of bits 1's is below
using System;
  
class GFG
{
      
// Main Function to find next 
// Bigger number Smaller than n
static int getPrev(int n)
{
    /* Compute c0 and 
    c1 and store N*/
    int temp = n;
    int c0 = 0;
    int c1 = 0;
  
    while ((temp & 1) == 1)
    {
        c1++;
        temp = temp >> 1;
    }
  
    if (temp == 0)
        return -1;
  
    while (((temp & 1) == 0) && 
            (temp!= 0))
    {
        c0++;
        temp = temp >> 1;
    }
  
    return n - (1 << c1) - 
               (1 << (c0 - 1)) + 1;
}
  
// Driver Code
static public void Main ()
{
    int n = 6; // input 1
    Console.WriteLine(getPrev(n));
  
    n = 16; // input 2
    Console.WriteLine(getPrev(n));
}
}
  
// This code is contributed by ajit

的PHP


输出 :

5
8