在准备面试时,我偶然发现了一个有趣的问题:
你得到了一个排序然后旋转的数组。
例如:
- 让
arr = [1,2,3,4,5]
,这是排序的- 向右旋转两次以给出
[4,5,1,2,3]
。现在如何最好地在这个排序+旋转的数组中进行搜索?
可以取消旋转数组,然后进行二分搜索。但这并不比在输入数组中进行线性搜索更好,因为两者都是最坏情况 O(N)。
请提供一些指示。我在谷歌上搜索了很多关于这个的特殊算法,但找不到任何东西。
我了解 C 和 C++。
原文由 Jones 发布,翻译遵循 CC BY-SA 4.0 许可协议
这可以在
O(logN)
中使用稍微修改的二进制搜索来完成。排序+旋转数组的有趣特性是,当您将其分成两半时,两半中至少有一个将始终被排序。
似乎右子数组未排序,而左子数组已排序。
如果 mid 恰好是旋转点,它们左右子数组都将被排序。
但 无论如何,必须对一半(子数组)进行排序。
通过比较每一半的开始和结束元素,我们可以很容易地知道哪一半是排序的。
一旦我们找到哪一半被排序,我们就可以看到关键是否存在于那一半中——与极端情况进行简单比较。
如果密钥存在于那一半,我们递归地调用那一半的函数
否则我们递归地调用另一半的搜索。
我们在每次调用中丢弃数组的一半,这使得该算法
O(logN)
。伪代码:
这里的关键是一个子数组总是被排序的,使用它我们可以丢弃数组的一半。