计算将一串数字分成26以下的数字的方法

时间:2015-04-16 05:06:06

标签: c++ algorithm

给定一串数字,我希望找到将字符串分解为单个数字的方式,以便每个数字都在26以下。

例如," 8888888"只能分解为" 8 8 8 8 8 8 8"。鉴于" 1234567"可以分解为" 1 2 3 4 5 6 7"," 12 3 4 5 6 7"和" 1 23 4 5 6 7"。

我既喜欢解决方案的递归关系,也喜欢使用动态编程的一些代码。

这是我到目前为止所得到的。它只涵盖了一个空字符串的基本情况应该返回1一个数字的字符串应该返回1并且所有大于2的数字的字符串应该返回1.

int countPerms(vector<int> number,  int currentPermCount)
{
    vector< vector<int> > permsOfNumber;
    vector<int> working;
    int totalPerms=0, size=number.size();
    bool areAllOverTwo=true, forLoop = true;

    if (number.size() <=1)
    { 
        //TODO: print out permetations
        return 1;
    }
    for (int i = 0; i < number.size()-1; i++) //minus one here because we dont care what the last digit is if all of them before it are over 2 then there is only one way to decode them
    {
        if (number.at(i) <= 2)
        {
            areAllOverTwo = false;
        }
    }
    if (areAllOverTwo) //if all the nubmers are over 2 then there is only one possable combination 3456676546 has only one combination.
    {
        permsOfNumber.push_back(number);
        //TODO: write function to print out the permetions
        return 1;
    }
    do
    {
        //TODO find all the peremtions here
    } while (forLoop);

    return totalPerms;
}

3 个答案:

答案 0 :(得分:2)

假设您没有零,或者您不允许带前导零的数字),则重复关系为:

N(1aS) = N(S) + N(aS)
N(2aS) = N(S) + N(aS) if a < 6.
N(a) = 1
N(aS) = N(S) otherwise

此处,a表示单个数字,S表示数字。递归关系的第一行表示如果你的字符串以1开头,那么你可以自己拥有它,或者将它与下一个数字连接起来。第二行说明如果你从一个2开始,你可以自己拥有它,或者将它与下一个数字连接,假设它给出的数字小于26.第三行是终止条件:当你'下降到1位数,结果是1.最后一行说如果你不能匹配以前的规则之一,那么第一个数字不能连接到第二个数字,所以它必须站在它的上面自己的。

可以相当直接地实现递归关系作为迭代动态编程解决方案。这是Python中的代码,但很容易翻译成其他语言。

def N(S):
    a1, a2 = 1, 1
    for i in xrange(len(S) - 2, -1, -1):
        if S[i] == '1' or S[i] == '2' and S[i+1] < '6':
            a1, a2 = a1 + a2, a1
        else:
            a1, a2 = a1, a1
    return a1

print N('88888888')
print N('12345678')

输出:

1
3

一个有趣的观察结果是N('1' * n)是第n + 1'个斐波纳契数:

for i in xrange(1, 20):
    print i, N('1' * i)

输出:

1 1
2 2
3 3
4 5
5 8
6 13
7 21
8 34
9 55

答案 1 :(得分:1)

如果我理解正确,只有25种可能性。我的第一个解决方案是将一个25个整数的数组初始化为零,当我找到一个小于25的数字时,将该索引设置为1.然后,当我看完该数据后,我会计算数组中的所有1字符串。

复发意味着什么?如果您正在寻找递归函数,则需要找到一种以递归方式打破数字串的好方法。我不确定这是最好的方法。我会直接逐个数字,如你所说,如果数字是2或更少,然后存储它并测试附加下一个数字...即10 *数字+下一个。我希望有所帮助!祝你好运。

答案 2 :(得分:1)

考虑它的另一种方法是,在最初的单个数字可能性之后,对于长度为n的每个连续可能的数字对(例如,111或12223)的每个序列,我们将结果乘以:

1 + sum, i=1 to floor (n/2), of (n-i) choose i

例如,序列号为11111,我们可以

i=1, 1 1 1 11 => 5 - 1 = 4 choose 1 (possibilities with one pair)
i=2, 1 11 11 => 5 - 2 = 3 choose 2 (possibilities with two pairs)

这似乎与维基百科对斐波那契数字的描述直接相关。 &#34;在数学中使用,&#34;例如,计算&#34; 1和2的组合数量总和为给定的总数n&#34; http://en.wikipedia.org/wiki/Fibonacci_number)。

使用组合方法(或其他快速斐波那契方法)可能适用于序列很长的字符串。