- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
不久前,我了解了一些有关大 O 表示法和不同算法效率的知识。
例如,循环遍历数组中的每一项以对其执行某些操作
foreach(item in array)
doSomethingWith(item)
是一个O(n)
算法,因为程序执行的循环次数与数组的大小成正比。
不过,令我吃惊的是表查找是 O(1)
。即在哈希表或字典中查找键
value = hashTable[key]
无论表有一个键、十个键、一百个键还是十亿个键,都需要相同的循环次数。
这真的很酷,我很高兴这是真的,但这对我来说很不直观,我不明白为什么这是真的。
我能理解第一个 O(n)
算法,因为我可以将它与现实生活中的例子进行比较:如果我有几张纸要盖章,我可以遍历每一张一张一张地打印纸,并在每张纸上贴上邮票。这对我来说很有意义,如果我有 2,000 张纸,使用这种方法盖章所需的时间是我有 1,000 张纸时的两倍。
但我不明白为什么查表是O(1)
。我在想,如果我有一本字典,并且我想找到多态性的定义,我将花费 O(logn)
时间来找到它:我'我将打开字典中的某个页面,看看它是按字母顺序排列在多态性 之前还是之后。比方说,如果它在 P 部分之后,我可以在我打开的页面之后删除字典中的所有内容,并对字典的其余部分重复该过程,直到找到单词 多态性。
这不是一个O(1)
过程:与在两页词典中相比,在一千页词典中查找单词通常需要更长的时间。我很难想象一个无论字典大小如何都需要相同时间的过程。
tl;dr:您能否向我解释一下如何使用 O(1)
复杂度进行表查找?
(如果你告诉我如何复制惊人的 O(1)
查找算法,我肯定会得到一个大胖字典,这样我就可以向我所有的 friend 炫耀我的忍者-查字典的技巧)
编辑:大多数答案似乎都取决于这个假设:
You have the ability to access any page of a dictionary given its page number in constant time
如果这是真的,我很容易看出来。但我不知道为什么这个基本假设是正确的:我会使用相同的过程来按数字查找页面,就像我按单词查找页面一样。
与内存地址相同,加载内存地址使用什么算法?是什么让从一个地址找到一 block 内存如此便宜?换句话说,为什么内存访问是O(1)
?
最佳答案
您应该阅读 Wikipedia article .
但本质是您首先对您的 key 应用哈希函数,将其转换为整数索引(这是 O(1)
)。然后将其用于对数组进行索引,这也是 O(1)
。如果哈希函数设计得很好,数组中的每个位置应该只存储一项(或几项),因此查找完成。
所以在大量简化的伪代码中:
ValueType array[ARRAY_SIZE];
void insert(KeyType k, ValueType v)
{
int index = hash(k);
array[index] = v;
}
ValueType lookup(KeyType k)
{
int index = hash(k);
return array[index];
}
显然,这不会处理碰撞,但您可以阅读这篇文章以了解它是如何处理的。
更新
为了解决编辑后的问题,对数组进行索引是 O(1) 因为在引擎盖下,CPU 正在这样做:
ADD index, array_base_address -> pointer
LOAD pointer -> some_cpu_register
其中 LOAD
加载存储在内存中指定地址的数据。
更新 2
从内存加载是 O(1)
的原因实际上只是因为这是我们在谈论计算复杂性时通常指定的公理(参见 http://en.wikipedia.org/wiki/RAM_model)。如果我们忽略缓存层次结构和数据访问模式,那么这是一个合理的假设。当我们扩展机器的规模时,这可能不是真的(具有 100TB 存储的机器可能与具有 100kB 的机器花费的时间不同)。但通常,我们假设我们机器的存储容量是恒定的,并且比我们可能看到的任何问题规模都大得多。因此,就所有意图和目的而言,这是一个恒定时间的操作。
关于algorithm - 是什么让表查找如此便宜?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7287144/
我有一台 MySQL 服务器和一台 PostgreSQL 服务器。 需要从多个表中复制或重新插入一组数据 MySQL 流式传输/同步到 PostgreSQL 表。 这种复制可以基于时间(Sync)或事
如果两个表的 id 彼此相等,我尝试从一个表中获取数据。这是我使用的代码: SELECT id_to , email_to , name_to , status_to
我有一个 Excel 工作表。顶行对应于列名称,而连续的行每行代表一个条目。 如何将此 Excel 工作表转换为 SQL 表? 我使用的是 SQL Server 2005。 最佳答案 这取决于您使用哪
我想合并两个 Django 模型并创建一个模型。让我们假设我有第一个表表 A,其中包含一些列和数据。 Table A -------------- col1 col2 col3 col
我有两个表:table1,table2,如下所示 table1: id name 1 tamil 2 english 3 maths 4 science table2: p
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 1 年前。 Improve th
下面两个语句有什么区别? newTable = orginalTable 或 newTable.data(originalTable) 我怀疑 .data() 方法具有性能优势,因为它在标准 AX 中
我有一个表,我没有在其中显式定义主键,它并不是真正需要的功能......但是一位同事建议我添加一个列作为唯一主键以随着数据库的增长提高性能...... 谁能解释一下这是如何提高性能的? 没有使用索引(
如何将表“产品”中的产品记录与其不同表“图像”中的图像相关联? 我正在对产品 ID 使用自动增量。 我觉得不可能进行关联,因为产品 ID 是自动递增的,因此在插入期间不可用! 如何插入新产品,获取产品
我有一个 sql 表,其中包含关键字和出现次数,如下所示(尽管出现次数并不重要): ____________ dog | 3 | ____________ rat | 7 | ____
是否可以使用目标表中的LAST_INSERT_ID更新源表? INSERT INTO `target` SELECT `a`, `b` FROM `source` 目标表有一个自动增量键id,我想将其
我正在重建一个搜索查询,因为它在“我看到的”中变得多余,我想知道什么 (albums_artists, artists) ( ) does in join? is it for boosting pe
以下是我使用 mysqldump 备份数据库的开关: /usr/bin/mysqldump -u **** --password=**** --single-transaction --databas
我试图获取 MySQL 表中的所有行并将它们放入 HTML 表中: Exam ID Status Assigned Examiner
如何查询名为 photos 的表中的所有记录,并知道当前用户使用单个查询将哪些结果照片添加为书签? 这是我的表格: -- -- Table structure for table `photos` -
我的网站都在 InnoDB 表上运行,目前为止运行良好。现在我想知道在我的网站上实时发生了什么,所以我将每个页面浏览量(页面、引荐来源网址、IP、主机名等)存储在 InnoDB 表中。每秒大约有 10
我在想我会为 mysql 准备两个表。一个用于存储登录信息,另一个用于存储送货地址。这是传统方式还是所有内容都存储在一张表中? 对于两个表...有没有办法自动将表 A 的列复制到表 B,以便我可以引用
我不是程序员,我从这个表格中阅读了很多关于如何解决我的问题的内容,但我的搜索效果不好 我有两张 table 表 1:成员 id*| name | surname -------------------
我知道如何在 ASP.NET 中显示真实表,例如 public ActionResult Index() { var s = db.StaffInfoDBSet.ToList(); r
我正在尝试运行以下查询: "insert into visits set source = 'http://google.com' and country = 'en' and ref = '1234
我是一名优秀的程序员,十分优秀!