如何比较两组1000个数字?

bak*_*lap 64 javascript php sql algorithm

我必须检查大约1000个数字和1000个其他数字.

我加载了两个并比较了服务器端:

foreach( $numbers1 as $n1 ) {
  foreach( $numbers2 as $n2 ) {
    if( $n1 == $n2 ) {
      doBla();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这需要很长时间,所以我尝试使用两个隐藏div元素进行相同的比较客户端 .然后使用JavaScript比较它们.加载页面仍然需要45秒(使用隐藏div元素).

我不需要加载不相同的数字.

有更快的算法吗?我正在考虑比较它们的数据库端,只是加载错误号,然后对剩余的非错误号进行Ajax调用.但MySQL数据库是否足够快?

Poi*_*nty 129

首先对列表进行排序.然后你可以从头开始走两个列表,比较你去的地方.

循环看起来像这样:

var A = getFirstArray().sort(), B = getSecondArray().sort();

var i = 0, j = 0;
while (i < A.length && j < B.length) {
    if (A[i] === B[j]) {
        doBla(A[i]);
        i++; j++;
    }
    else if (A[i] < B[j]) {
        i++;
    }
    else
        j++;
}
Run Code Online (Sandbox Code Playgroud)

(那是JavaScript;你也可以在服务器端做,但我不懂PHP.)

编辑 - 为了公平对待所有哈希表粉丝(我当然尊重他们),在JavaScript中这很容易做到:

var map = {};
for (var i = 0; i < B.length; ++i) map[B[i]] = true; // Assume integers.
for (var i = 0; i < A.length; ++i) if (map[A[i]]) doBla(A[i]);
Run Code Online (Sandbox Code Playgroud)

或者,如果数字是或可能是浮点数:

var map = {};
for (var i = 0; i < B.length; ++i) map['' + B[i]] = true; // Assume integers.
for (var i = 0; i < A.length; ++i) if (map['' + A[i]]) doBla(A[i]);
Run Code Online (Sandbox Code Playgroud)

由于哈希数字相当便宜(即使在JavaScript中,在散列之前转换为字符串也非常便宜),这将非常快.

  • 如果*m*和*n*都很大 - 正如问题中所规定的那样 - 那么排序是绝对的,肯定会更快.算一算!对1000个元素的数组进行排序约为3000次操作,因此3000 + 3000 + 1000.但1000*1000是*工作量的*100倍*. (66认同)
  • 是的,但对于两个大小为1000的数组,即1000*lg(1000)+ 1000*lg(1000)+ 1000,其中~2000*10 + 1000,其中~21000.OP的方法,m*n时间为1000 ^ 2即1000000. 21000 << 1000000.这就是为什么渐近评估很重要 - n ^ 2 = o(n*lg(n)),n*lg(n)= O(m*n),这意味着Pointy的方法是非常快,如lg(n)<< n (24认同)
  • @Kache4这将是一个相当简单的改变 - 我将把它留给读者练习:-) (12认同)
  • 此代码不会重现OP的代码所做的事情.如果`x`分别在列表1和2中出现`x1`次和'x2'次,`doBla()`应该运行`x1*x2`次,这不是这里的情况. (6认同)
  • 如果它不是,则..如果A的大小为n,B的大小为m,则需要nlg(n)+ mlg(m)+ min(m,n)时间,而OP的方法仅为mn. .. (4认同)
  • @Pointy:我不认为*你*理解哈希.给定足够的初始内存容量(10000/50000可能会好,取决于散列算法),不太可能发生冲突.你使用的内存越多,你碰撞的可能性就越小.散列步骤是非常恒定的时间,因为它可能只是使用一些基本的数学.地狱,如果你知道范围,你可以创建一个大小为[1..N]的布尔数组,其中N是最大可能值.现在你有一个更好的O(n)算法,以牺牲内存为代价. (2认同)
  • 为什么不是很聪明的问题得到这么多的赞成? (2认同)
  • 这可能是程序员对算法理解不足的一种说法.而且不知道语言是没有理由改变你的解决方案或推广一个糟糕的算法.算法独立于语言. (2认同)

Phi*_*ord 85

  • @dhruvbird问题'我必须检查大约1000个数字和1000个其他数字.' 上面的PHP函数就像问一样.返回的输出应该是所需的结果,用户可以轻松地操作以利用他们的doBla() (3认同)

Pre*_*gha 27

在数据库术语中,这可以是1000行到另外1000行的连接.任何现代数据库系统都可以处理.

select x from table1
inner join table2
on table1.x = table2.y
Run Code Online (Sandbox Code Playgroud)

其中,table1table2是有关行,可能是同一个表.

  • 正如Preet所说,+1是一个现代的Db,比如...... 1974年后的P: (15认同)
  • 我不确定为什么会假设这些数组的元素来自数据库.是因为他在PHP和Javascript中演示了一个例子吗?来源可以是任何东西,真的. (4认同)

mar*_*mnl 26

你不应该花那么长时间 - doBla()做什么?我怀疑是花时间吗?使用相同的算法比较两组1000000个数字根本不需要时间.

这很有趣 - 作为答案的优化技术的数量 - 问题不是你的算法 - 它是什么doBla()做的是花费时间比任何优化可以帮助你多倍的因子:) esp.鉴于套装只有1000长,你必须先对它们进行排序..

  • 我想知道你为什么要投票?当然,你是对的 - 即使是他所得到的蛮力比较也应该相当快.在典型情况下,他必须多次调用doBla,否则每次执行都需要很长时间...... (4认同)

sod*_*sod 23

也许只是交叉数组值来查找两个数组中存在的数字?

$result = array_intersect($numbers1, $numbers2);
foreach ($result as $val)
  doBla();
Run Code Online (Sandbox Code Playgroud)


Gio*_*lbo 9

如果您首先对list2进行排序,然后对list1中的每个数字进行二进制搜索,您将看到速度大幅提升.

不是一个PHP人,但这应该给你的想法:

sort($numbers2);

foreach($numbers1 as $n1)
{
   if (BinarySearch($numbers2, $n1) >= 0) {
     doBla();
 }
}
Run Code Online (Sandbox Code Playgroud)

显然不是一个PHP人我不知道库,但我确信排序和二进制搜索应该很容易找到.

注意:如果您不熟悉二进制搜索; 你正在对list2进行排序,因为二进制搜索需要对排序列表进行操作.


JRL*_*JRL 5

先排序它们.


mun*_*ent 5

我不是PHP专家,所以这可能需要一些调试,但你可以在O(n)时间内轻松完成:

// Load one array into a hashtable, keyed by the number: O(n).
$keys1 = [];
foreach($numbers1 as $n1) $keys1[$n1] = true;

// Find the intersections with the other array:
foreach($numbers2 as $n2) { // O(n)
  if (isset($keys1[$n2]) { // O(1)
     doBla();
  }
}
Run Code Online (Sandbox Code Playgroud)

无论如何,交汇点不是你的时间.即使像你现在这样糟糕的O(n ^ 2)实现也应该能够在一秒钟内完成1000个数字.


det*_*tch 5

- 你为什么要这样做?

如果数字已经在SQL数据库中,那么进行连接并让DB找出最有效的路由.

如果他们不在数据库中,那么我打赌你已经离开了某个地方,真的应该重新考虑你是如何到达这里的.