38. Count and Say [easy] (Python)

来源:互联网 发布:linux考试认证 编辑:程序博客网 时间:2024/06/05 08:42

题目链接

https://leetcode.com/problems/count-and-say/

题目原文

The count-and-say sequence is the sequence of integers beginning as follows:
1, 11, 21, 1211, 111221, ...

1 is read off as "one 1" or 11.
11 is read off as "two 1s" or 21.
21 is read off as "one 2, then one 1" or 1211.
Given an integer n, generate the nth sequence.

Note: The sequence of integers will be represented as a string.

题目翻译

一个”数和说(count and say)“序列是像这样的一个整数序列:1, 11, 21, 1211, 111221, ...
1 读作 "1个1"11.
11 读作 "2个1"21.
21 读作 "1个2,1个1"1211.
给定整数n,生成第n个序列。
注意:整数序列用字符串表示。

思路方法

这个问题重点首先是要读懂题目。然后在想这个过程的时候,你可能会想的比较复杂,比如,会不会出现连续十几个一样的数字,比如1111111111,读作“ten 1”,然后转换成101。实际上,有大神已经证明,这个序列里的数不会超过4。这边搬运了一下。
原链接:https://leetcode.com/discuss/6762/how-to-proof-the-count-is-always-less-than-10

Proof by exhaustion and contrapositive:

In order for a number greater than 4 to be created, there must be a series of numbers n>4 in length all the same digit. Therefore, there is a subset of that series where the count would only reach 4. Because of this, any proof for the existence of a chain resulting in a number greater than 4 is also a proof for the existence of a 4-chain. Using the proof by contrapositive, this means that if 4-chains are proved to be impossible, then any n-chain with n>4 is also impossible.

In order to start with a chain with numbers greater than 4, you must assume that a 4-chain is possible in the first place, which is circular reasoning, and so cannot be used as an initial point. It is further impossible to have a negative value, since the counting numbers do not include them.

Therefore, the only chains able to create a 4 (at least the first one) are 0000, 1111, 2222, or 3333.

0 0 0 0 -> 40
The 0000 is read zero 0, zero 0, which must come from . Since there is nothing present, it could in theory occur anywhere in the string. However, since they would be next to each other, if the 0 is repeated as would be neccessary, the zeros would add together, resulting in just zero 0, leaving only 20, not 40.

1 1 1 1 -> 41
The 1111 is read one 1, one 1 (or 11), which translates to 21, not 1111. This contradicts the assumption that there is a way to get 1111, and so prevents 4 or greater from appearing. Therefore, 1s cannot reach 4.

2 2 2 2 -> 42
The 2222 is read two 2, two 2 (or 22 22), which is identical to the output. Since the input maps to itself, there is no way to leave that cycle, or it already would have. If 2222 exists in the input, then 2222 must have mapped to it. It cannot reach 42. Therefore, 2s cannot reach 4.

3 3 3 3 -> 43
The 3333 is read three 3, three 3 (or 333 333). This in turn would require 333 333 333. This fails in two respects. First, that the previous inputs would not merge to 63 or 93. The second, that the sequence eventually traces back to the origin, 1. Since it keeps increasing in length as the number of rounds since the start decreases, it cannot have started at 1. Therefore, 3s cannot reach 4.

As every possible case has been examined, and none can reach a 4 while starting at the given beginning (1), it is not possible for a 4-chain to occur, meaning a 4 cannot appear in any valid string for this problem. Further, as stated above, since a 4-chain is impossible, so too are all n-chains with n>4, so no number greater than 4 can appear either.

思路一

根据题目描述的过程写代码,完全遵照规则写就行了。所以要用到三个循环,最外层是生成第几个序列;中间层用于遍历一个序列;最内层找出连续相同的几个数字。

代码

class Solution(object):    def countAndSay(self, n):        """        :type n: int        :rtype: str        """        res = '1'        for i in xrange(n-1):            new_res = ''            j = 0            while j < len(res):                count = 1                while j < len(res)-1 and res[j] == res[j+1]:                    j = j + 1                    count = count + 1                j = j + 1                new_res = new_res + str(count) + res[j-1]            res = new_res        return res

思路二

当然,其实最内层和中间层不需要分开写,用一个pre变量存放上一个字符即可。

代码

class Solution(object):    def countAndSay(self, n):        """        :type n: int        :rtype: str        """        res = '1'        for i in xrange(n-1):            new_res, pre, count = '', res[0], 0            for j in xrange(len(res)):                if res[j] == pre:                    count += 1                else:                    new_res += str(count) + pre                    count = 1                    pre = res[j]            res = new_res + str(count) + pre        return res

思路三

其实Python有个itertools.groupby()可以帮助我们数连着的数字,所以代码可以精简很多。

代码

class Solution(object):    def countAndSay(self, n):        """        :type n: int        :rtype: str        """        res = '1'        for i in xrange(n-1):            res = ''.join([str(len(list(group))) + digit for digit, group in itertools.groupby(res)])        return res

PS: 新手刷LeetCode,新手写博客,写错了或者写的不清楚还请帮忙指出,谢谢!
转载请注明:http://blog.csdn.net/coder_orz/article/details/51702322

0 0