Leetcode1415-长度为 n 的开心字符串中字典序第 k 小的字符串(Python3实现)
Posted 大师的试炼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode1415-长度为 n 的开心字符串中字典序第 k 小的字符串(Python3实现)相关的知识,希望对你有一定的参考价值。
题目描述:
一个 「开心字符串」定义为:
- 仅包含小写字母 [\'a\', \'b\', \'c\'].
- 对所有在 1 到 s.length - 1 之间的 i ,满足 s[i] != s[i + 1] (字符串的下标从 1 开始)。
比方说,字符串 "abc","ac","b" 和 "abcbabcbcb" 都是开心字符串,但是 "aa","baa" 和 "ababbc" 都不是开心字符串。
给你两个整数 n 和 k ,你需要将长度为 n 的所有开心字符串按字典序排序。
请你返回排序后的第 k 个开心字符串,如果长度为 n 的开心字符串少于 k 个,那么请你返回空字符串 。
示例 2:
输入:n = 1, k = 4
输出:""
解释:长度为 1 的开心字符串只有 3 个。
示例 3:
输入:n = 3, k = 9
输出:"cab"
解释:长度为 3 的开心字符串总共有 12 个 ["aba", "abc", "aca", "acb", "bab", "bac", "bca", "bcb", "cab", "cac", "cba", "cbc"] 。第 9 个字符串为 "cab"。
示例 5:
输入:n = 10, k = 100
输出:"abacbabacb"
代码:
class Solution: def getHappyString(self, n: int, k: int) -> str: def add(array): #因为k值大小必定是小于等于所有情况数的 #所以,当array长度为1时,此时array值必定只能为\'a\'或\'b\',只要进行直接更新即可 if len(array)==1: if array[-1]==\'a\': return [\'b\'] else: return [\'c\'] #当array长度大于1时,就分情况进行讨论 ##第1,2种情况:[a,b],[b,a],直接更新最后一位为\'c\'即可 if (array[-2]==\'a\' and array[-1]==\'b\') or (array[-2]==\'b\' and array[-1]==\'a\'): array[-1]=\'c\' return array #第3种情况:[c,a],直接更新最后一位为\'b\'即可 elif array[-2]==\'c\' and array[-1]==\'a\': array[-1]=\'b\' return array #第4,5,6种情况:[a,c],[b,c],[c,b],其中[a,c]情况得到的最后一位必定是\'a\',后两种的最后一位更新情况需要根据倒数第二位决定 else: tmp=add(array[:-1]) return tmp + [\'b\'] if tmp[-1]==\'a\' else tmp + [\'a\'] #字符串每增加一位长度,情况*2 allCases=3*(2**(n-1)) #判定n,k是否符合条件 if allCases<k or n<1 or k<0: return "" #生成第一种情况的字符串 arr=[\'a\'] for i in range(1,n): arr.append(\'a\') if arr[-1]!=\'a\' else arr.append(\'b\') #循环k-1次得到第k次的结果 for i in range(1,k): arr=add(arr) return \'\'.join(arr)
LeetCode判定结果:
解题思路2:
第二种思路是看了大佬的解法自己重新整理复现的:
如果把字符串第一位看成是3进制,之后的所有位数都是2进制的数值(称之为2.3进制),就能直接将k-1转化为2.3进制,加到0000000...000(对应字符串abababa...)上,直接得到对应的字符串。
其中定义第一位上的进制转换为:0->a,1->b,2->c,其他位置上的数值对应为:
前一位若为a,则当前位0->b,1->c;
前一位若为b,则当前位0->a,1->c;
前一位若为c,则当前位0->a,1->b;
代码:
class Solution: def getHappyString(self, n: int, k: int) -> str: #在2.3进制下第一个数为(00000...00),对应为(ababab...) #对于第k个字符串,相当于进行k-1次的+1操作,即对数(0000...000)加上k-1的二进制值,最后根据规则直接生成字符串 addNum = k - 1 charList=[\'a\',\'b\',\'c\'] chrMap = { \'a\' : [\'b\', \'c\'], \'b\' : [\'a\', \'c\'], \'c\' : [\'a\', \'b\'], } #将k-1转换为二进制,其中所有字符串的情况有3*(2**(n-1)) bit = [] for i in range(n-1): bit.append(addNum % 2) addNum = addNum // 2 #如果此时addNum还是大于2(第一位是3进制的),说明字符串第一位需要进行进位,溢出返回 if addNum > 2: return \'\' else: bit.append(addNum) #数组反向,生成k-1的二进制值 bit=bit[::-1] #第一个数字是三进制的,0对应a,1对应b,2对应c arr=[] arr.append(charList[bit[0]]) for i in range(1,n): arr.append(chrMap[arr[-1]][bit[i]]) return \'\'.join(arr)
该方法的速度更快,LeetCode上表现接近双一百。
以上是关于Leetcode1415-长度为 n 的开心字符串中字典序第 k 小的字符串(Python3实现)的主要内容,如果未能解决你的问题,请参考以下文章
数据结构与算法之深入解析“长度为n的开心字符串中字典序第k小的字符串”的求解思路与算法示例