📜  门| GATE CS 2011 |问题16(1)

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

门 | GATE CS 2011 | 问题16

本题涉及到查找算法和时间复杂度的概念,需要应聘的程序员具备一定的算法基础和编程经验。

题目描述

给定 n 个正整数和一个正整数 k,判断是否能够从这 n 个正整数中选出若干个数,使得这些数的和恰好等于 k,并分析时间复杂度。

输入格式
  • 输入分为两行:
    • 第一行为两个整数 n 和 k,中间用空格分隔,分别表示正整数的个数和目标值。
    • 第二行为 n 个用空格分隔的正整数,表示给定的正整数集合。
输出格式
  • 如果能够选出若干个正整数,使得它们的和恰好等于 k,则输出字符串 Yes,否则输出字符串 No。
  • 另外,需要在程序中通过注释的方式给出解题思路和时间复杂度分析。
代码实现
def find_sum(n, k, arr):
    """
    解题思路:使用动态规划算法。
    对于数组中的一个数,要么选取要么不选取,因此,可以将问题转化为
    是否存在一个数列,使得其中的数的和等于 k。设 dp(i, j) 表示
    由前 i 个数能否选出若干个数使得它们的和恰好为 j,则有
    dp(i, j) = dp(i-1, j-a[i-1]) or dp(i-1, j),其中 a[i-1] 表示第 i 个数。
    时间复杂度为 O(nk)。

    :param n: 正整数的个数
    :param k: 目标值
    :param arr: 正整数集合
    :return: 返回字符串 Yes 或者 No
    """
    dp = [[False] * (k + 1) for _ in range(n + 1)]
    for i in range(n + 1):
        dp[i][0] = True
    for i in range(1, n + 1):
        for j in range(1, k + 1):
            if j >= arr[i - 1]:
                dp[i][j] = dp[i - 1][j - arr[i - 1]] or dp[i - 1][j]
            else:
                dp[i][j] = dp[i - 1][j]
    return "Yes" if dp[n][k] else "No"


# 测试代码
print(find_sum(5, 10, [2, 3, 5, 7, 8]))  # Yes
print(find_sum(4, 11, [2, 3, 5, 7]))     # No