• 60第K个排列


    题目:给出集合 [1,2,3,…,n],其所有元素共有 n! 种排列。按大小顺序列出所有排列情况,并一一标记,当 n = 3 时, 所有排列如下:
        "123"
        "132"
        "213"
        "231"
        "312"
        "321"
    给定 n 和 k,返回第 k 个排列。
    说明:给定 n 的范围是 [1, 9]。给定 k 的范围是[1,  n!]。

    来源: https://leetcode-cn.com/problems/permutation-sequence/

    法一:自己的代码    耗时很短,利用python自带的阶乘函数计算耗时会更短

    思路:转化为一个纯数学的问题,关键是要把每种情况都考虑到,特别是除n!后是整数的情况,举例的时候就要把每种情况都枚举到,编程才不会出错

    import math
    class Solution:
        def getPermutation(self, n: int, k: int):
            # 自定义阶乘函数
            def n_factorial(x):
                if x == 0:
                    return 1
                else:
                    return x * n_factorial(x-1)
            nums = [i+1 for i in range(n)]
            result = ''
            while n > 0:
                n = n - 1
                # 通过观察数据可以看出,假如输入是(4,9),则说明以1开头的有3!个,以2开头的有3!个,
                # 所以用9除以3的阶乘是1.5,1,5向上取整为2,即nums中的第二个数2是结果中的第一个数,
                # 再用9减去6为3表示从2开始的组别中找第三个数,
                res = k / n_factorial(n)
                res_up = math.ceil(res)
                # 注意这里向下取整必须是向上取整后减1,这是因为比如输入的是(4,6),则6除3!为1,1-1=0,所以不可直接向下取整
                res_down = res_up - 1
                k = k - res_down * n_factorial(n)
                result = result + str(nums[res_up-1])
                del nums[res_up-1]
                print('-'* 20)
                print('k', k)
                # print(res)
                print(res_up)
                # print(res_down)
            return result
    if __name__ == "__main__":
        duixiang = Solution()
        a = duixiang.getPermutation(4,9)
        print(a)
    View Code

    法二:自己的代码    利用回溯,但是超时,超时是因为没有用continue,每个分支都要检查一遍

    class Solution:
        def getPermutation(self, n: int, k: int):
            nums = [i+1 for i in range(n)]
            global count,result
            count = 0
            def backtrack(a='', nums=nums, ):
                global count,result
                # print('k',count)
                if count == k:
                    return
                if len(a) == n:
                    count += 1
                    # print('count', count)
                    if count == k:
                        result = a
                        # exit()
                    # return count
                for i,j in enumerate(nums):
                    r = nums.copy()
                    del r[i]
                    # print('ttt',count)
                    # sign,result = backtrack(a+str(j), r)
                    backtrack(a+str(j), r)
            backtrack()
            return result
    View Code

    改进后的不会超时,注意这里return的用法,非常巧妙

    class Solution:
        def getPermutation(self, n: int, k: int):
            nums = [i+1 for i in range(n)]
            from1to9_factorial = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
            def backtrack(a='', nums=nums,k = k ):
                # 一旦满足条件立即逐层返回a,结束所有函数
                if len(a) == n:
                    return a
                t = from1to9_factorial[len(nums) - 1]
                for i,j in enumerate(nums):
                    if k > t:
                        # 执行剪枝操作,如果大于t了,就结束本次循环
                        k = k - t
                        continue
                    # r中是下次for循环要遍历的数
                    r = nums.copy()
                    del r[i]
                    # 这里必须用return,避免了定义全局变量来解决问题
                    return backtrack(a+str(j), r, k)
            return backtrack()
    if __name__ == "__main__":
        duixiang = Solution()
        a = duixiang.getPermutation(4,10)
        print(a)
    View Code
  • 相关阅读:
    c#读取Excel并显示出来
    异步编程模型。
    细分线程的等待(WaitAny,WaitAll),区别于Thread.Join
    waitany,waitall在线程池中的使用。from msdn
    SQL SET NOCOUNT ON的含义和作用
    MS ゴシック与MS UI Gothic的区别
    线程的管理1
    HDU 1203 I NEED A OFFER!(背包)
    hdu 1232 畅通工程
    POJ 1088 滑雪
  • 原文地址:https://www.cnblogs.com/xxswkl/p/11949915.html
Copyright © 2020-2023  润新知