• 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"
    解题思路1:
    1、先根据n值建立第一种情况('ababa...',长度为n)。
    2、根据k值,进行k-1次循环,直至得到第k次的结果。
    3、每次循环中,针对最后两位的情况分六种情况讨论:
    1)针对([a,b],[b,a],[c,a])三种情况,直接对最后一位进行更新,即b->c,a->c,a->b。
    2)同时针对其中的三种情况([a,c],[b,c],[c,b]),利用递归进行倒数第二位的更新,同时根据倒数第二位的结果更新最后一位。

    代码:

    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上表现接近双一百。

  • 相关阅读:
    Codeforces Round #417 C. Sagheer and Nubian Market
    linux 终端抓包命令
    计算机网络体系结构分析
    排序算法-快速排序
    排序算法-堆排序
    排序算法-希尔排序
    排序算法-插入排序
    排序算法-冒泡排序
    排序算法-选择排序
    杂谈:终端小工具
  • 原文地址:https://www.cnblogs.com/lhdb/p/12748395.html
Copyright © 2020-2023  润新知