给定一个二进制字符串S。找到将零转换为S表示的数字所需的最小操作数。
允许执行两种类型的操作:
- 加2 x
- 减2 x
注意:从0开始执行操作。
例子:
Input : 100
Output : 1
Explanation: We just perform a single operation, i.e Add 4 (2^2)
Input : 111
Output : 2
Explanation: We perform the following two operations:
1) Add 8(2^3)
2) Subtract 1(2^0)
这个想法是使用动态编程来解决这个问题。
注意:在下面的分析中,我们认为所有二进制字符串都从LSB到MSB(从LHS到RHS)表示,即2(二进制形式:“ 10”)表示为“ 01”。
让给定的二进制字符串为S。
令dp [i] [0]代表制作二进制字符串R所需的最小操作数,以使R [0…i]与S [0…i]相同且R [i + 1…] =“ 00”。 .0”
同样,让dp [i] [1]代表生成二进制字符串R所需的最小操作数,以使R [0…i]与S [0…i]相同,并且R [i + 1…] =“ 11 ..1”
如果S i为’0’,则dp [i] [0] = dp [i – 1] [0]。由于我们不需要任何其他操作。现在我们考虑dp [i] [1]的值,这有点棘手。对于dp [i] [1],我们可以仅通过使dp [i-1] [1]形成的字符串的第i个字符为’0’来从dp [i – 1] [1]过渡。从更早的时候开始,第i个字符就是“ 1”。我们只需要从dp [i-1] [0]表示的字符串减去2 i即可。因此,我们执行的操作不同于dp [i-1] [0]表示的操作。
另一个转换可以来自dp [i-1] [0]。令dp [i-1] [1]代表字符串R。那么我们需要保持R [i] = 0,因为它已经存在,但是R [i +1 …..]当前为“ 000..0”,需要将其更改为“ 111…1”,这可以通过从R中减去2 (i + 1)来完成。因此,我们只需要除dp [i-1] [0]所表示的操作之外的一项操作即可。
当S i为“ 1”时,情况类似。
最终答案是由dp [1-1] [0]表示的答案,其中l是二进制字符串S的长度。
下面是上述方法的实现:
C++
// CPP program to find the minimum number
// of operations required to sum to N
#include
using namespace std;
// Function to return the minimum operations required
// to sum to a number reprented by the binary string S
int findMinOperations(string S)
{
// Reverse the string to consider
// it from LSB to MSB
reverse(S.begin(), S.end());
int n = S.length();
// initialise the dp table
int dp[n + 1][2];
// If S[0] = '0', there is no need to
// perform any operation
if (S[0] == '0') {
dp[0][0] = 0;
}
else {
// If S[0] = '1', just perform a single
// operation(i.e Add 2^0)
dp[0][0] = 1;
}
// Irrespective of the LSB, dp[0][1] is always
// 1 as there is always the need of making the
// suffix of the binary string of the form "11....1"
// as suggested by the definition of dp[i][1]
dp[0][1] = 1;
for (int i = 1; i < n; i++) {
if (S[i] == '0') {
// Transition from dp[i - 1][0]
dp[i][0] = dp[i - 1][0];
/* 1. Transition from dp[i - 1][1] by just doing
1 extra operation of subtracting 2^i
2. Transition from dp[i - 1][0] by just doing
1 extra operation of subtracting 2^(i+1) */
dp[i][1] = 1 + min(dp[i - 1][1], dp[i - 1][0]);
}
else {
// Transition from dp[i - 1][1]
dp[i][1] = dp[i - 1][1];
/* 1. Transition from dp[i - 1][1] by just doing
1 extra operation of adding 2^(i+1)
2. Transition from dp[i - 1][0] by just doing
1 extra operation of adding 2^i */
dp[i][0] = 1 + min(dp[i - 1][0], dp[i - 1][1]);
}
}
return dp[n - 1][0];
}
// Driver Code
int main()
{
string S = "100";
cout << findMinOperations(S) << endl;
S = "111";
cout << findMinOperations(S) << endl;
return 0;
}
Java
// Java program to find the minimum number
// of operations required to sum to N
class GFG
{
// Function to return the minimum operations required
// to sum to a number reprented by the binary string S
static int findMinOperations(String S)
{
// Reverse the string to consider
// it from LSB to MSB
S = reverse(S);
int n = S.length();
// initialise the dp table
int dp[][] = new int[n + 1][2];
// If S[0] = '0', there is no need to
// perform any operation
if (S.charAt(0) == '0')
{
dp[0][0] = 0;
}
else
{
// If S[0] = '1', just perform a single
// operation(i.e Add 2^0)
dp[0][0] = 1;
}
// Irrespective of the LSB, dp[0][1] is always
// 1 as there is always the need of making the
// suffix of the binary string of the form "11....1"
// as suggested by the definition of dp[i][1]
dp[0][1] = 1;
for (int i = 1; i < n; i++)
{
if (S.charAt(i) == '0')
{
// Transition from dp[i - 1][0]
dp[i][0] = dp[i - 1][0];
/* 1. Transition from dp[i - 1][1] by just doing
1 extra operation of subtracting 2^i
2. Transition from dp[i - 1][0] by just doing
1 extra operation of subtracting 2^(i+1) */
dp[i][1] = 1 + Math.min(dp[i - 1][1], dp[i - 1][0]);
}
else
{
// Transition from dp[i - 1][1]
dp[i][1] = dp[i - 1][1];
/* 1. Transition from dp[i - 1][1] by just doing
1 extra operation of adding 2^(i+1)
2. Transition from dp[i - 1][0] by just doing
1 extra operation of adding 2^i */
dp[i][0] = 1 + Math.min(dp[i - 1][0], dp[i - 1][1]);
}
}
return dp[n - 1][0];
}
static String reverse(String input)
{
char[] temparray = input.toCharArray();
int left, right = 0;
right = temparray.length - 1;
for (left = 0; left < right; left++, right--)
{
// Swap values of left and right
char temp = temparray[left];
temparray[left] = temparray[right];
temparray[right] = temp;
}
return String.valueOf(temparray);
}
// Driver Code
public static void main(String[] args)
{
String S = "100";
System.out.println(findMinOperations(S));
S = "111";
System.out.println(findMinOperations(S));
}
}
// This code is contributed by
// PrinciRaj1992
Python3
# Python3 program to find the minimum
# number of operations required to sum to N
# Function to return the minimum
# operations required to sum to a
# number reprented by the binary string S
def findMinOperations(S) :
# Reverse the string to consider
# it from LSB to MSB
S = S[: : -1]
n = len(S)
# initialise the dp table
dp = [[0] * 2] * (n + 1)
# If S[0] = '0', there is no need
# to perform any operation
if (S[0] == '0') :
dp[0][0] = 0
else :
# If S[0] = '1', just perform a
# single operation(i.e Add 2^0)
dp[0][0] = 1
# Irrespective of the LSB, dp[0][1] is
# always 1 as there is always the need
# of making the suffix of the binary
# string of the form "11....1" as
# suggested by the definition of dp[i][1]
dp[0][1] = 1
for i in range(1, n) :
if (S[i] == '0') :
# Transition from dp[i - 1][0]
dp[i][0] = dp[i - 1][0]
"""
1. Transition from dp[i - 1][1]
by just doing 1 extra operation
of subtracting 2^i
2. Transition from dp[i - 1][0] by
just doing 1 extra operation of
subtracting 2^(i+1)
"""
dp[i][1] = 1 + min(dp[i - 1][1],
dp[i - 1][0])
else :
# Transition from dp[i - 1][1]
dp[i][1] = dp[i - 1][1];
"""
1. Transition from dp[i - 1][1] by
just doing 1 extra operation
of adding 2^(i+1)
2. Transition from dp[i - 1][0] by
just doing 1 extra operation
of adding 2^i
"""
dp[i][0] = 1 + min(dp[i - 1][0],
dp[i - 1][1])
return dp[n - 1][0]
# Driver Code
if __name__ == "__main__" :
S = "100"
print(findMinOperations(S))
S = "111";
print(findMinOperations(S))
# This code is contributed by Ryuga
C#
// C# program to find the minimum number
// of operations required to sum to N
using System;
class GFG
{
// Function to return the minimum
// operations required to sum
// to a number reprented by
// the binary string S
static int findMinOperations(String S)
{
// Reverse the string to consider
// it from LSB to MSB
S = reverse(S);
int n = S.Length;
// initialise the dp table
int [,]dp = new int[n + 1, 2];
// If S[0] = '0', there is no need to
// perform any operation
if (S[0] == '0')
{
dp[0, 0] = 0;
}
else
{
// If S[0] = '1', just perform a single
// operation(i.e Add 2^0)
dp[0, 0] = 1;
}
// Irrespective of the LSB, dp[0,1] is always
// 1 as there is always the need of making the
// suffix of the binary string of the form "11....1"
// as suggested by the definition of dp[i,1]
dp[0, 1] = 1;
for (int i = 1; i < n; i++)
{
if (S[i] == '0')
{
// Transition from dp[i - 1,0]
dp[i, 0] = dp[i - 1, 0];
/* 1. Transition from dp[i - 1,1] by just doing
1 extra operation of subtracting 2^i
2. Transition from dp[i - 1,0] by just doing
1 extra operation of subtracting 2^(i+1) */
dp[i, 1] = 1 + Math.Min(dp[i - 1, 1], dp[i - 1, 0]);
}
else
{
// Transition from dp[i - 1,1]
dp[i, 1] = dp[i - 1, 1];
/* 1. Transition from dp[i - 1,1] by just doing
1 extra operation of adding 2^(i+1)
2. Transition from dp[i - 1,0] by just doing
1 extra operation of adding 2^i */
dp[i, 0] = 1 + Math.Min(dp[i - 1, 0], dp[i - 1, 1]);
}
}
return dp[n - 1, 0];
}
static String reverse(String input)
{
char[] temparray = input.ToCharArray();
int left, right = 0;
right = temparray.Length - 1;
for (left = 0; left < right; left++, right--)
{
// Swap values of left and right
char temp = temparray[left];
temparray[left] = temparray[right];
temparray[right] = temp;
}
return String.Join("",temparray);
}
// Driver Code
public static void Main()
{
String S = "100";
Console.WriteLine(findMinOperations(S));
S = "111";
Console.WriteLine(findMinOperations(S));
}
}
//This code is contributed by 29AjayKumar
PHP
1
2
时间复杂度:O(n)
辅助空间:O(n)
如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。