如何在从左到右、从上到下排序的二维数组中搜索数字?

2024-05-04

我最近收到了这个面试问题,我很好奇有什么好的解决方案。

假设我有一个二维数组,其中所有 数组中的数字在增加 从左到右、从上到下的顺序 底部。

搜索和搜索的最佳方式是什么? 判断目标号码是否在 大批?

现在,我的第一个倾向是使用二分搜索,因为我的数据已排序。我可以在 O(log N) 时间内确定一个数字是否在一行中。然而,这两个方向让我失望。

我认为可能有效的另一个解决方案是从中间的某个地方开始。如果中间值小于我的目标,那么我可以确定它位于矩阵中间的左侧正方形部分。然后,我沿对角线移动并再次检查,减小目标可能所在的正方形的大小,直到我磨练出目标数字为止。

有人对解决这个问题有什么好主意吗?

数组示例:

从左到右、从上到下排序。

1  2  4  5  6  
2  3  5  7  8  
4  6  8  9  10  
5  8  9  10 11  

这是一个简单的方法:

  1. 从左下角开始。
  2. 如果目标小于该值,则它一定在我们之上,所以上移一位.
  3. 否则我们知道目标不能在该列中,所以向右移动一个.
  4. Goto 2.

For an NxM数组,这运行在O(N+M)。我认为很难做得更好。 :)


Edit:很多很好的讨论。我上面说的是一般情况;显然,如果N or M很小,您可以使用二分搜索方法在接近对数时间内完成此操作。

以下是一些细节,供好奇的人参考:

History

这个简单的算法称为马鞍峰搜索 http://www.cs.geneseo.edu/~baldwin/math-thinking/saddleback.html。它已经存在了一段时间,当它是最佳的N == M。一些参考:

  • 大卫·格里斯,编程科学 https://rads.stackoverflow.com/amzn/click/com/0387964800. 施普林格出版社,1989.
  • 埃兹格·迪杰斯特拉,马鞍峰搜索 http://www.cs.utexas.edu/users/EWD/index09xx.html. 注 EWD-934,1985.

然而,当N < M,直觉表明二分查找应该能够比O(N+M): 例如,当N == 1,纯二分搜索将以对数时间而不是线性时间运行。

最坏情况界限

Richard Bird 在 2006 年的一篇论文中检验了二分搜索可以改进 Saddleback 算法的直觉:

  • 理查德·伯德,改进鞍背搜索:算法设计的一课 http://www.cs.ox.ac.uk/publications/publication2664-abstract.html, 程序构建数学,第 82--89 页,第 4014 卷,2006 年.

伯德使用一种相当不寻常的对话技巧向我们展示了N <= M,这个问题的下界为Ω(N * log(M/N))。这个界限是有道理的,因为它为我们提供了线性性能N == M和对数性能时N == 1.

矩形阵列的算法

一种使用逐行二分搜索的方法如下所示:

  1. 从一个矩形数组开始,其中N < M。比方说N是行并且M是列。
  2. 对中间行进行二分查找value。如果我们找到它,我们就完成了。
  3. 否则我们找到了一对相邻的数字s and g, where s < value < g.
  4. 上方和左侧的数字矩形s小于value,所以我们可以消除它。
  5. 下面和右侧的矩形g大于value,所以我们可以消除它。
  6. 对于剩下的两个矩形,分别转到步骤 (2)。

就最坏情况的复杂度而言,该算法log(M)努力消除一半可能的解决方案,然后在两个较小的问题上递归调用自身两次。我们确实必须重复一个较小的版本log(M)为每一行工作,但如果行数与列数相比较小,那么能够在对数时间内消除所有这些列就开始变得值得.

这使得算法的复杂度为T(N,M) = log(M) + 2 * T(M/2, N/2),伯德表明是O(N * log(M/N)).

Craig Gidney 发布的另一种方法 http://twistedoakstudios.com/blog/Post5365_searching-a-sorted-matrix-faster描述了一种与上述方法类似的算法:它使用步长大小一次检查一行M/N。他的分析表明,这会导致O(N * log(M/N))性能也是如此。

性能比较

Big-O 分析固然很好,但这些方法在实践中效果如何?下图检查了用于日益“方形”数组的四种算法:

