当前位置: 首页 > 面试题库 >

如何计算两个列表的增量(插入/删除/移动索引)?

吴峰
2023-03-14
问题内容

假设我有两个具有唯一ID的对象列表和一个确定其顺序的属性,那么如何有效地获取增量索引(插入了哪些索引,删除了哪些索引以及移动了哪些索引)?

输入示例:

let before: [(id: String, timestamp: String)] = [
    ("A", "2015-06-04T12:38:09Z"),
    ("B", "2015-06-04T10:12:45Z"),
    ("C", "2015-06-04T08:39:55Z"),
    ("D", "2015-06-03T23:58:32Z"),
    ("E", "2015-06-01T00:05:51Z"),
]

let after: [(id: String, timestamp: String)] = [
    ("F", "2015-06-04T16:13:01Z"),
    ("C", "2015-06-04T15:10:29Z"),
    ("A", "2015-06-04T12:38:09Z"),
    ("B", "2015-06-04T10:12:45Z"),
]

let delta = deltaFn(before, after)

上面是可视化的:

BEFORE                                   AFTER
+-------+----+----------------------+    +-------+----+----------------------+
| index | id | timestamp            |    | index | id | timestamp            |
+-------+----+----------------------+    +-------+----+----------------------+
|     0 |  A | 2015-06-04T12:38:09Z |    |     0 |  F | 2015-06-04T16:13:01Z |
|     1 |  B | 2015-06-04T10:12:45Z |    |     1 |  C | 2015-06-04T15:10:29Z |
|     2 |  C | 2015-06-04T08:39:55Z |    |     2 |  A | 2015-06-04T12:38:09Z |
|     3 |  D | 2015-06-03T23:58:32Z |    |     3 |  B | 2015-06-04T10:12:45Z |
|     4 |  E | 2015-06-01T00:05:51Z |    |     - |    |                      |
+-------+----+----------------------+    +-------+----+----------------------+

预期结果(增量):

Inserted indexes:  [0]
Deleted indexes:   [3, 4]
Moved indexes:     [(from: 0, to: 2), (from: 1, to: 3), (from: 2, to: 1)]

问题答案:

可以通过使用2个映射(从每个元素的ID到其索引的映射)并将它们进行比较来解决。

对于哈希映射,时间复杂度为O(n),对于基于树的映射,时间复杂度为O(nlogn)。

伪代码:

map1 = empty map
map2 = empty map
for each element x with index i in before:
    map1.insert(x,i)
for each element x with index i in after:
    map2.insert(x,i)

//find moved and deleted:
for each key x in map1:
   id1 = map1.get(x)
   id2 = map2.get(x)
   if id2 == nil:
       add id1 to "deleted indexes"
   else if id1 != id2:
       add (id1,id2) to "moved indexes"
       map2.delete(x)
//find new indexes:
for each key x in map2:
    add map2.get(x) to "inserted indexes"

编辑 :(建议在评论中)

通过仅映射最小的列表,然后迭代数组(未映射)而不是映射,可以将O(min{m,n})基于树的映射到的内存输出和时间减到最少(两个列表的大小O(max{m,n}log(min{m,n}))在哪里m,n)。

map = empty map
for each element x with index i in smaller list:
    map.insert(x,i)

for each element x with index i1 in larger list:
   i2 = map.get(x)
   if i2:
       if i1 != i2:
           add (i2, i1) to "moved indexes" if smaller list is before
           add (i1, i2) to "moved indexes" if smaller list is after
       map.delete(x)
   else:
       add i1 to "inserted indexes" if smaller list is before
       add i1 to "deleted indexes" if smaller list is after

// Find new indexes:
for each key x in map:
    add map.get(x) to "deleted indexes" if smaller list is before
    add map.get(x) to "inserted indexes" if smaller list is after


 类似资料:
  • 我的应用程序使用SpringMVC+Hibernate+MySQL组合 我从一开始就纠结于一个问题- “在我的应用程序中,有些表使用Hibernate添加了自动递增功能.因此,当我删除任何记录时,当我再次插入一些记录时,我没有得到正确的顺序.” 为。假设我的表ABC最初有100条记录(例如,abc_id的主键具有从1到100的正确顺序的值)。 当我删除。50个记录,再插入50个记录,但这个时间序列

  • 问题内容: 我生成一个SQLite表(在Java中): 之后,我尝试使用INSERT命令添加行: 我得到错误: 我以为行ID会自动生成,但似乎我什么都没想。 我尝试了另一种解决方案: 结果,我在“ prep.setInt(1,n);”处收到一个空指针异常。 看到故障了吗? 问题答案: 您是否尝试指出要传递的参数应该与表的哪些字段相关? 在您的情况下,可能类似于:

  • 在Liquibase留档中,我可以看到的ChangeSet操作...然而,与之相反的(?)似乎不存在。 在数据库表中,我已从单字段自动增量id()切换为复合id(超过3列)。在3列上添加新的主索引(、、)似乎工作正常。 在新设计下,我的应用程序可以显式设置WidgetId(例如:1、2、3…等) 但是,当我的应用程序将新数据插入表时,我收到以下错误: 当我查看表时,的类型是-这是以前数据库设计的遗

  • 问题内容: 我正在寻找这样的查询: id | int | 自动增量 varchar | 255 这样桌子就看起来像 1 | val1 2 | val2 3 | val3 … 除了id总是以每一行都结束而已。 我怎样才能做到这一点? 问题答案:

  • 问题内容: 如何在Java中计算两个角度量度(以度为单位)的差,使结果在[0°,180°]范围内? 例如: 问题答案: /* * Shortest distance (angular) between two angles. * It will be in range [0, 180]. / public static int distance(int alpha, int beta) { int

  • 问题内容: 使用Postgres,我试图用SQL自动编号主键。但是,这给了我一个错误。 错误: 知道为什么吗? 问题答案: Postgres 10或更高版本 列(请参见下文)保持不变。但是考虑一个 专栏。Postgres10实现了此标准SQL功能。 手册中的基本语法和信息。 __用列 创建 表 将 列 添加 到现有表 表可能填充也可能不填充行。 同时使它成为PK(表还不能拥有PK): 有关的: 如