php算法

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的就可以了

参考牛逼哄哄的 BitMap,到底强在哪里?(腾讯三面:给你20亿个QQ号,如何去重?)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值