# PHP面试：常见查找算法一篇说透

### 线性查找

``````function linearSearch(array \$arr, int \$needle) {
for (\$i = 0, \$count = count(\$arr); \$i < \$count; \$i++) {
if (\$needle === \$arr[\$i]) {
return true;
}
}

return false;
}``````

#### 线性查找的复杂度

best time complexity O(1)
worst time complexity O(n)
Average time complexity O(n)
Space time complexity O(1)

### 二分搜索

``````
function binarySearch(array \$arr, int \$needle) {
\$low = 0;
\$high = count(\$arr) - 1;

while (\$low <= \$high) {
\$middle = (int)((\$high + \$low) / 2);

if (\$arr[\$middle] < \$needle) {
\$low = \$middle + 1;
} elseif (\$arr[\$middle] > \$needle) {
\$high = \$middle - 1;
} else {
return true;
}
}

return false;
}``````

``````function binarySearchRecursion(array \$arr, int \$needle, int \$low, int \$high)
{
if (\$high < \$low) return false;

\$middle = (int)((\$high + \$low) / 2);

if (\$arr[\$middle] < \$needle) {
return binarySearchRecursion(\$arr, \$needle, \$middle + 1, \$high);
} elseif (\$arr[\$middle] > \$needle) {
return binarySearchRecursion(\$arr, \$needle, \$low, \$middle - 1);
} else {
return true;
}
}``````

#### 二分搜索复杂度分析

best time complexity O(1)
worst time complexity O(log n)
Average time complexity O(log n)
Space time complexity O(1)

### 重复二分查找

``````function repetitiveBinarySearch(array \$data, int \$needle)
{
\$low = 0;
\$high = count(\$data);
\$firstIndex = -1;

while (\$low <= \$high) {
\$middle = (\$low + \$high) >> 1;

if (\$data[\$middle] === \$needle) {
\$firstIndex = \$middle;
\$high = \$middle - 1;
} elseif (\$data[\$middle] > \$needle) {
\$high = \$middle - 1;
} else {
\$low = \$middle + 1;
}
}

return \$firstIndex;
}``````

``````public function testRepetitiveBinarySearch()
{
\$arr = [1,1,1,2,3,4,5,5,5,5,5,6,7,8,9,10];

\$firstIndex = repetitiveBinarySearch(\$arr, 6);

\$this->assertEquals(11, \$firstIndex);
}``````

### 插值搜索

``````function interpolationSearch(array \$arr, int \$needle)
{
\$low = 0;
\$high = count(\$arr) - 1;

while (\$arr[\$low] != \$arr[\$high] && \$needle >= \$arr[\$low] && \$needle <= \$arr[\$high]) {
\$middle = intval(\$low + (\$needle - \$arr[\$low]) * (\$high - \$low) / (\$arr[\$high] - \$arr[\$low]));

if (\$arr[\$middle] < \$needle) {
\$low = \$middle + 1;
} elseif (\$arr[\$middle] > \$needle) {
\$high = \$middle - 1;
} else {
return \$middle;
}
}

if (\$needle == \$arr[\$low]) {
return \$low;
}

return -1;

}``````

### 指数搜索

1.我们通过查找第一个指数k来确定边界大小，其中值2^k的值大于搜索项。 现在，2^k和2^(k-1)分别成为上限和下限。
2.使用以上的边界来进行二分搜索。

``````function exponentialSearch(array \$arr, int \$needle): int
{
\$length = count(\$arr);
if (\$length == 0) return -1;

\$bound = 1;

while (\$bound < \$length && \$arr[\$bound] < \$needle) {
\$bound *= 2;
}

return binarySearchRecursion(\$arr, \$needle, \$bound >> 1, min(\$bound, \$length));
}``````

best time complexity O(1)
worst time complexity O(log i)
Average time complexity O(log i)
Space time complexity O(1)

### 哈希查找

PHP底层C实现中数组本身就是一个哈希表，由于数组是动态的，不必担心数组溢出。我们可以将值存储在关联数组中，以便我们可以将值与键相关联。

``````function hashSearch(array \$arr, int \$needle)
{
return isset(\$arr[\$needle]) ? true : false;
}``````

### 树搜索

#### 广度优先搜索（BFS）

``````procedure BFS(Node root)
Q := empty queue
Q.enqueue(root)

while(Q != empty)
u := Q.dequeue()
for each node w that is childnode of u
Q.enqueue(w)
end for each
end while
end procedure        ``````

``````class TreeNode
{
public \$data = null;
public \$children = [];

public function __construct(string \$data = null)
{
\$this->data = \$data;
}

{
\$this->children[] = \$treeNode;
}
}

class Tree
{
public \$root = null;

public function __construct(TreeNode \$treeNode)
{
\$this->root = \$treeNode;
}

public function BFS(TreeNode \$node): SplQueue
{
\$queue = new SplQueue();
\$visited = new SplQueue();

\$queue->enqueue(\$node);

while (!\$queue->isEmpty()) {
\$current = \$queue->dequeue();
\$visited->enqueue(\$current);

foreach (\$current->children as \$children) {
\$queue->enqueue(\$children);
}
}

return \$visited;
}
}``````

#### 深度优先搜索（DFS）

``````procedure DFS(Node current)
for each node v that is childnode of current
DFS(v)
end for each
end procedure
``````
`````` public function DFS(TreeNode \$node): SplQueue
{
\$this->visited->enqueue(\$node);

if (\$node->children) {
foreach (\$node->children as \$child) {
\$this->DFS(\$child);
}
}

return \$this->visited;
}``````

``````public function DFS(TreeNode \$node): SplQueue
{
\$stack = new SplStack();
\$visited = new SplQueue();

\$stack->push(\$node);

while (!\$stack->isEmpty()) {
\$current = \$stack->pop();
\$visited->enqueue(\$current);

foreach (\$current->children as \$child) {
\$stack->push(\$child);
}
}

return \$visited;
}``````

``````public function DFS(TreeNode \$node): SplQueue
{
\$stack = new SplStack();
\$visited = new SplQueue();

\$stack->push(\$node);

while (!\$stack->isEmpty()) {
\$current = \$stack->pop();
\$visited->enqueue(\$current);

\$current->children = array_reverse(\$current->children);
foreach (\$current->children as \$child) {
\$stack->push(\$child);
}
}

return \$visited;
}``````

DFS的时间复杂度类似于BFS。

#### 你可能感兴趣的

4 条评论

0

xx19941215 作者 · 2018年10月03日
Tuesday · 2018年10月04日

0

xx19941215 作者 · 2018年10月04日