检查是否可以对二进制字符串进行分区,使每个分区的幂为5

时间:2015-08-26 00:26:56

标签: algorithm recursion dynamic-programming

我最近遇到了这个问题 - 给定一个二进制字符串,检查我们是否可以将字符串分割/拆分为0..n部分,使每个部分的幂为5.返回最小分割数,如果可以的话。

例子如下:

input = "101101" - returns 1, as the string can be split once to form "101" and "101",as 101= 5^1.
input = "1111101" - returns 0, as the string itself is 5^3.
input = "100"- returns -1, as it can't be split into power(s) of 5.

我提出了这种递归算法:

  1. 检查字符串本身是否为5的幂。如果是,则返回0
  2. 否则,逐字符遍历字符串,检查每个点是否到目前为止看到的数字是5的幂。如果是,则将1加到拆分计数并递归检查字符串的其余部分以获得5的幂从第1步开始。
  3. 返回到目前为止看到的最小分割数。
  4. 我在Java中实现了上述算法。我相信它可行,但它是一个简单的递归解决方案。这可以通过动态编程来解决,以改善运行时间吗?

    代码如下:

    public int partition(String inp){
        if(inp==null || inp.length()==0)
            return 0;
        return partition(inp,inp.length(),0);
    }
    public int partition(String inp,int len,int index){
        if(len==index)
            return 0;
        if(isPowerOfFive(inp,index))
            return 0;
        long sub=0;
        int count = Integer.MAX_VALUE;
        for(int i=index;i<len;++i){
            sub = sub*2 +(inp.charAt(i)-'0');
            if(isPowerOfFive(sub))
                count = Math.min(count,1+partition(inp,len,i+1));
        }
        return count;
    }
    

    助手功能:

    public boolean isPowerOfFive(String inp,int index){
        long sub = 0;
        for(int i=index;i<inp.length();++i){
            sub = sub*2 +(inp.charAt(i)-'0');
        }
        return isPowerOfFive(sub);
    }
    
    public boolean isPowerOfFive(long val){
        if(val==0)
            return true;
        if(val==1)
            return false;
        while(val>1){
            if(val%5 != 0)
                return false;
            val = val/5;
        }
        return true;
    }
    

2 个答案:

答案 0 :(得分:1)

您只需在地图中保存给定字符串的值即可。例如,如果你有一个像这样结束的字符串:(每个字母可以是一个任意大小的字符串)

ABCD

您发现部分A mod 5没问题,因此您再次尝试BCD,但发现B mod 5也正常,C和{{1}也一样}以及D在一起。现在您应该缓存以下结果:

CD

但是你还没有完成C -> 0 D -> 0 CD -> 0 BCD -> 1 # split B/CD is the best - 你发现ABCD没问题,所以你检查结果AB mod 5 - 它已经在缓存中而你不必从一开始就处理它。

实际上,您只需要缓存来自CD的答案 - 无论是实际字符串还是partition()元组。哪一个更好取决于你有多少重复序列,以及比较内容或只是索引更快。

答案 1 :(得分:0)

以下是C ++中的解决方案。使用动态编程我正在考虑所有可能的分裂并保存最佳结果。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int isPowerOfFive(ll n)
{
    if(n == 0) return 0;
    ll temp = (ll)(log(n)/log(5));
    ll t = round(pow(5,temp));
    if(t == n)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
ll solve(string s) 
{
    vector<ll> dp(s.length()+1);
    for(int i = 1; i <= s.length(); i++)
    {
        dp[i] = INT_MAX;
        for(int j = 1; j <= i; j++)
        {
            if( s[j-1] == '0')
            {
                continue;
            }
            ll num = stoll(s.substr(j-1, i-j+1), nullptr, 2);
            if(isPowerOfFive(num))
            {
                dp[i] = min(dp[i], dp[j-1]+1);
            }
        }
    }
    if(dp[s.length()] == INT_MAX)
    {
        return -1;
    }
    else
    {
        return dp[s.length()];
    }
}
int main()
{
    string s;
    cin>>s;
    cout<<solve(s);
}