给定数字之间的最小位交换以使其按位或等于按位与
给定两个正整数A和B,任务是计算所需的最小操作数,使得A和B的按位或等于A和B的按位与相等,即(A&B)=(A|B) ,其中,在每个操作选择两个索引i和j并且第i个 A的位与B的第j位交换。如果不可能使(A&B)=(A|B),则打印 -1。
例子:
Input: A = 1, B = 2
Output: 2
Explanation:
A10 ≡ 012, B10 ≡ 102
The following sequence of moves can be performed:
- i = 1, j = 1⇒ A = 11, B = 00 (A|B = 3, A&B = 0).
- i = 1, j = 0⇒ A = 01, B = 01 (A|B = 1, A&B = 1).
Thus, 2 moves are required.
Input: A = 27, B = 5
Output: 3
Explanation:
A10 ≡ 110112, B10 ≡ 001012
The following sequence of moves can be performed:
- i = 4, j = 3⇒ A = 01011, B = 01101 (A|B = 15, A&B = 9).
- i = 2, j = 2⇒ A = 01111, B = 01001 (A|B = 15, A&B = 9).
- i = 2, j = 1⇒ A = 01011, B = 01011 (A|B = 11, A&B = 11).
Thus, 3 moves are required.
方法:
观察:解决这个问题的主要观察是对于 (A&B)=(A|B) 是 A 必须等于 B,因为如果只设置了两个位,那么只有它们的位与和位或相等。
请按照以下步骤解决问题:
- 计算A和B中的总设置位数。
- 如果计数是奇数,则两个数不能相等,所以打印 -1。
- 初始化两个计数器oneZero =0 和zeroOne =0
- 遍历A和B的位,并执行以下操作:
- 如果A的当前位已设置而B的当前位未设置,即 (1, 0),则递增oneZero 。
- 如果A的当前位未设置而B的当前位已设置,即 (0, 1),则递增zeroOne 。
- 为了最小化所需的操作数量,最好选择两个 (1, 0) 或两个 (0, 1) 索引并交换其中一个,即只需要oneZero和zeroOne操作的一半。
- 如果oneZero是奇数(这意味着zeroOne也是奇数),则需要再进行两次操作才能将 (0, 1) 和 (1, 0) 变为 (1, 1) 和 (0, 0)
- 所以,最终的答案是(oneZero/2)+(zeroOne/2)+(oneZero%2?2:0)。
下面是上述方法的实现:
C++
// C++ implementation of the above approach
#include
using namespace std;
// Function for counting number of set bit
int countSetBits(int n)
{
int count = 0;
while (n) {
n = n & (n - 1);
count++;
}
return count;
}
// Function to return the count of
// minimum operations required
int minOperations(int A, int B)
{
// cnt to count the number of bits
// set in A and in B
int cnt1 = 0, cnt2 = 0;
cnt1 += countSetBits(A);
cnt2 += countSetBits(B);
// if odd numbers of total set bits
if ((cnt1 + cnt2) % 2 != 0)
return -1;
// one_zero = 1 in A and 0 in B at ith bit
// similarly for zero_one
int oneZero = 0, zeroOne = 0;
int ans = 0;
for (int i = 0; i < max(cnt1, cnt2); i++) {
int bitpos = 1 << i;
// When bitpos is set in B, unset in B
if ((!(bitpos & A)) && (bitpos & B))
zeroOne++;
// When bitpos is set in A, unset in B
if ((bitpos & A) && (!(bitpos & B)))
oneZero++;
}
// number of moves is half of
// number pairs of each group
ans = (zeroOne / 2) + (oneZero / 2);
// odd number pairs
if (zeroOne % 2 != 0)
ans += 2;
return ans;
}
// Driver code
int main()
{
// Input
int A = 27, B = 5;
// Function call to compute the result
cout << minOperations(A, B);
return 0;
}
Java
// Java program for the above approach
import java.io.*;
class GFG{
// Function for counting number of set bit
static int countSetBits(int n)
{
int count = 0;
while (n != 0) {
n = n & (n - 1);
count++;
}
return count;
}
// Function to return the count of
// minimum operations required
static int minOperations(int A, int B)
{
// cnt to count the number of bits
// set in A and in B
int cnt1 = 0, cnt2 = 0;
cnt1 += countSetBits(A);
cnt2 += countSetBits(B);
// if odd numbers of total set bits
if ((cnt1 + cnt2) % 2 != 0)
return -1;
// one_zero = 1 in A and 0 in B at ith bit
// similarly for zero_one
int oneZero = 0, zeroOne = 0;
int ans = 0;
for (int i = 0; i < Math.max(cnt1, cnt2); i++) {
int bitpos = 1 << i;
// When bitpos is set in B, unset in B
if (((bitpos & A) == 0) && ((bitpos & B) != 0))
zeroOne++;
// When bitpos is set in A, unset in B
if (((bitpos & A) != 0) && ((bitpos & B) == 0))
oneZero++;
}
// number of moves is half of
// number pairs of each group
ans = (zeroOne / 2) + (oneZero / 2);
// odd number pairs
if (zeroOne % 2 != 0)
ans += 2;
return ans;
}
// Driver Code
public static void main(String args[])
{
// Input
int A = 27, B = 5;
// Function call to compute the result
System.out.println( minOperations(A, B));
}
}
// This code is contributed by splevel62.
Python3
# Python3 implementation of the above approach
# Function for counting number of set bit
def countSetBits(n):
count = 0
while (n):
n = n & (n - 1)
count += 1
return count
# Function to return the count of
# minimum operations required
def minOperations(A, B):
# cnt to count the number of bits
# set in A and in B
cnt1 = 0
cnt2 = 0
cnt1 += countSetBits(A)
cnt2 += countSetBits(B)
# If odd numbers of total set bits
if ((cnt1 + cnt2) % 2 != 0):
return -1
# one_zero = 1 in A and 0 in B at ith bit
# similarly for zero_one
oneZero = 0
zeroOne = 0
ans = 0
for i in range(max(cnt1, cnt2)):
bitpos = 1 << i
# When bitpos is set in B, unset in B
if ((not(bitpos & A)) and (bitpos & B)):
zeroOne += 1
# When bitpos is set in A, unset in B
if ((bitpos & A) and (not(bitpos & B))):
oneZero += 1
# Number of moves is half of
# number pairs of each group
ans = (zeroOne // 2) + (oneZero // 2)
# Odd number pairs
if (zeroOne % 2 != 0):
ans += 2
return ans
# Driver code
if __name__ == '__main__':
# Input
A = 27
B = 5
# Function call to compute the result
print(minOperations(A, B))
# This code is contributed by mohit kumar 29
C#
// C# implementation of the above approach
using System;
using System.Collections.Generic;
class GFG{
// Function for counting number of set bit
static int countSetBits(int n)
{
int count = 0;
while (n > 0)
{
n = n & (n - 1);
count++;
}
return count;
}
// Function to return the count of
// minimum operations required
static int minOperations(int A, int B)
{
// cnt to count the number of bits
// set in A and in B
int cnt1 = 0, cnt2 = 0;
cnt1 += countSetBits(A);
cnt2 += countSetBits(B);
// If odd numbers of total set bits
if ((cnt1 + cnt2) % 2 != 0)
return -1;
// one_zero = 1 in A and 0 in B at ith bit
// similarly for zero_one
int oneZero = 0, zeroOne = 0;
int ans = 0;
for(int i = 0; i < Math.Max(cnt1, cnt2); i++)
{
int bitpos = 1 << i;
// When bitpos is set in B, unset in B
if (((bitpos & A) == 0) && (bitpos & B) != 0)
zeroOne++;
// When bitpos is set in A, unset in B
if ((bitpos & A) != 0 && ((bitpos & B) == 0))
oneZero++;
}
// Number of moves is half of
// number pairs of each group
ans = (zeroOne / 2) + (oneZero / 2);
// Odd number pairs
if (zeroOne % 2 != 0)
ans += 2;
return ans;
}
// Driver code
public static void Main()
{
// Input
int A = 27, B = 5;
// Function call to compute the result
Console.Write(minOperations(A, B));
}
}
// This code is contributed by bgangwar59
Javascript
输出
3
时间复杂度: O(Log 2 N)
辅助空间: O(1)