我有两个无序的整数数组,我需要知道这些数组有多少个整数

时间:2009-07-03 12:32:50

标签: php arrays sorting

我在LAMP环境中工作,所以PHP是语言;至少我可以使用python。

正如标题所说我有两个无序的整数数组。

$array_A = array(13, 4, 59, 38, 9, 69, 72, 93, 1, 3, 5)

$array_B = array(29, 72, 21, 3, 6)

我想知道这些数组有多少个整数;在示例中,您看到结果是2.我对整数的共同点不感兴趣,如(72,3)。

我需要一个更快的方法,而不是采用数组B的每个元素并检查它是否在数组A(O(nxm))

数组可以通过asort或sql排序进行排序(它们来自sql结果)。

我想到的一个想法是为每个数组创建一个'向量',其中整数是一个得到值为1且不存在的整数得到0的位置。

因此,对于数组A(从第1位开始)

(1, 0, 1, 1, 1, 0, 0, 0, 1, 0, ...)

阵列B相同

(0, 0, 1, 0, 0, 1, ...)

然后将这两个向量与一个周期进行比较。问题是,这样矢量长度约为400k。

6 个答案:

答案 0 :(得分:8)

根据您的数据(大小),您可能希望使用array_intersect_key()而不是array_intersect()。显然,array_intersect(测试php 5.3)的实现不使用任何优化/缓存/但是循环遍历数组并逐个比较数组A中每个元素的值。哈希表查找比这快得多。

<?php
function timefn($fn) {
    static $timer = array();
    if ( is_null($fn) ) {
        return $timer;
    }
    $x = range(1, 120000);
    $y = range(2, 100000);
    foreach($y as $k=>$v) { if (0===$k%3) unset($y[$k]); }

    $s = microtime(true);
    $fn($x, $y);
    $e = microtime(true);

    @$timer[ $fn ] += $e - $s; 
}

function fnIntersect($x, $y) {
    $z = count(array_intersect($x,$y));
}

function fnFlip($x, $y) {
    $x = array_flip($x);
    $y = array_flip($y);
    $z = count(array_intersect_key($x, $y));
}


for ($i=0; $i<3; $i++) {
    timefn( 'fnIntersect' );
    timefn( 'fnFlip' );
}

print_r(timefn(null));

打印

Array
(
    [fnIntersect] => 11.271192073822
    [fnFlip] => 0.54442691802979
)
这意味着我的笔记本上的array_flip / intersect_key方法快了~20倍。 (像往常一样:这是一个临时测试。如果你发现错误,告诉我......我期待那个;-))

答案 1 :(得分:3)

我对PHP知之甚少,所以你可能会从别人那里得到更具体的答案,但我想提出一种与语言无关的方法。

通过检查A中的每个元素对B中的每个元素,确实是O(n 2 )[我假设这里的数组长度相同,以简化方程式但是相同的推理将保留不同长度的数组]。

如果要对两个数组中的数据进行排序,可以将时间复杂度降低到O(n log n)或类似值,具体取决于所选的算法。

但是你需要记住,复杂性对于更大的数据集才真正变得重要。如果你给出的这两个数组是典型的大小,我会说不要对它进行排序,只需使用“将所有内容与所有内容进行比较”方法 - 排序不会给你足够的优势。 50个元素的数组仍然只能给你2,500次迭代(不管PHP是否可以接受,我不知道,对于C语言和其他编译语言来说,它肯定会脱离它的后代。)

在任何人跳入并声明你应该计划更大的数据集以防万一,这是YAGNI,因为不必要的过早优化。您可能从不需要它,在这种情况下,您浪费的时间本来可以更好地花在其他地方。实现这个问题的时间就是它成为一个问题(当然,我认为,其他人可能不同意)。

如果数据集确实足够大以使O(n 2 )不可行,我认为排序然后并行遍历数组可能是你最好的选择。

另一种可能性是如果数字的范围不是太大 - 那么你提出的布尔矢量解决方案是非常可行的,因为那将是O(n),走两个数组以填充矢量,然后比较固定的两个向量内的位置。但我假设你的范围太大,或者你不会提到400K的要求。但同样,数据集的大小将决定这是否值得做。

答案 2 :(得分:2)

最简单的方法是:

count(array_intersect($array_A, $array_B));

如果我明白你在追求什么。 应该很快。

答案 3 :(得分:0)

如果两个数组都来自SQL,您是否可以在2组数据上编写带有内部联接的SQL查询以获得结果?

答案 4 :(得分:0)

您需要array_intersect()功能。从那里你可以计算结果。在你知道自己遇到问题之前不要担心速度。内置函数的执行速度比用PHP编写的任何函数都要快得多。

答案 5 :(得分:0)

我编写了一个PHP扩展,它提供了有效集合操作的功能,如并集,交集,二进制搜索等。内部数据布局是存储在PHP字符串中的普通int32_t数组。操作基于合并算法。

示例:

    // Create two intarrays
    $a = intarray_create_from_array(array(1, 2, 3));
    $b = intarray_create_from_array(array(3, 4, 5));
    // Get a union of them
    $u = intarray_union($a, $b);
    // Dump to screen
    intarray_dump($u);

可在此处找到:https://github.com/tuner/intarray