给定一个由 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) 的递推关系为:
dp[i] = min(dp[i], 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));
}
}
Javascript
输出:
3
时间复杂度: O(n^2*log(x)),x = 从输入字符串可获得的 4 或 6 的最大幂。
辅助空间: O(n)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。