📌  相关文章
📜  最小拆分二进制字符串,以使每个子字符串为4或6的幂。

📅  最后修改于: 2021-05-04 20:13:32             🧑  作者: Mango

给定由0和1组成的字符串S。找到最小拆分,以使子字符串是4或6的幂的二进制表示,且没有前导零。如果无法进行此类分区,请打印-1。

例子:

Input: 100110110
Output: 3
The string can be split into a minimum of 
three substrings 100(power of 4), 110
(power of 6) and 110(power of 6).

Input : 00000
Output : -1
0 is not a power of  4 or 6.

推荐:在继续解决方案之前,请先在“实践”上解决它。

一个简单的解决方案是在不同的索引处递归拆分字符串,并检查每个拆分是否为4或6的幂。从索引0开始,然后从其他字符串拆分str [0]。如果它是4或6的幂,则递归调用索引1并执行相同的操作。拆分整个字符串,请检查到目前为止分区的总数是否最小。然后拆分str [0..1],检查它是4还是6的幂,然后递归调用rest 字符串。到目前为止,在字符串遍历结束时比较分区与最小分区。这种方法在时间上将是指数式的。

一个有效的解决方案是使用动态编程。将创建一个一维dp表,其中dp [i]存储将字符串str [i..n-1]拆分为4或6的幂的子字符串所需的最小分区数。假设我们位于索引i和str [i..j]是4或6的幂,则最小分区数将是从中拆分str [j + 1..n-1]的最小分区数加上一个从中拆分str [i..j]的分区字符串,即dp [j + 1] +1。因此(j!=(n-1))和(dp [j + 1]!=-1)的递归关系将是:

执行:

C++
// CPP program for Minimum splits in a 
//string such that substring is a power of 4 or 6.
  
#include 
using namespace std;
  
// Function to find if given number
// is power of another number or not.
bool isPowerOf(long val, int base)
{
  
    // Divide given number repeatedly
    // by base value. 
    while (val > 1) {
        if (val % base != 0)
            return false; // not a power 
        val /= base;
    }
  
    return true;
}
  
// Function to find minimum number of
// partitions of given binary string
// so that each partition is power of 4 or 6. 
int numberOfPartitions(string binaryNo)
{
    int i, j, n = binaryNo.length();
  
    // Variable to store integer value of
    // given binary string partition.
    long val;
  
    // DP table to store results of
    // partitioning done at differentindices.
    int dp[n];
  
    // If the last digit is 1, hence 4^0=1 and 6^0=1
    dp[n - 1] = ((binaryNo[n - 1] - '0') == 0) ? -1 : 1;
  
    // Fix starting position for partition
    for (i = n - 2; i >= 0; i--) {
        val = 0;
  
        // Binary representation
        // with leading zeroes is not allowed. 
        if ((binaryNo[i] - '0') == 0) {
            dp[i] = -1;
            continue;
        }
  
        dp[i] = INT_MAX;
  
        // Iterate for all different partitions starting from i
        for (j = i; j < n; j++) {
  
            // Find integer value of current
            // binary partition.
            val = (val * 2) + (long)(binaryNo[j] - '0');
  
            // Check if the value is a power of 4 or 6 or not
            // apply recurrence relation
            if (isPowerOf(val, 4) || isPowerOf(val, 6)) {
                if (j == n - 1) {
                    dp[i] = 1;
                }
                else {
                    if (dp[j + 1] != -1)
                        dp[i] = min(dp[i], dp[j + 1] + 1);
                }
            }
        }
  
        // If no partitions are possible, then
        // make dp[i] = -1 to represent this.
        if (dp[i] == INT_MAX)
            dp[i] = -1;
    }
  
    return dp[0];
}
  
// Driver code
int main()
{
    string binaryNo = "100110110";
    cout << numberOfPartitions(binaryNo);
    return 0;
}


Java
// Java program for Minimum splits 
// in a string such that substring 
// is a power of 4 or 6.
import java.io.*;
  
class GFG 
{
    static boolean isPowerOf(long val, 
                             int base)
{
  
    // Divide given number 
    // repeatedly by base value. 
    while (val > 1) 
    {
        if (val % base != 0)
            return false; // not a power 
        val /= base;
    }
  
    return true;
}
  
// Function to find minimum 
// number of partitions of 
// given binary string so that
// each partition is power 
// of 4 or 6. 
static int numberOfPartitions(String binaryNo)
{
    int i, j, n = binaryNo.length();
  
    // Variable to store integer
    // value of given binary 
    // string partition.
    long val;
  
    // DP table to store results 
    // of partitioning done at 
    // differentindices.
    int dp[] = new int[n];
  
    // If the last digit is 1, 
    // hence 4^0=1 and 6^0=1
    dp[n - 1] = (((binaryNo.charAt(n - 1) - 
                               '0') == 0) ? 
                                   -1 : 1);
  
    // Fix starting position
    // for partition
    for (i = n - 2; i >= 0; i--) 
    {
        val = 0;
  
        // Binary representation
        // with leading zeroes 
        // is not allowed. 
        if ((binaryNo.charAt(i) - '0') == 0) 
        {
            dp[i] = -1;
            continue;
        }
  
        dp[i] = Integer.MAX_VALUE;
  
        // Iterate for all different
        // partitions starting from i
        for (j = i; j < n; j++) 
        {
  
            // Find integer value of 
            // current binary partition.
            val = (val * 2) + 
                  (long)(binaryNo.charAt(j) - '0');
  
            // Check if the value is a 
            // power of 4 or 6 or not
            // apply recurrence relation
            if (isPowerOf(val, 4) || 
                isPowerOf(val, 6))
            {
                if (j == n - 1)
                {
                    dp[i] = 1;
                }
                else 
                {
                    if (dp[j + 1] != -1)
                        dp[i] = Math.min(dp[i], 
                                         dp[j + 1] + 1);
                }
            }
        }
  
        // If no partitions are possible, 
        // then make dp[i] = -1 to 
        // represent this.
        if (dp[i] == Integer.MAX_VALUE)
            dp[i] = -1;
    }
  
    return dp[0];
}
  
// Driver code
public static void main (String[] args) 
{
    String binaryNo = "100110110";
    System.out.println(numberOfPartitions(binaryNo));
}
}
  
