字母按字母顺序排列的可能子字符串列表。递归

时间:2018-05-16 14:25:20

标签: python recursion

我遇到了这个question而这one都指向同一个练习。我想做同样的事情,但使用递归。

我想返回满足此条件的完整字符串中可能的子字符串列表: 所有字母都按字母顺序排列。

例如,如果完整字符串为'abca',则该函数应以任何顺序返回['a', 'b', 'c' , 'ab', 'bc', 'abc']

我的函数尝试从完整字符串num中获取长度s的子字符串数。它不起作用。结果总是一个空列表。它永远不会进入第一个if语句。请指出我错在哪里。我用来调用函数的语句是:

print(recursion('abca',3))

def recursion(s, num):
    wrds = []    

    if num > 1:
        if num <= len(s) - 1:
            num -= 1
            wrds.extend(recursion(s, num))
            return wrds
        else:
            for starting_position in range(len(s) - num):
                for counter in range(num):
                    if s[starting_position + counter] < s[starting_position+counter - 1]:
                        wrds.append(s[:(starting_position + counter + 1)])
                        return wrds
    else:
        return wrds

5 个答案:

答案 0 :(得分:2)

这不是最佳解决方案,尤其是在Python中。然而,为了给你这个想法,我想根据你的代码给你一个解决方案。

基本上,在while=True循环中,我将初始starting_position设置为0并开始获取长度为num的子字符串,直到我超出范围,即num+starting_position>len(s)。在那之后,我退出while=True循环并继续下一个重新执行功能。

def recursion(s, num):
    wrds = []

    if num < 1 or num > len(s)-1:
        return wrds

    starting_position = 0
    while True:
        counter = 0
        if num+starting_position<=len(s):
            next_substring = s[starting_position:(starting_position + num)]
            print("appending %s stpos: %d" % (next_substring, starting_position))
            wrds.append(next_substring)
            counter += 1
        else:
            print("out of limit! exiting while loop.")
            break
        starting_position += 1
        if starting_position == len(s):
            break
    wrds.extend(recursion(s, num-1))
    return wrds


arr = recursion("abca", 3)
print(arr)

打印

appending abc stpos: 0
appending bca stpos: 1
out of limit! exiting while loop.
appending ab stpos: 0
appending bc stpos: 1
appending ca stpos: 2
out of limit! exiting while loop.
appending a stpos: 0
appending b stpos: 1
appending c stpos: 2
appending a stpos: 3
['abc', 'bca', 'ab', 'bc', 'ca', 'a', 'b', 'c', 'a']

编辑:如果你想找到按字母顺序排序的子串,我也写了这个解决方案。基本上,我再次从num开始遍历窗口大小starting_position的每个子字符串。但是,我遍历char by char以验证next_substring_candidate是按字母顺序排序的单词。我希望代码输出能帮助您清楚地理解。

def recursion(s, num):
    wrds = []

    if num < 1 or num > len(s)-1:
        return wrds

    starting_position = 0
    while True:
        counter = 0
        if num+starting_position<=len(s):
            next_substring_candidate = s[starting_position]
            print("starting with %s!" % next_substring_candidate)
            for i in range(1, num):
                next_letter = s[starting_position+i]
                previous_letter = s[starting_position+i-1]
                print("next letter: %s, previous letter: %s" % (next_letter, previous_letter))
                if next_letter >= previous_letter:
                    print("yes! adding next letter (%s) to word (%s)!" % (next_letter,next_substring_candidate))
                    next_substring_candidate += next_letter
                else:
                    print("no! next letter (%s) is smaller than previous (%s)!" % (next_letter, previous_letter))
                    break

            if len(next_substring_candidate) != num:
                print("skipping this substring because not enough length! (%s)" % next_substring_candidate)
                starting_position += 1
                if starting_position == len(s):
                    break
                continue
            if next_substring_candidate not in wrds:
                print("adding new substring to list! (%s)" % next_substring_candidate)
                wrds.append(next_substring_candidate)
            counter += 1
        else:
            print("out of limit! exiting while loop.")
            break
        starting_position += 1
        if starting_position == len(s):
            break
    wrds.extend(recursion(s, num-1))
    return wrds


