数字增殖问题 | 豆包MarsCode AI刷题

66 阅读3分钟

问题描述

给定一个正整数 n,定义一次"增殖"操作如下:

  • 将数字 n 转化为一个包含 1 到 n 的递增序列
  • 例如:当 n = 4 时,一次增殖后变为序列 [1, 2, 3, 4]

现给定三个正整数:

  • 初始数字 n
  • 增殖次数 k
  • 位置索引 p(从1开始计数) 请计算经过 k 次增殖操作后,序列中第 p 个位置的数字。如果 p 超出序列长度,则返回 -1

样例

输入:n = 4 ,k = 3 ,p = 19
输出:3
解释:
第1次增殖:4 -> [1,2,3,4]
第2次增殖:[1,2,3,4] -> [1, 1,2, 1,2,3, 1,2,3,4]
第3次增殖:得到最终序列 [1, 1, 1,2, 1, 1,2, 1,2,3, 1, 1,2, 1,2,3, 1,2,(3),4] -> ,第19个位置的数字是3

分析

由题意可知,每次增殖都会将正整数n转化为 [1, 2, ..., n],并将这些序列拼接起来,每次增殖操作会将当前的序列转化为一个更长的序列。

据此,我们选用列表

  • 先定义一个函数,实现将数字 n 转化为一个包含 1 到 n 的递增序列。
def to_list(a):
    a_list = []
    for i in range(1,a + 1):
        a_list.append(i)
    return a_list

这里,我们定义一个空列表a_list[],使用append方法,配合for...range返回一个递增序列。注意是1~n

  • 接着我们实现k次增殖操作。
def solution(n, k, p):
    b_list = to_list(n)
    for x in range(2,k + 1):
        c_list = []
        for y in b_list:
            c_list += to_list(y)
            b_list = c_list

在这部分,我们使用b_list = to_list(n)先增殖一次,获取一个列表,这样方便后续使用for循环。定义一个空列表c_list = [],通过c_list += to_list(y)将遍历时每个元素增值后的结果合并在一起,然后更新b_list,这便是最终结果。

  • 输出
 if p > len(b_list):
     return -1
 else:
     return b_list[p - 1]

在输出结果之前,检查一下p 是否超出我们获得的最终列表长度,如果超出,return -1,如果没有,return b_list[p - 1]。(因为我们需要的是第p个数字,而列表的下标是从0开始的,所以我们需要的是下标为p - 1的元素。

  • 测试
def to_list(a):
    a_list = []
    for i in range(1,a + 1):
        a_list.append(i)
    return a_list
def solution(n, k, p):
    b_list = to_list(n)
    for x in range(2,k + 1):
        c_list = []
        for y in b_list:
            c_list += to_list(y)
            b_list = c_list
    if p > len(b_list):
        return -1
    else:
        return b_list[p - 1]


if __name__ == "__main__":
    print(solution(4, 3, 19) == 3)

运行成功且结果正确。

总结、优化

以上示例的代码只是一个比较直接的方法。这个方法会在增殖次数较大时,产生大量的计算(我们生成了列表)。仔细思考我们会发现,每次增殖后,列表元素数量是可知的,那么我们只需要计算包含第p个元素的列表就行,这将免去不必要的计算。

  • 以下是优化后的示例代码
def solution(n, k, p):
    # 计算前 k 次增殖操作后的序列长度
    def calculate_length(n, k):
        length = 0
        for i in range(1, n + 1):
            length += i ** k
        return length
        
    # 计算第 p 个位置的数字
    def find_position(n, k, p):
        current_length = 0
        for i in range(1, n + 1):
            next_length = current_length + i ** k
            if p <= next_length:
                return i
            current_length = next_length
        return -1
        
    # 计算序列长度
    total_length = calculate_length(n, k)
    # 检查 p 是否超出序列长度
    if p > total_length:
        return -1
    # 找到第 p 个位置的数字
    return find_position(n, k, p)