这个问题是在亚马逊采访中问我的-
给定一个正整数数组,你必须找到一个最小的正整数,这个正整数不能由数组中的数字之和构成。
例子:
Array:[4 13 2 3 1]
result= 11 { Since 11 was smallest positive number which can not be formed from the given array elements }
我做的是:
但这是nlog(n)解
面试官对此不满意,在不到O(n logn)的时间内提出了解决方案。
考虑区间[2i...2i 1-1]中的所有整数。并且假设所有低于2i的整数都可以由给定数组的数字之和形成。还假设我们已经知道C,它是低于2i的所有数字的和。如果C
下面是一个算法的草图:
S[int_log(x)]=x
foreach i:C[i]=C[i-1]S[i]
i=int_log(x)-1;B[i]|=(x)
如果不清楚为什么我们可以应用第3步,下面是证据。选择2i和C之间的任何数字,然后按降序从中依次减去2i以下的所有数字。最终我们得到的要么是比最后一个减法数少的数,要么是零。如果结果为零,只需将所有减去的数字相加,我们就得到了所选数字的表示形式。如果结果为非零且小于最后一个减去的数字,则该结果也小于2,因此它是“可表示的”,且所有减去的数字均不用于其表示。当我们把这些减去的数字加回去时,我们得到了所选数字的表示形式。这也表明,我们可以直接跳到C的int_log,一次跳过几个间隔,而不是一个接一个地过滤间隔。
时间复杂度由函数
int_log()
决定,它是整数对数或数字中最高集位的索引。如果我们的指令集包含整数对数或其任何等价物(计数前导零,或使用浮点数的技巧),则复杂度为O(n)。否则我们可以使用一些位黑客在O(log log U)中实现int_log()
并获得O(n*log log U)时间复杂度。(这里U是数组中最大的数字)。
如果第1步(除了更新和)还将更新给定范围内的最小值,则不再需要第4步。我们可以将C[i]与min[i 1]进行比较。这意味着我们只需要单遍输入数组。或者我们可以将此算法应用于数字流,而不是数组。
几个例子:
Input: [ 4 13 2 3 1] [ 1 2 3 9] [ 1 1 2 9]
int_log: 2 3 1 1 0 0 1 1 3 0 0 1 3
int_log: 0 1 2 3 0 1 2 3 0 1 2 3
S: 1 5 4 13 1 5 0 9 2 2 0 9
C: 1 6 10 23 1 6 6 15 2 4 4 13
filtered(C): n n n n n n n n n n n n
number in
[2^i..C+1]: 2 4 - 2 - - 2 - -
C+1: 11 7 5
对于多精度输入数,这种方法需要O(n*logm)时间和O(logm)空间。其中M是数组中的最大数。读取所有数字需要同样的时间(最糟糕的情况下,我们需要每一个数字)。
尽管如此,这个结果可能会被改进为O(n*logr),其中R是这个算法找到的值(实际上是它的输出敏感变量)。这种优化所需的唯一修改不是一次处理整数,而是逐位处理:第一次通过处理每个数字的低阶位(如位0..63),第二次通过-下一个位(如64..127),等等。在找到结果后,我们可以忽略所有高阶位。此外,这将空间需求减少到O(K)个数,其中K是机器字中的位数。
使用位向量在线性时间内完成此操作。
从空位向量b开始。然后对数组中的每个元素k执行以下操作:
b=b | b
为了清楚起见,第i个元素被设置为1来表示数字i,而|k
将第k个元素设置为1。
处理完数组后,b中第一个零的索引就是你的答案(从右边开始计算,从1开始)。
第一个零:位置11。
时间O(n Sort)中有一个很好的算法可以解决这个问题,其中Sort是对输入数组进行排序所需的时间。
该算法的思想是对数组进行排序,然后问以下问题:使用数组的前k个元素不能生成的最小正整数是什么?然后从左到右向前扫描数组,更新这个问题的答案,直到找到无法生成的最小数字。
下面是它的工作原理。最初,最小的数字是1。然后,从左到右,执行以下操作:
在伪代码中:
Sort(A)
candidate = 1
for i from 1 to length(A):
if A[i] > candidate: return candidate
else: candidate = candidate + A[i]
return candidate
下面是对[4, 13, 2, 1, 3]
的测试。对数组进行排序以获得[1, 2, 3, 4, 13]
。然后,将候选
设置为1。然后执行以下操作:
候选
=1:
候选
,所以设置候选=候选A[1]=2
候选者=候选者A[2]=4
候选
,所以设置候选=候选A[3]=7
候选人=候选人A[4]=11
所以答案是11。
这里的运行时是O(n Sort),因为在排序之外,运行时是O(n)。你可以使用heapsort在O(n logn)时间内清晰地排序,如果你知道一些数字的上限,你可以使用基数排序在O(n logu)时间内排序(U是最大可能的数字)。如果U是一个固定常数(例如,109),那么基数排序在时间O(n)中运行,整个算法也在时间O(n)中运行。
希望这有帮助!
令我惊讶的是,它通过了所有的测试用例。有人能给我解释一下这个逻辑吗?
我正在尝试解决此问题: 一位物理教授给班上的学生做项目。学生们必须组成一个两人小组来做这个项目。教授让学生来决定队伍。一个班级的学生人数将是偶数。 每个学生都有自己的知识水平。它告诉每个学生有多少知识。一个团队的知识水平是两个学生知识水平的总和。 学生们决定组成小组,这样知识最高的团队和知识最低的团队之间的差异就最小了。 投入 输入的第一行将包含测试用例的数量t;在接下来的t行中,第一个数字是n,
本文向大家介绍Java数组中最大质数和最小质数之间的差异,包括了Java数组中最大质数和最小质数之间的差异的使用技巧和注意事项,需要的朋友参考一下 问题陈述 对于给定的整数数组,其中所有元素均小于1000000。找到数组中最大素数和最小素数之间的差。 示例 解 使用Eratosthenes筛分法,这是找出小于给定数的所有素数的有效方法。然后,我们将找出最大和最小的质数以获得所需的差。 示例 以下是
NowCoder 题目描述 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组 {3,32,321},则打印出这三个数字能排成的最小数字为 321323。 解题思路 可以看成是一个排序问题,在比较两个字符串 S1 和 S2 的大小时,应该比较的是 S1+S2 和 S2+S1 的大小,如果 S1+S2 < S2+S1,那么应该把 S1 排在前面,
编写一个函数: 函数解($ A); 给定一个包含 N 个整数的数组 A,返回 A 中未出现的最小正整数(大于 0)。 例如,给定A = [1,3,6,4,1,2],函数应该返回5。 再比如,给定A = [1,2,3],函数应该返回4。 给定A =[1,3],该函数应返回1。 假设: N是[1…100,000]范围内的整数;数组A的每个元素都是[−1,000,000…1,000,000]范围内的整数
把一个int型数组中的数字拼成一个串,这个串代表的数字最小。 #思路说明 对这个问题的理解: 有一个元素是int类型的list; 将上述list中的每个元素的数字分别取出来,然后将这些数字的顺序进行从新排列,并将其中的最小整数输入,就是题目中要求的最小数字。 如果按照上述理解,在解题中,最应当小心的是数字如果很大,比如list中的某个int元素是:2222222222222277777777777