arr = recursion("abca", 3)
print(arr)

观察代码输出以查看其工作原理:

yilmazali@yilmazali:~/stackoverflow_tests$ python3 sotestrecur.py 
starting with a!
next letter: b, previous letter: a
yes! adding next letter (b) to word (a)!
next letter: c, previous letter: b
yes! adding next letter (c) to word (ab)!
adding new substring to list! (abc)
starting with b!
next letter: c, previous letter: b
yes! adding next letter (c) to word (b)!
next letter: a, previous letter: c
no! next letter (a) is smaller than previous (c)!
skipping this substring because not enough length! (bc)
out of limit! exiting while loop.
starting with a!
next letter: b, previous letter: a
yes! adding next letter (b) to word (a)!
adding new substring to list! (ab)
starting with b!
next letter: c, previous letter: b
yes! adding next letter (c) to word (b)!
adding new substring to list! (bc)
starting with c!
next letter: a, previous letter: c
no! next letter (a) is smaller than previous (c)!
skipping this substring because not enough length! (c)
out of limit! exiting while loop.
starting with a!
adding new substring to list! (a)
starting with b!
adding new substring to list! (b)
starting with c!
adding new substring to list! (c)
starting with a!
['abc', 'ab', 'bc', 'a', 'b', 'c']
yilmazali@yilmazali:~/stackoverflow_tests$ 

答案 1 :(得分:1)

好的,所以我只是给你一个不依赖递归的解决方案 (由于函数调用的大量开销,通常递归在python中很糟糕)。它不是基于你的,但希望你能得到什么呢?

def alph_substr(s):

    all_substr = []
    itr = iter(s)
    prev = next(itr)
    current_substr = [prev]

    for char in itr:
        if char >= prev:
            current_substr.append(char)
        else:
            all_substr.append(current_substr)
            current_substr = [char]
        prev = char

    all_substr.append(current_substr)

    all_substr = [''.join(substr) for substr in all_substr]
    for substr in all_substr.copy():
        for length in range(1, len(substr)):
            for index in range(len(substr) - length + 1):
                all_substr.append(substr[index:index+length])

    return set(all_substr)

并测试:

alph_substr('helloworld')

输出

{'d',
 'e',
 'el',
 'ell',
 'ello',
 'ellow',
 'h',
 'l',
 'll',
 'llo',
 'llow',
 'lo',
 'low',
 'o',
 'or',
 'ow',
 'r',
 'w'}

答案 2 :(得分:1)

感谢大家的意见。根据你的答案,我找到了一个解决方案:

def recursion(s,num):
    wrds = []    

    if num<1:
        return wrds

    for starting_position in range(len(s)-num):
            for counter in range(num):
                if s[starting_position+counter]>=s[starting_position+counter-1]:
                    wrds.append(s[starting_position:starting_position+counter+1])
                else:
                    wrds.extend(recursion(s[1:],num))
                    return wrds

    wrds.extend(recursion(s,num-1))
    return list(set(wrds))

答案 3 :(得分:1)

我们可以通过假设从第一个字符开始以递增的长度呈现子字符串来编写纯递归(一个函数,一个参数)。

Python代码:

def f(s):
  if len(s) < 2:
    return [s]

  rest = f(s[1:])

  if s[0] > s[1]:
    return [s[0]] + rest

  else:
    updates = [s[0]]
    i = 0

    while i < len(rest) and i < len(rest[i]):
      updates.append(s[0] + rest[i])
      i = i + 1

    return updates + rest

输出:

 > f('abca')
=> ['a', 'ab', 'abc', 'b', 'bc', 'c', 'a']

 > f('cdeabc')
=> ['c', 'cd', 'cde', 'd', 'de', 'e', 'a', 'ab', 'abc', 'b', 'bc', 'c']

答案 4 :(得分:0)

我不愿意直接给你解决方案。但是在调试代码时,请尝试以下方法:

def generateComb(s,num):
    wrds = []    
    print "s ", s
    x = len(s)
    for i in range(1 << x):
        str = [s[j] for j in range(x) if (i & (1 << j))]
        if len(str) > num:
            break
        print "".join(str)



generateComb("abcd", 2)