剑指Offer-题4-二维数组中的查找
题目:二维数组中的查找
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
解析
可以肯定的是直接遍历不可取🙄。之后想到跳步判断,先走斜线,若此时数值大于查找数则往左或往右倒退?往左之后该往上还是往下?继而联想到A*路径查找算法……
naive ! 书中指出考虑每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。问题变得困难是因为考虑数组中中间位置的数,此时该位置含有两个排序规律;不如考虑特殊位置-顶角的数呢?
二维数组有四个顶角,选择其中某个顶角分析。举例分析:
有如下二维数组,查找数字 7
$$
\begin{bmatrix}
1 & 2 & 8 & 9 \\
2 & 4 & 9 & 12 \\
4 & 7 & 10 & 13 \\
6 & 8 & 11 & 15 \\
\end{bmatrix}
$$
对四个顶点分情况讨论(↓、→、↘表示增大方向):
- 考虑左上角则有规律:对于左上角有三个出度
$$
\begin{bmatrix}
● & \rightarrow & \rightarrow & \rightarrow \\
\downarrow & \searrow & \downarrow & \downarrow \\
\downarrow & \rightarrow & \searrow & \downarrow \\
\downarrow & \rightarrow & \rightarrow & \searrow \\
\end{bmatrix}
$$ - 考虑右下角则有规律:对于右下角有三个入度
$$
\begin{bmatrix}
+ & \rightarrow & \rightarrow & \rightarrow \\
\downarrow & \searrow & \downarrow & \downarrow \\
\downarrow & \rightarrow & \searrow & \downarrow \\
\downarrow & \rightarrow & \rightarrow & ● \\
\end{bmatrix}
$$ - 考虑右上角则有规律:对于右上角有一个入度和一个出度
$$
\begin{bmatrix}
+ & \rightarrow & \rightarrow & ● \\
\downarrow & \searrow & \downarrow & \downarrow \\
\downarrow & \rightarrow & \searrow & \downarrow \\
\downarrow & \rightarrow & \rightarrow & \searrow \\
\end{bmatrix}
$$ - 考虑左下角则有规律:对于左下角有一个入度和一个出度
$$
\begin{bmatrix}
+ & \rightarrow & \rightarrow & \rightarrow \\
\downarrow & \searrow & \downarrow & \downarrow \\
\downarrow & \rightarrow & \searrow & \downarrow \\
● & \rightarrow & \rightarrow & \searrow \\
\end{bmatrix}
$$
“柿子要捡软的捏”,当然选一出一入的突破口啊!例如选择右上角数字 9
,则 9 > 7
说明第四列均大于 7
,故判断数组范围缩小为
$$
\begin{bmatrix}
1 & 2 & 8 \\
2 & 4 & 9 \\
4 & 7 & 10 \\
6 & 8 & 11 \\
\end{bmatrix}
$$
继续选择右上角数字 8
,则 8 > 7
说明第四列均大于 8
,故判断数组范围又缩小
$$
\begin{bmatrix}
1 & 2 \\
2 & 4 \\
4 & 7 \\
6 & 8 \\
\end{bmatrix}
$$
继续选择右上角数字 2
,则 2 < 7
说明第一行均小于 8
,故判断数组范围双缩小
$$
\begin{bmatrix}
2 & 4 \\
4 & 7 \\
6 & 8 \\
\end{bmatrix}
$$
继续选择右上角数字 4
,则 4 < 7
说明第一行均小于 8
,故判断数组范围叒缩小
$$
\begin{bmatrix}
4 & 7 \\
6 & 8 \\
\end{bmatrix}
$$
选择右上角数字 7
,则寻找完毕😄。转化为代码如下1
2
3
4
5
6
7
8
9
10
11
12
13
14
15bool findNumber(int *arr, int rows, int columns, int number)
{
if (nullptr == arr || rows < 1 || columns < 1)
return false;
int row = 1;
int column = columns;
while (row <= rows && column > 1)
if (arr + ((row - 1) + (column - 1) * rows) > number)
--column;
else if (arr + ((row - 1) + (column - 1) * rows) < number)
++row;
else
return true;
return false;
}
本文采用 CC BY-NC-SA 3.0 Unported 协议进行许可