深信服笔试--递归用法
1、已知某一个字母序列,把序列中的字母按出现顺序压入一个栈,在入栈的任意过程中,允许栈中的字母出栈,求所有可能的出栈顺序
思路:
遍历序列中的每一个字母,先把当前字母入栈,这个时候,栈中肯定有字母,你可以选择继续遍历序列,也可以在这个时候把栈中的字母一个一个出栈,
最后,遍历完序列后,再把栈中的所有字母顺序出栈,这样子就可以得到所有合法的序列;
1 #import itertools 2 def GetAllSeq(input, i, stk, tmp, res): 3 tmp1 = list(tmp) # 注意tmp1和stk是要回溯的,所以这两者不能传引用;而res是一直保留结果的,传引用就对 4 stk1 = list(stk) 5 if i == len(input): # 结果记录 6 stk1 = stk1[::-1] 7 tmp1.extend(stk1) 8 res.append(tmp1) 9 #print(res) 10 return 11 stk1.append(input[i]) # 先将当前字母入栈,然后后面选择继续递归入栈或者出栈 12 GetAllSeq(input, i+1, stk1, tmp1, res) #继续遍历 13 while stk1: # 一个个出栈 14 #tmp = [] 15 tmp1.append(stk1[-1]) 16 stk1.pop() 17 GetAllSeq(input, i+1, stk1, tmp1, res) 18 19 20 21 input = 'abc' 22 res = [] 23 stk = '' 24 tmp = '' 25 GetAllSeq(input, 0, stk, tmp, res) 26 27 res = [''.join(x) for x in res] 28 # 法一 29 # res = list(set(res)) 30 # res.sort() 31 32 # 法二 33 #res = itertools.groupby(res) 34 35 # 法三 dict去重并保留顺序 36 # res = list(dict.fromkeys(res)) 37 # print(res)
2、函数match检查字符串str是否匹配模板pattern,匹配则返回0,否则返回-1。模板支持普通字符(a-z0-9A-Z)及通配符?和*。普通字符匹配该字符本身,?匹配任意一个字符,*匹配任意多个任意字符。
思路:使用递归回溯遍历所有的情况
def match(str, pattern): str_len, pattern_len = len(str), len(pattern) if not str_len and not pattern_len: return 0 if not str_len or not pattern_len: return -1 if pattern[0] == '*': #如果是*则前者递归k个单位(k进行迭代遍历取值),后者递归一个单位 for i in range(len(str)): if match(str[i+1:], pattern[1:]) == 0: # 递归 return 0 return -1 elif pattern[0] == '?': # 如果是?则两者都递归一个单位 return match(str[1:], pattern[1:]) else: if pattern[0] == str[0]: # 如果是相同则两者都递归一个单位 return match(str[1:], pattern[1:]) else: return -1 str = input() pattern = input() res = match(str, pattern) print(res) if res == 0: print('match') elif res == -1: print('unmat
3、有K种颜色的小球(K<=10),每种小球有若干个,总数小于100个。
现在有一个小盒子,能放N个小球(N<=8),现在要从这些小球里挑出N个小球,放满盒子。
想知道有哪些挑选方式。注:每种颜色的小球之间没有差别。
请按数字递增顺序输出挑选小球的所有方式。
如有3种颜色,每种颜色小球的个数分别为a:1,b:2,c:3,挑出3个小球的挑法有:
003,012,021,102,111,120
思路:递归回溯,my_dic, res, s都可变,s用来保存理想结果,注意s的现场恢复
# K, N = list(map(int, input().split())) # def bfs(i, my_dic, cnt, res, s): # if i == K and cnt == N: # res.append(''.join(s)) # elif i < K: # for use in range(my_dic[i]+1): # 迭代递归:先迭代整个串,然后再递归每个子集 # if use <= N - cnt: # s.append(str(use)) # bfs(i+1, my_dic, cnt+use, res, s) # s.pop() #回溯 # else: # break # my_dic = {} # for i in range(K): # my_dic[i] = int(input()) # res = [] # bfs(0, my_dic, 0, res, []) # for r in res: # print(r) a = [0] * 11 ans = [0] * 11 def Print(k, ans): res = '' for i in range(k): res += str(ans[i]) print(res) def fun(i, n): if n == 0: Print(k, ans) return if n < 0 or k == i: return for j in range(a[i]+1): ans[i] = j fun(i+1, n-j) ans[i] = 0 #回溯 k,n = list(map(int, input().split())) a = {} for i in range(k): a[i] = int(input()) fun(0, n)
4、判断所给的字符串是否由所给的词典中的若干个词组成。
如已知词典["code", "sangfor", "org"]
则字符串"codesangfororg" 由上述词典组成,
字符串"codesangforsangfororg" 也由上述词典组成,
但字符串"sangforcom" 则不由上述词典组成。
def wordbreak(s, WordDict): if not s or not len(s): return False dp = [False for i in range(len(s)+1)] dp[0] = True for i in range(1, len(s)+1): # 迭代递归:先迭代遍历整个串,然后再对每个子串进行递归遍历 for j in range(i): if dp[j] and (s[j:i] in WordDict): dp[i] = True break return dp[len(s)] K = int(input()) WordDict = [] for i in range(K): WordDict.append(input()) s = input() res = wordbreak(s, WordDict) print(res)
5、总结
先看问题是否是求整体字符串中的可变长子集(起始点不确定),如果是则先迭代遍历整个串,然后在递归每个子串,如3、4题;
如果是起始点确定的可变长子集,如2题,则可以不用迭代遍历整个串,只需要递归遍历子串就行。