// This code is contributed
// by shiv_bhakt.


Python 3
# Python 3 program for Minimum
# splits in a string such that
# substring is a power of 4 or 6.
  
import sys
  
# Function to find if given number
# is power of another number or not.
def isPowerOf(val, base):
  
    # Divide given number repeatedly
    # by base value. 
    while (val > 1):
        if (val % base != 0):
            return False # not a power 
        val //= base
  
    return True
  
# Function to find minimum number of
# partitions of given binary string
# so that each partition is power of 4 or 6. 
def numberOfPartitions(binaryNo):
  
    n = len(binaryNo)
  
    # DP table to store results of
    # partitioning done at differentindices.
    dp = [0] * n
  
    # If the last digit is 1, hence 4^0=1 and 6^0=1
    if ((ord(binaryNo[n - 1]) - ord('0')) == 0) :
        dp[n - 1] = -1
    else:
        dp[n - 1] = 1
  
    # Fix starting position for partition
    for i in range( n - 2, -1, -1):
        val = 0
  
        # Binary representation
        # with leading zeroes is not allowed. 
        if ((ord(binaryNo[i]) - ord('0')) == 0):
            dp[i] = -1
            continue
  
        dp[i] = sys.maxsize
  
        # Iterate for all different partitions starting from i
        for j in range(i, n):
  
            # Find integer value of current
            # binary partition.
            val = (val * 2) + (ord(binaryNo[j]) - ord('0'))
  
            # Check if the value is a power of 4 or 6 or not
            # apply recurrence relation
            if (isPowerOf(val, 4) or isPowerOf(val, 6)):
                if (j == n - 1):
                    dp[i] = 1
                  
                else :
                    if (dp[j + 1] != -1):
                        dp[i] = min(dp[i], dp[j + 1] + 1)
  
        # If no partitions are possible, then
        # make dp[i] = -1 to represent this.
        if (dp[i] == sys.maxsize):
            dp[i] = -1
  
    return dp[0]
  
# Driver code
if __name__ == "__main__":
      
    binaryNo = "100110110"
    print(numberOfPartitions(binaryNo))
      
# This code is contributed by Ita_c.


C#
// C# program for Minimum splits 
// in a string such that substring 
// is a power of 4 or 6.
  
using System;
   
class GFG 
{
    static bool isPowerOf(long val, int b)
{
   
    // Divide given number 
    // repeatedly by base value. 
    while (val > 1) 
    {
        if (val % b != 0)
            return false; // not a power 
        val /= b;
    }
   
    return true;
}
   
// Function to find minimum 
// number of partitions of 
// given binary string so that
// each partition is power 
// of 4 or 6. 
static int numberOfPartitions(string binaryNo)
{
    int i, j, n = binaryNo.Length;
   
    // Variable to store integer
    // value of given binary 
    // string partition.
    long val;
   
    // DP table to store results 
    // of partitioning done at 
    // differentindices.
    int[] dp = new int[n];
   
    // If the last digit is 1, 
    // hence 4^0=1 and 6^0=1
    dp[n - 1] = (((binaryNo[n - 1] - 
                               '0') == 0) ? 
                                   -1 : 1);
   
    // Fix starting position
    // for partition
    for (i = n - 2; i >= 0; i--) 
    {
        val = 0;
   
        // Binary representation
        // with leading zeroes 
        // is not allowed. 
        if ((binaryNo[i] - '0') == 0) 
        {
            dp[i] = -1;
            continue;
        }
   
        dp[i] = int.MaxValue;
   
        // Iterate for all different
        // partitions starting from i
        for (j = i; j < n; j++) 
        {
   
            // Find integer value of 
            // current binary partition.
            val = (val * 2) + 
                  (long)(binaryNo[j] - '0');
   
            // Check if the value is a 
            // power of 4 or 6 or not
            // apply recurrence relation
            if (isPowerOf(val, 4) || 
                isPowerOf(val, 6))
            {
                if (j == n - 1)
                {
                    dp[i] = 1;
                }
                else
                {
                    if (dp[j + 1] != -1)
                        dp[i] = Math.Min(dp[i], 
                                         dp[j + 1] + 1);
                }
            }
        }
   
        // If no partitions are possible, 
        // then make dp[i] = -1 to 
        // represent this.
        if (dp[i] == int.MaxValue)
            dp[i] = -1;
    }
   
    return dp[0];
}
   
// Driver code
public static void Main () 
{
    string binaryNo = "100110110";
    Console.Write(numberOfPartitions(binaryNo));
}
}


输出:

3

时间复杂度: O(n ^ 2 * log(x)),x =可从输入字符串获得4或6的最大幂。
辅助空间: O(n)