📌  相关文章
📜  查找不能用给定数字表示的最小正数(1)

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

查找不能用给定数字表示的最小正数

问题描述

给定一个正整数集合S,S中所有数字均为非负整数。现在你需要找到最小的正整数X,使得无论你选取集合S中的任意数量的数字,若干个它们的和等于X,总是可以找到一种方案使得被选取的数字中不含有数字X。

解题思路

为了方便,我们将集合S中的所有数字按升序排序。设当前已经找到的最小正整数为X,已经处理完的数的和为sum,正在处理的数的下标为i。那么,有如下的推论:

  • 如果S[i]小于等于sum+1,那么X可以被更新为X+S[i];
  • 否则,X就是sum+1。

理由如下:

首先考虑第一种情况。如果S[i]小于等于sum+1,我们可以向S[i]添加一个S[j],使得S[j]=S[i]+S[j],使得S[j]的范围扩大到S[1:i]。如果S[j]小于等于sum+1,那么X 就被更新为 X+S[j]。因为sum < X <= sum+S[j],所以X 是最小的正整数(sum+S[k],k < j,显然小于X,sum+S[k],k >= j 显然大于X)。

如果S[j]大于sum+1,那么X = sum+1,原因如下:假设X!=sum+1,那么sum+1必定可以用集合S中的若干个数表示。由于X是最小的不能用S中的数表示的正整数,所以sum+1可以用S中的数表示。这样,我们可以将大于S[j]的元素,从S[j]的集合中除去,并将S[j]并入S[1:j-1]集合中,然后进行下一次遍历。

代码实现
def find_minimun_positive(S):
    X = 1
    for i in range(len(S)):
        if S[i] <= X:
            X += S[i]
        else:
            break
    return X
时间复杂度

在调用完这个函数之后,程序会首先排序,排序的复杂度为O(nlgn),接下来遍历一遍S,时间复杂度为O(n),加起来就是O(nlgn+n),即最坏时间复杂度为O(nlgn)。

空间复杂度

空间复杂度为O(1),因为无论集合S中有多少元素,X都只需要一个整数的空间存储。