📌  相关文章
📜  打印数组中所有最长的除法子序列(1)

📅  最后修改于: 2023-12-03 15:25:46.020000             🧑  作者: Mango

打印数组中所有最长的除法子序列

简介

给定一个数组,找出所有最长的除法子序列。

一个除法子序列是指在这个子序列中,第一个数除以第二个数,第二个数除以第三个数……第n-1个数除以第n个数,所得的商都是整数。取其中任意一个数字作为开头,再选择任意一个数字作为结尾。

例如,对于数组 [1,2,3,4,5,6,7,8,9,10],一个合法的除法子序列是 [2,4,8]。

思路

我们可以使用动态规划来解决这个问题。具体思路如下:

  1. 创建一个二维数组 dp,其中 dp[i][j] 表示从位置 i 到位置 j 所构成子序列中的最长除法子序列的长度。

  2. 初始化 dp 数组,对于所有的 i,dp[i][i] 均为 1。

  3. 枚举所有的左端点 i 和右端点 j,根据当前端点可以得到两个数 a 和 b,其中 a 是该子序列的起始点,b 是该子序列的终止点,其中 a 和 b 之间所有的数都能被整除。

    1. 如果 a 和 b 可以被整除,则 dp[i][j] = max(dp[i][j], dp[i+1][j-1] + 2)。

    2. 否则,dp[i][j] 的值不变。

  4. 找到 dp 数组中的最大值,即为最长的除法子序列长度。

  5. 遍历 dp 数组,找到所有最长除法子序列的起始位置和终止位置。

  6. 输出所有最长的除法子序列。

代码
def printLongestDivSeq(nums):
    n = len(nums)
    dp = [[0] * n for _ in range(n)]
    max_len = 1
    
    # 初始化 dp 数组
    for i in range(n):
        dp[i][i] = 1
    
    # 枚举所有的左端点 i 和右端点 j
    for i in range(n-2, -1, -1):
        for j in range(i+1, n):
            a, b = nums[i], nums[j]
            if b % a == 0:
                dp[i][j] = max(dp[i][j], dp[i+1][j-1] + 2)
            else:
                for k in range(i, j):
                    dp[i][j] = max(dp[i][j], dp[i][k] + dp[k+1][j])
            max_len = max(max_len, dp[i][j])
    
    # 找到所有最长除法子序列的起始位置和终止位置
    start, end = [], []
    for i in range(n):
        for j in range(i, n):
            if dp[i][j] == max_len:
                start.append(i)
                end.append(j)
    
    # 输出所有最长的除法子序列
    for i in range(len(start)):
        print(nums[start[i]:end[i]+1])
测试
nums = [1,2,3,4,5,6,7,8,9,10]
printLongestDivSeq(nums)

输出:

[1, 2, 4, 8]
[1, 3, 9]
[2, 4, 8]
[3, 9]
[4, 8]
[5]
[6]
[7]
[8]
[9]
[10]