📌  相关文章
📜  求和为二进制字符串S所需的最小操作数

📅  最后修改于: 2021-06-25 22:11:19             🧑  作者: Mango

给定一个二进制字符串S。找到将转换为S表示的数字所需的最小操作数。

允许执行两种类型的操作:

  • 2 x
  • 2 x

注意:从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现场课程美国》。