在求职面试中我被问到以下问题。
给定一个大小未知的输入数组,开头的所有1和最后的0。找到数组中从0开始的索引。考虑到array.ie数组中有数百万的1和0是非常大的..例如数组内容1111111 ....... 1100000 ......... 0000000.稍后谷歌搜索问题,我发现关于http://www.careercup.com/question?id=2441的问题。
关于这个问题最令人费解的是,如果我不知道数组的大小,我怎么知道*(array_name + index)是否属于数组?即使有人找到一个值从1变为0的索引,如何断言索引属于该数组。
我能找到的最佳答案是O(logn)解决方案,其中一个保持索引加倍直到找到0.再次保证特定元素属于数组。
编辑: 这是一个基于c的数组。约束是你没有end elem的索引(不能使用sizeof(arr)/ sizeof(arr [0]))。如果我说1024.arr [1024] == 1怎么办? arr [2048]超出范围,因为数组长度为1029(程序员不知道)。那么在找到解决方案时可以使用arr [2048]吗?它超出了界限,它的价值可以是任何东西。所以我想知道这个问题可能存在缺陷。
答案 0 :(得分:2)
我会使用二进制搜索来找到0。
首先你取中间,如果是1,你进入右侧,否则进入左侧。继续这样做,直到你找到第一个0。
现在,问题陈述说:给定一个大小未知的输入数组,开头的所有1和最后的0。数组在内存中的表示方式是1个元素接一个,因为你知道数组末尾有0,如果你的算法正常工作,那么*(array_name + index)肯定属于数组。 / p>
编辑:
抱歉,我刚刚意识到只有你知道尺寸才能解决问题。否则,是的,加倍索引是我脑海中最好的算法。但是索引仍然属于数组这一事实的证明是相同的。
由于评论而编辑:
它声明在数组的末尾有0。因此,如果你做一个简单的
int i;
while(i)
if( *(array_name+i) != 1 )
return i;
它应该给你第一个索引,对吧? 既然你知道数组看起来像1111 ... 000000你也知道0的至少1和那是第一个,肯定属于数组。
在你的情况下,你通过加倍索引然后在index和index / 2之间使用二进制搜索来进行搜索。在这里你不能确定index是否属于数组,但index和index / 2之间的第一个0肯定属于数组(声明表示至少有一个0)。
Uppss ...我刚才意识到,如果你继续加倍索引并且你离开了数组,你会发现“垃圾值”,这意味着它们可能不是0。因此,你可以做的最好的事情是检查第一个0来检查第一个不是0的元素。遗憾的是,可能存在值为1的垃圾值(可能发生的极小机会)。如果是这种情况,您将需要使用O(n)算法。
答案 1 :(得分:2)
如果你不知道数组的长度,并且无法读取数组的末尾(因为它可能是段错误或给你随机垃圾),那么只有 的东西你可以做的是从头开始并查看每个元素,直到找到零:
int i = 0;
while (a[i] != 0) i++;
return i;
你最好希望 阵列中至少有一个零。
如果可以以某种方式找出数组的长度,那么二进制搜索确实更有效。
聚苯乙烯。如果它是char
数组,那么只需在其上调用strlen()
就会更容易也可能更快。上面的代码几乎是strlen()
所做的,除了标准库实现可能更适合您的CPU架构。
答案 2 :(得分:0)
如果您不知道阵列的大小,可以从index = 1
开始;在每一步中,检查2 * index
是否大于数组的长度 - 如果是,或者它是零 - 现在你有一个边界来开始二进制搜索;否则index = 2 * index
。