1、递归
2、去重
1、最简单的方式array_unique
2、用array_flip 交换键值,实现去重,array_keys 获取keys
3、通过bitmap去重
3、bitmap操作 (查找,排序,去重)
- 去重
// bitmap方式对qq号去重,要求:我们需要知道qq号的三种状态,存在、不存在、重复
/**
*
*分析:我们需要采用bit位的方式来保存qq号,所以位最大长度取决于最大的qq号码大小,所有qq信息保存在bitmap数组内;
* qq号要保存3种状态,所以1个qq号需要2bit去保存状态信息(用00标识不存在,01标识存在,11标识重复)
* 假设qq最大号码位99999999999 则,需要(9999999999 + 1) * 2bit去保存所有可能的qq号信息 (考虑qq号为0的情况,所以需要+1)
* 我们假设代码运行在32位的机器,1个int是4个字节,也就是32bit,所以1个int可以保存32 / 2 = 16个qq的信息,所以我们需要的bitmap数组长度为(9999999999 + 1)/ 16
* 一个qq号处于bitmap数组的位置:索引位置= qq号 / 16(商) bit位置:起始位置(qq号 % 16)*2 ,结束位置 (qq号 % 16)*2 + 1
*/
$box = ["123","456","789","123"];
$qq_max = 99999999999; // 目前qq11,位理论最大值99999999999
// $max_len = 1 + intval(($qq_max + 1) / 16);
// 数组的理论大小为数组长度 * int大小(4字节)$max_len * 4 / 1024 / 1024 / 1024 = 23G,远远低于通过变量方式存储
// 如果通过变量存储理论大小99999999999 * 4 / 1024 / 1024 / 1024 = 372G
$bitmap = []; // bitmap数组
foreach ($box as $val) {
$index = intval($val / 16); // qq号对应索引位置
$bit_start = ($val % 16) * 2 ; // qq号对应比特位起始位置
$bit_stop = ($val % 16) * 2 + 1 ; // qq号对应比特位结束位置
if (!isset($bitmap[$index])) {
$bitmap[$index] = 0;
}
$bit_start_bool = $bitmap[$index] & 1 << $bit_start;
$bit_stop_bool = $bitmap[$index] & 1 << $bit_stop;
if (!$bit_start_bool && !$bit_stop_bool) { // 之前没有存储过这个qq号,qq号状态为存在01
$bitmap[$index] |= 1 << $bit_start;
} else if ($bit_start_bool && !$bit_stop_bool) { // 之前存储过这个qq号 则qq号状态变为重复11,
$bitmap[$index] |= 1 << $bit_stop;
} else {
// 之前已经是重复的状态,则不做任何操作
}
}
// 判断qq号状态
$test = ["123","456","234"];
foreach ($test as $val) {
$index = intval($val / 16); // qq号对应索引位置
$bit_start = ($val % 16) * 2 ; // qq号对应比特位起始位置
$bit_stop = ($val % 16) * 2 + 1 ; // qq号对应比特位结束位置
if (!isset($bitmap[$index])) {
echo 'qq号 '.$val.' 不存在'.PHP_EOL;
continue;
}
$bit_start_bool = $bitmap[$index] & 1 << $bit_start;
$bit_stop_bool = $bitmap[$index] & 1 << $bit_stop;
if (!$bit_start_bool) { // 之前没有存储过这个qq号,qq号状态为存在01
echo 'qq号 '.$val.' 不存在'.PHP_EOL;
} else if ($bit_stop_bool) { // 之前存储过这个qq号 则qq号状态变为重复11,
echo 'qq号 '.$val.' 存在且重复'.PHP_EOL;
} else {
echo 'qq号 '.$val.' 存在但不重复'.PHP_EOL;
}
}
-
查找
只要在去过重的bitmap相应的索引和bit位判断0,1就可以了 -
排序
只要从索引0,索引1,索引2… 依次去除bit位为1的就可以了