返回格式良好的数字

时间:2011-06-12 01:33:48

标签: algorithm performance python

我在面试问题论坛中找到了这个:

  

写一个函数返回格式良好   数量n。形成良好   数字是一个数字i较少的数字   比数i + 1,例如123,246,349等

所以这就是我在Python中的表现:

  
      
  • 输入位数(x)
  •   
  • 循环遍历所有x位数
  •   
  • 对于每个数字n,如果str(n)==“”。join(sorted(str(n))),则打印数量
  •   

所以我的问题是......这种方法是否有效且pythonic?我相信应该有一个更优雅的方式,所以任何提示都会非常感激。

克雷格

6 个答案:

答案 0 :(得分:7)

这个解决方案怎么样?

[int("".join(x)) for x in itertools.combinations("123456789", n)]

答案 1 :(得分:2)

在我看来,如果你检查每个号码,你已经输了。

我用堆栈实现它。首先将1-9放在堆栈上。当您从堆栈中取出一个数字时,如果您可以遵循这些规则,请为其添加另一个数字。如果是n位数,则打印出来。如果它不是n位数,请将其放回堆栈。

假设你从筹码中抓到7。 8和9是唯一大于7的数字,因此在o(1)时间内你可以将78和79放在堆栈上。

答案 2 :(得分:0)

您的实施不能确保数字位数,或严格小于部分的格式要求。


无论如何,这是一种有效的方法来生成没有任何库函数的序列(转换为python留给读者练习):

void find_well_formed(char* pfirst, char* pnext, int min, int slack, int digits_left)
{
    if (!digits_left) puts(pfirst);
    else for( int i = 0; i <= slack; ++i )
        find_well_formed(pfirst, pnext+1, (*pnext=min+i)+1, slack - i, digits_left-1);
}

char* result = malloc(n+2);
result[n] = '\n';
find_well_formed(&result[0], &result[0], '1', 9-n, n);
free(result);

演示:http://ideone.com/0oZAV

如果python需要更多的代码来解决这个问题而不是C ++,那就错了。

答案 3 :(得分:0)

1)你试图在你的方法中将结构良好的数字返回到'n位数,这可能不是他们要求的东西

2)对该范围内的每个数字进行排序有点傻。您可以通过比较连续数字来检查每个数字是否是格式良好的数字,每个数字需要O(d)个时间。但是,排序肯定会花费更多。

答案 4 :(得分:0)

我的想法是遵循逻辑:

  • 对于给定的数字,我们可以添加到它的开头但仍然得到格式正确的数字的数字都小于数字中的最小数字
  • 对于给定的格式良好的数字,最小数字始终是第一个数字
  • 我们可以添加到给定数字并保持格式良好的最大位数等于它(最小数字 - 1)

鉴于上述情况,可以使用以下方法解决问题:

def _well_formed_numbers(current_number_str, size):
    if size == 0: 
        # we don't need to add any more
        return [current_number_str]
    if(len(current_number_str) == 0):
        min_digit = 9
    else:
        min_digit = int(current_number_str[0]) - 1
    if min_digit < size: 
        raise Exception("can't add " + str(size) + " more digits to " + current_number_str)
    # Return a list of all the numbers resulting from recursively applying 
    # this function to the "children" of the number we already have
    # Children are the input number with one valid digit added to the beginning
    # valid digits are [size .. min_digit], inclusive
    return reduce(lambda x,y: x+y, [_well_formed_numbers(str(digit) + str(current_number_str), size-1) for digit in range(size,min_digit+1)])

def well_formed_numbers(size):
    if size <= 0 or size >= 10:
        raise "invalid size for perfect number: " + str(size)
    return _well_formed_numbers("", size)

if __name__ == '__main__':
    import unittest
    class Tests(unittest.TestCase):
        def testMaxList(self):
            self.assertEqual(["123456789"], well_formed_numbers(9))

        def testEightList(self):
            self.assertEqual(sorted(['12345678', '12345679', '12345689', '12345789', '12346789', '12356789', '12456789', '13456789', '23456789']), sorted(well_formed_numbers(8)))

        def testOneList(self):
            self.assertEqual(sorted(["1","2","3","4","5","6","7","8","9"]), sorted(well_formed_numbers(1)))

        def testTwoList(self):
            self.assertEqual(sorted(['12', '13', '23', '14', '24', '34', '15', '25', '35', '45', '16', '26', '36', '46', '56', '17', '27', '37', '47', '57', '67', '18', '28', '38', '48', '58', '68', '78', '19', '29', '39', '49', '59', '69', '79', '89']), sorted(well_formed_numbers(2)))

    unittest.main()

不可否认,Sven Marnach的答案更短更聪明......但是这个答案显示了合理算法的思维过程。

答案 5 :(得分:0)

我建议如下:

第i位的最大值是max [i] = 10 - (len - i)

  • 以1..n
  • 开头
  • 在每一步,找到最左边的位置i,其中digit [i] == max [i]
  • 如果找不到这样的i,请增加最右边的数字
  • 如果我找到了,它是= 0,我们就完成了
  • 如果我找到了,那就是&gt; 0,增加数字[i - 1]并填充其余部分,使数字[j] =数字[j - 1] + 1

(故意丑陋的)python

a = [1, 2, 3]
n = len(a)

while 1:
    print a
    f = 0
    for i in range(n):
        if a[i] == 10 - (n - i):
            if i == 0:
                exit()
            else:
                f = 1
                a[i - 1] += 1
                for j in range(i, n):
                    a[j] = a[j - 1] + 1
                break

    if f == 0:
        a[n - 1] += 1