棘手的算法问题[重复]
Posted
技术标签:
【中文标题】棘手的算法问题[重复]【英文标题】:Tricky algorithm question [duplicate] 【发布时间】:2011-05-01 17:53:36 【问题描述】:可能重复:Quickest way to find missing number in an array of numbers
输入:未排序数组 A[1,..,n] 包含范围 0,..,n 中除一个整数之外的所有整数
问题是在 O(n) 时间内确定丢失的整数。 A 的每个元素是 以二进制表示,唯一可用的操作是函数 bit(i, j),它 返回 A[i] 的第 j 位的值,并花费常数时间。
有什么想法吗?我认为某种分而治之的算法是合适的,但我想不出我到底应该做什么。提前致谢!
【问题讨论】:
如果 bit(i,j) 是唯一可用的操作,您建议如何实现分治算法? @A. Rex:你链接的可能的骗子对指令没有相同的限制,所以我认为它不一定是骗子。 这不是重复的。在这个问题中,您只能读取输入 A 的 n log n 位中的 O(n)。如果这是唯一的约束(即,如果除了 bit(i, j) 之外的操作)是免费的,那么您仍然可以解决它,使用分治算法,有点:算法的注释大小描述是计算偶数和奇数的数量,检查哪个计数与您从 0 得到的不匹配... n,并在丢弃最低位后递归输入的那一半。 这不是 ***.com/questions/2113795 的副本,正如 Reid 解释的那样,paxdiablo 的回答是错误的。 Reid 的算法是 O(n),如果您在计数时保留一个列表,其中列出了每一半中的元素。 【参考方案1】:1
和 n
之间的数字之和是一个数学属性,其中 n
是 n(n+1)/2
。你可以看到10
:
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
= (1+10) + (2+9) + (3+8) +(4+7) + (5+6)
= 11 + 11 + 11 + 11 + 11
= 55
因此,通过扩展,是从 0
到 n
的数字的总和,因为您只是将 0 添加到它。所以你要做的就是将所有数字相加并保持计数,然后使用该公式找出缺少的数字。
所以,类似:
count = 0
sum = 0
foreach num in list:
sum = sum + num
count = count + 1
missing = count * (count+1) / 2 - sum
使用bit(i,j)
获取数字很棘手,因此您必须单独提取这些位并将它们转换为实际数字以进行求和。
【讨论】:
这会读取 A 的所有 n log n 位,因此需要 n log n 时间。 @Reid:不,这根本不是 n log n。您不能同时将 n 用于位数 和 整数数。整数中的位数是常量,因此它实际上是O(32n)
(对于32 位数字),与O(n)
完全相同。
我很确定当 OP 写“整数”时,它们的意思是“整数”,而不是“小于 2^32 的整数”。否则,只有有限多个可能的输入,所以谈论渐近运行时根本没有意义。显然,实际数学整数的长度(以位为单位)不是恒定的。
我很确定整数意味着一个固定宽度的整数,即 32 位或 1024 位,而不是基于整数值的可变长度整数。那是因为这是一个编程问答网站,固定宽度架构的数量远远超过可变宽度架构的数量:-) 无论固定宽度是 32 还是任何其他常数,都无所谓,它仍然是一个常数。我可能是错的,但基于证据的优势,我对此表示怀疑。如果您想澄清,请随时质疑 OP。如果事实证明我错了,我会删除或编辑以修复。【参考方案2】:
您可以使用 XOR 运算符,因为它比加法更快。由于您可以访问每个位,因此您将在此处进行按位异或。 这里要使用的原理是 (A XOR B XOR A ) = B
例如:(1 XOR 2 XOR 3) XOR (1 XOR 2) = 3
for i=0 to n
Total=Total XOR i
foreach element in A
Total=Total XOR element
【讨论】:
实际上,这很漂亮,+1。您不能确定 XOR 会比加法更快,但它是对使用 XOR 的二合一/一合一(例如,91 91 82 82 73 64 64 55 55
)变体的巧妙修改找到单身人士。
Xor 永远不会比加法慢...为什么:此外还有一个结转位,需要一个全加器加一个步骤...在现代架构中使用并行加法器消除了它几乎相同的性能(xor 在此操作中使用少 1 个门)
1 到 n 的 XOR 有一个 O(1) 公式。 ***.com/questions/3932346/…。 XOR 还可以避免溢出问题。【参考方案3】:
那么这是一个技巧问题,因为使用 bit 方法只需要为每个数字循环每个位,这意味着它将自动变为 O(n*j),其中 j 是表示 n 的位数。
我认为 paxdiablo 已经知道了,假设您被允许使用不使用 bit 方法的解决方案。
【讨论】:
Neil,从技术上讲,这仍然是O(n)
,因为 j
是一个常数。
j 在实践中是恒定的,因为整数或 long 的长度始终相同,但是 j 的有效数字以 n*2 递增 1,其中 n > 0。更像 O(log n )。以上是关于棘手的算法问题[重复]的主要内容,如果未能解决你的问题,请参考以下文章