• 526优美的排列


    题目:假设有从 1 到 N 的 N 个整数,如果从这 N 个数字中成功构造出一个数组,使得数组的第 i 位 (1 <= i <= N) 满足如下两个条件中的一个,我们就称这个数组为一个优美的排列。条件:a>第 i 位的数字能被 i 整除  b>i 能被第 i 位上的数字整除现在给定一个整数 N,请问可以构造多少个优美的排列?
    来源:https://leetcode-cn.com/problems/beautiful-arrangement/

    法一:自己的代码   回溯法  时间上击败百分之60

    思路:遍历回溯,先取一个数字放在第一位上看是否满足如果满足,回溯遍历剩下的,否则结束

    class Solution:
        def countArrangement(self, N: int) -> int:
            results = [0]
            # 逆序遍历更省时间
            nums = [N-i for i in range(N)]
            print(nums)
            def backtrack(a=[], nums=nums, index=0):
                if len(a) == N:
                    results[0] = results[0] + 1
                    return
                index += 1
                for i,j in enumerate(nums):
                    # 剪枝条件,如果不满足,直接进入下一个循环
                    if (j % index == 0) | ( index % j == 0):
                        b = nums.copy()
                        del b[i]
                        backtrack(a+[j],nums=b,index=index)
                    else:
                        continue
            backtrack()
            return results[0]
    
    if __name__ == '__main__':
        duixiang = Solution()
        a = duixiang.countArrangement(15)
        print(a)
    View Code

    改进后的思路:由于满足每个index的数不用,如给的是8,则第三位只能是1 3 6这个三个数,其它的数不需要遍历,每个位置遍历的数都是满足这个位置的和已经用过的差集,提交后超时

    class Solution:
        def countArrangement(self, N: int) -> int:
            results = [0]
            nums = [N-i for i in range(N)]
            # nums = [i+1 for i in range(N)]
            print(nums)
            # 求数n的所有因子,但不包括n,因为下面的index_multiple中已经包括了
            def find_factor(n):
                res = []
                if n == 1:
                    return set([1])
                for i in range(1,n):
                    if n % i == 0:
                        res.append(i)
                return set(res)
            # 求index到N之间,所有index的倍数
            def index_multiple(index,N):
                p = 1
                res = []
                while p * index <= N:
                    res.append(p*index)
                    p += 1
                return set(res)
            # 回溯函数
            def backtrack(a=[], nums=nums, index=0):
                # 这里可以看做是可变对象的妙用,如果变量为整型的话,则函数调用结束会变为调用前的值
                if len(a) == N:
                    results[0] = results[0] + 1
                    return
                index += 1
                # num中存放的是第index位可以放的数字,每次只遍历在该位可以放的数字,注意要去掉已经使用过的数字a
                # 这里如果不加括号的话会先计算 差集 - 后计算并集 |  因为 - 的优先级高
                # 对nums的限定就是剪枝条件
                nums = list((index_multiple( index, N) | find_factor(index)) - set(a))
                # 排序后再逆序也超时
                # nums.sort()
                # nums.reverse()
                for i,j in enumerate(nums):
                    backtrack(a+[j],index=index)
            backtrack()
            return results[0]
    
    if __name__ == '__main__':
        duixiang = Solution()
        a = duixiang.countArrangement(15)
        print(a)
    View Code

    可考虑的改进,对index排序,先填充质数,再合数,再填2,最后填1,或许会更快

  • 相关阅读:
    《Hadoop应用开发技术详解》
    c#中WMI 中的日期和时间转为本地时间
    c# 获取某个进程的CPU使用百分百(类似任务管理器中显示CPU)
    获得特定进程信息
    javascript利用jquery-1.7.1来判断是否是谷歌Chrome浏览器
    Oracle 用Drapper进行like模糊传参查询需要在参数值前后带%符合
    IIS7.0部署MVC/WebApi项目,报404.4错误
    MVC+EF6+Oracle,提示ORA-01918: user '***' does not exist
    MongoDB查询转对象是出错Element '_id' does not match any field or property of class
    MongoDB 导出、导入表
  • 原文地址:https://www.cnblogs.com/xxswkl/p/11965920.html
Copyright © 2020-2023  润新知