(“朴素”算法简单地搜索数组的每个元素。“递归”算法如上所述。“混合”算法是吉德尼算法 http://twistedoakstudios.com/blog/Post5365_searching-a-sorted-matrix-faster。对于每个数组大小,通过在 1,000,000 个随机生成的固定数组上对每个算法进行计时来测量性能。)

一些值得注意的点:

  • 正如预期的那样,“二分搜索”算法在矩形数组上提供最佳性能,而马鞍形算法在方形数组上效果最佳。
  • 对于一维数组,Saddleback 算法的性能比“朴素”算法差,大概是因为它对每个项目进行多次比较。
  • “二分搜索”算法对方形数组的性能影响可能是由于运行重复二分搜索的开销造成的。

Summary

巧妙地使用二分查找可以提供O(N * log(M/N)矩形和方形阵列的性能。这O(N + M)“鞍背”算法要简单得多,但随着数组变得越来越矩形,性能会下降。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在从左到右、从上到下排序的二维数组中搜索数字? 的相关文章

  • 如何将无向图转换为 DAG?

    The 维基页面 http en wikipedia org wiki Directed acyclic graph Relation to other kinds of graphs says 任何无向图都可以通过为其顶点选择总顺序并将每
  • 数组长度未定义[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我试图按如
  • 快速搜索压缩文本文件

    我需要能够在大量压缩文件 txt 中搜索文本 压缩可能会改变为其他东西 甚至成为专有的 我想避免解压所有文件并压缩 编码 搜索字符串并在压缩文件中搜索 这应该可以通过对所有文件使用相同的码本使用霍夫曼压缩来实现 我不想重新发明轮子 所以 任
  • 我需要一个支持高效随机访问和 O(k) 插入和删除的容器

    我再次尝试问同样的问题question https stackoverflow com questions 3808708 delete parts of a dynamic array and grow other 但我最终提出了一个不同
  • 通过另一个二维数组中的行过滤二维数组的行

    我有两个数组 我正在使用array diff assoc 以获得差异 但它总是返回common set结果中的行 它应该返回new q sets排 我的方法有什么问题吗 样本数据 array1 12 gt new q sets 11 gt
  • 最慢的计算复杂度(Big-O)

    在这些算法中 我知道 Alg1 是最快的 因为它是 n 平方的 接下来是 Alg4 因为它是 n 的立方 然后 Alg2 可能是最慢的 因为它是 2 n 这应该具有非常差的性能 然而Alg3和Alg5在我的阅读速度方面还没有遇到过 这两种算
  • 有人可以解释以下异或属性

    我的一个论坛提到给定的数组n数字 arr 0 n 1 以下条件成立 is the xor运算符 f l r f 0 r f 0 l 1 where f l r arr l arr l 1 arr r 我检查了上面的数组数量和不同的值l an
  • 在 C++ 中通过引用传递 std 算法谓词

    我正在尝试从 a 中删除元素std list并保留已删除元素的一些统计信息 为此 我使用列表中的remove if 函数 并且我有一个谓词 我想使用这个谓词来收集统计数据 这是谓词的代码 class TestPredicate privat
  • 快速约会算法

    我在一家咨询公司工作 大部分时间都在客户所在地 正因为如此 我很少见到同事 为了更好地了解彼此 我们将安排一个晚宴 会有很多小桌子 方便人们聊天 为了在聚会期间与尽可能多的不同的人交谈 每个人都必须每隔一段时间 比如每小时 换一张桌子 如何
  • 使用多级解决方案计算二维网格中的最近邻

    我有一个问题 在 x y 大小的网格中 我提供了一个点 并且我需要找到最近的邻居 在实践中 我试图在 pygame 中找到距离光标最近的点 该点跨越颜色距离阈值 计算如下 sqrt rgb1 0 rgb2 0 2 rgb1 1 rgb2 1
  • 当搜索文本包含感叹号 (!)、与号 (&) 等时,IMAP“搜索标头”命令失败

    我正在通过 python 访问 GMail 的 IMAP 界面 我运行这样的命令 UID SEARCH HEADER Message ID email protected cdn cgi l email protection 成功 返回匹配
  • 异或交换可以扩展到两个以上的变量吗?

    我一直在尝试将异或交换扩展到两个以上的变量 例如n变量 但我没有得到比这更好的地方3 n 1 对于两个整型变量x1 and x2你可以像这样交换它们 swap x1 x2 x1 x1 x2 x2 x1 x2 x1 x1 x2 所以 假设你有
  • 计算两点之间的最短路线

    过去几周我一直在开发一款多人 HTML5 游戏 使用nodejs and websockets 我已经被这个问题困扰了一段时间 想象一下 我用数组实现了这个平铺地图 如下所示 1 or 棕色瓷砖 路上有障碍物 玩家无法通过 0 or 绿色瓷
  • 如何检查是否存在可能的路径?

    我正在开发一个基于 javascript 的实验性游戏 玩家必须在二维平铺地图上移动才能退出 请随意检查这个小提琴并演奏 http jsfiddle net moonlife 74vLd 我只是随机放置障碍物 但有时障碍物会挡住玩家和出口之
  • 给定一个具有多个重复条目的数组,找到一个重复条目 O(N) 时间和常数空间

    我们得到了一个大小为 N 的数组 其中包含 0 到 N 2 范围内的整数 包括 0 和 N 2 该数组可以有多个重复的条目 我们需要在 O N 时间和常量空间中找到重复条目之一 我正在考虑取数组中所有条目的乘积和总和 以及 0 到 N 2
  • 归并排序中递归树的高度log(n)+1是怎么来的

    我按照 stackoveflow 的建议阅读了一些问题和答案 我正在遵循 cormen 的 算法简介 一书进行自学 那本书里已经解释得很清楚了 但唯一没有解释的是如何在合并排序分析中计算树的高度 如果在后面的章节中对此进行解释的话 我仍然在
  • 在 O(n) 时间内排序?

    我被这个问题困扰了 2周 知道如何处理它吗 令 L 为 n 个不同整数的列表 假设 L 的 x 的元素在 1 750 范围内 设计线性排序算法对 L 的元素进行排序 我已经尝试过插入排序 但我不确定我的方法是否正确 Construct an
  • Java递归方法求阶乘返回负输出[重复]

    这个问题在这里已经有答案了 我知道这是溢出 但问题是 20 是相对较小的数字 这不应该发生 对吧 有没有更好的方法来查找大数 例如 1000 的阶乘 而不会得到这种奇怪的结果 public class RecursiveFunctionsE
  • 解开 Knuth 的结:如何重构意大利面条式代码?

    这个问题的灵感来自如何将流程图转化为实施 https stackoverflow com questions 36647765它询问如何通过算法消除goto代码中的语句 这answer https stackoverflow com a 3
  • 在数据库中搜索时忽略空文本框

    此代码能够搜索数据并将其加载到DataGridView基于搜索表单文本框中提供的值 如果我将任何文本框留空 则不会有搜索结果 因为 SQL 查询是用 AND 组合的 如何在搜索 从 SQL 查询或 C 代码 时忽略空文本框 private

随机推荐

  • 制作一个未知大小的数组 C# [重复]

    这个问题在这里已经有答案了 可能的重复 C 中未知长度的数组 https stackoverflow com questions 599369 array of an unknown length in c sharp 我想创建一个程序 用
  • 如何更改 UIImage 的颜色? [复制]

    这个问题在这里已经有答案了 我不想改变图像的背景颜色 而是改变整个图像的颜色 但问题是 我只能改变backgroundColor 接受的答案是正确的 但还有更多easy way for UIImageView Obj C UIImage i
  • AngularJs 位置路径更改,无需重置所有控制器

    我的问题的简短版本是 如何更改 URL 而不需要触发路由更改或不需要运行当前显示页面上的所有控制器 Details 我有一个模板 显示在
  • Android 电子邮件意图和消息正文

    我正在使用意图从我的应用程序启动电子邮件应用程序 我使用意图设置主题 短信和电子邮件地址 除了电子邮件部分中的光标位置之外 一切正常 我的电子邮件信息类似于 感谢您选择 不要写在这条线下面 我在电子邮件正文中看到该消息 但我的光标在 请勿写
  • 索引 getter 中的 IndexOutOfRangeException

    在我的索引属性中 我检查索引是否超出范围 如果是的话 我抛出一个IndexOutOfBoundsException 当我运行代码分析器 在 VS12 中 时 它抱怨 CA1065 意外位置出现意外异常 参考CA1065的描述 仅 Syste
  • 如何使用 Gnuplot 在一个图中绘制代表数据集中多个子集行的多个图表?

    我有一个数据集 其名称为 output txt 格式如下 1 2 4 6 7 10 1 2 5 6 7 1 3 4 6 7 10 2 4 6 7
  • 使用 python 突出显示图像中的特定文本

    我想突出显示网站屏幕截图中的特定单词 句子 截取屏幕截图后 我使用提取文本pytesseract and cv2 效果很好 我可以获得有关它的文本和数据 import pytesseract import cv2 if name main
  • 嵌入式 Jetty 无法识别 Spring MVC Security

    我正在开发一个启动嵌入式 Jetty 服务器的 Spring 应用程序 然后 它将 Spring MVC Web 应用程序 部署 到该 Jetty 服务器 多个控制器都运行良好 但我无法将 Spring Security 添加到 Web 应
  • C# StreamReader 使用分隔符保存到数组

    我有一个文本文件 其中包含制表符分隔的数据 我在 C 应用程序中需要的是从文本文件中读取一行并将它们保存到一个数组中 在每个位置将它们分开 t 然后我对下一行做同样的事情 My code StreamReader sr new Stream
  • 为什么 float() 会截掉尾随零?

    该代码成功地将一个包含许多数字的大文件裁剪为几个包含数字的较小文本文件 但它产生了一个有趣的怪癖 所有数字都应精确到小数点后四位 例如 2 7400 但它们打印为 2 74 这是文件的片段 0 96 0 53 0 70 0 53 0 88
  • 在 C 中打印字符串的所有排列

    我正在学习回溯和递归 并且我陷入了打印字符串所有排列的算法 我用以下方法解决了它贝尔算法 http programminggeeks com bell algorithm for permutation 用于排列 但我无法理解递归方法 我在
  • mysql 查询从给定的表结构创建 SEO 友好的 url

    我正在尝试使用下表创建 SEO 友好的 URL 类别表 http sqlfiddle com 2 c474a 4 页表 http sqlfiddle com 2 c474a 5 我正在尝试编写一个 mysql 查询 该查询将使用产生以下输出
  • 如何获取firestore集合下的文档数量? [复制]

    这个问题在这里已经有答案了 我想获取 firestore 集合中的文档总数 我正在制作一个论坛应用程序 所以我想显示每个讨论中当前的评论量 有类似的东西db collection comments get lenght或类似的东西 随着si
  • ConcurrentLinkedDeque 与 LinkedBlockingDeque

    我需要一个线程安全的 LIFO 结构 并发现我可以使用线程安全的实现Deque为了这 Java 7 引入了ConcurrentLinkedDeque http docs oracle com javase 7 docs api java u
  • Grails 2.3 IntegrationSpec 不能为事务性 false

    我最近升级到 Grails 2 3 并尝试将所有旧测试迁移到 spock 集成测试 但它在清理时失败了 因为我的测试是非事务性的 Grails 文档说测试可以是非事务性的 但我们需要手动处理它 但在这里似乎不太正确 因为我在扩展 Integ
  • Linux 上的 wall-time 分析

    我有一个应用程序 我想分析在各种活动中花费了多少时间 由于此应用程序是 I O 密集型 因此我希望获得一份报告 该报告将总结每个库 系统调用所花费的时间 挂起时间 我已经尝试过 oprofile 但它似乎给出了 Unhalted CPU 周
  • JSF:如何通过 bean 验证来验证字段并返回错误消息?

    我有一个联系表单 并且有一些通过 Bean 验证进行验证的字段 提交后如何返回 Bean 验证错误消息 例如
  • 从 MySQL 执行 shell 命令

    我知道我正在寻找的可能是一个安全漏洞 但由于我设法在 Oracle 和 SQL Server 中做到了这一点 所以我会尝试一下 我正在寻找一种从 MySQL 上的 SQL 脚本执行 shell 命令的方法 如有必要 可以创建和使用新的存储过
  • openSUSE phpmyadmin 错误:缺少 mbstring 扩展名

    phpMyAdmin 错误 缺少 mbstring 扩展名 请检查 你的 PHP 配置 我已经安装了 php mbstring 和 php gettext 我的 php 版本是 php7 我通过 zypper 安装了 php 和 phpmy
  • 如何在从左到右、从上到下排序的二维数组中搜索数字?

    我最近收到了这个面试问题 我很好奇有什么好的解决方案 假设我有一个二维数组 其中所有 数组中的数字在增加 从左到右 从上到下的顺序 底部 搜索和搜索的最佳方式是什么 判断目标号码是否在 大批 现在 我的第一个倾向是使用二分搜索 因为我的数据