Range Extraction (Codewars 4kyu Python)

题目:

A format for expressing an ordered list of integers is to use a comma separated list of either

individual integers
or a range of integers denoted by the starting integer separated from the end integer in the range by a dash, ‘-’. The range includes all integers in the interval including both endpoints. It is not considered a range unless it spans at least 3 numbers. For example (“12, 13, 15-17”)
Complete the solution so that it takes a list of integers in increasing order and returns a correctly formatted string in the range format.

Example:

solution([-6, -3, -2, -1, 0, 1, 3, 4, 5, 7, 8, 9, 10, 11, 14, 15, 17, 18, 19, 20])
# returns "-6,-3-1,3-5,7-11,14,15,17-20"

我的思路:

题目让我们把连续的n个数字简写成一个区间,如1,2,3,4 变成 1-4。由于我们需要看到下一个数字,才能判断前一个数字是省略还是加入list,所以我用了两个指针last和now,指向list里前后两个相邻的数字。如果出现了两个相邻的数字,则第二个数字有被省略的可能性,而如果出现三个连续的数字,则中间那个一定被省略。所以我使用了两个标记,记录当前的状态,potential 和 omit,分别表示,当前数字有可能被省略和正在当前数字正在被省略过程中。

我的解答:

def solution(args):
    length = len(args)
    if length <= 2:
        return ",".join(args)
    args.append(0)
    last = args[0]
    now = args[1]
    potential = 0
    omit = 0
    result = str(args[0])
    for i in range(1,length+1):
        print(args[i])
        now = args[i]
        if now - last == 1 and potential == 0 and omit == 0:
            potential = 1
        elif now - last == 1 and potential == 1 and omit == 0:
            omit = 1
            potential = 0
            result += "-"
        elif now - last == 1 and potential == 0 and omit == 1:
            pass
        elif now - last != 1 and omit == 1:
            omit = 0
            result = result + str(last) + "," + str(now)
        elif now - last != 1 and potential == 1:
            potential = 0
            result = result + "," + str(last) + "," + str(now)
        else:
            result = result +  "," + str(now)
        last = args[i]
    return result[:-2]

Most Clever:

做完题目看一下题后投票clever最多的答案:

def solution(args):
    out = []
    beg = end = args[0]
    
    for n in args[1:] + [""]:        
        if n != end + 1:
            if end == beg:
                out.append( str(beg) )
            elif end == beg + 1:
                out.extend( [str(beg), str(end)] )
            else:
                out.append( str(beg) + "-" + str(end) )
            beg = n
        end = n
    
    return ",".join(out)

为了防止溢出,我在args后append了一个0,他在args后加了一个"",空的字符串。

他用了两个指针,beg(begin) 和 end,表示连续数字的开头和结尾。根据开头和结尾的差值来分类讨论:如果开头结尾相等(不连续),将该数字直接加入out列表;如果开头结尾相差1(有且仅有两个数字连续),将开头结尾两个数字都加入out列表;如果开头结尾相差1以上(有两个以上数字连续),将开头结尾两个数字中间加一个 “-” ,然后加入out列表。

总结:

两种方法思路一致,但Most Clever的实现方式比我清晰简洁很多。我的指针间距永远是1,即每往后一位,都分类讨论,显示在最后return的结果中。而他的两个指针代表着每一段的开头和结尾,每一段成型后再加入return的结果中,这样跟方便分类讨论,不需要加入额外的变量来标记状态。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值