这个排列组合的算法我得好好记录下

排列组合很常见的算法,但是这是第一次从元素中删除全部可能性元素再进行排列这样计算,得记录记录。。。。
比如 数组有1,2两个元素,排列组合为[1,2],[2,1],[1],[2]
但是得注意一下,如果数组元素过多可能会内存溢出

<?php

class KeywordLogic
{
    /**
     * 获取新的字符串
     * @param string $word
     * @param $pubProductId
     * @param $siteLangId
     * @return string
     */
    public function getShuffle(string $word,$pubProductId,$siteLangId): string
    {
        Log::getInstance()->info(__CLASS__.'@'.__FUNCTION__."开始处理",['args'=>func_get_args()]);
        $historyArray = KeywordShuffleCache::get($pubProductId,$siteLangId);
        $historyArray[] = $word;
        KeywordShuffleCache::storage($pubProductId,$siteLangId,$word);
        $newWord = $this->generateNewString($word,$historyArray);
        KeywordShuffleCache::storage($pubProductId,$siteLangId,$newWord);
        return $newWord;
    }

    /**
     * 生成新的字符串
     * @param $inputString
     * @param $historyArray
     * @return string
     */
    private function generateNewString($inputString, $historyArray): string
    {
        // 将输入字符串转换为字符数组
        
        if(strpos($inputString,PHP_EOL)!==false){
            $strList = array_values(array_filter(explode(PHP_EOL,$inputString)));
            $fuhao = PHP_EOL;
        }else{
            $strList = array_values(array_filter(explode(" ",$inputString)));
            $fuhao = " ";
        }
        $permutations = $this->getAllPermutations($strList);
        // 遍历所有排列,查找不在历史数组中的字符串
        foreach ($permutations as $permutation) {
            $newString = implode($fuhao, $permutation);
            if (!in_array($newString, $historyArray)) {
                // 如果找到新字符串,返回它
                Log::getInstance()->info(__CLASS__.'@'.__FUNCTION__."找到了未使用过的组合字符串",['args'=>func_get_args(),'result'=>$newString]);
                return $newString;
            }
        }
        // 如果没有找到新字符串,随便返回一个
        $randomIndex = rand(0,count($strList)-1);
        $newString = implode($fuhao,$permutations[$randomIndex]);
        Log::getInstance()->info(__CLASS__.'@'.__FUNCTION__."全部使用过,随机返回1个",['args'=>func_get_args(),'result'=>$newString,"permutations"=>$permutations,'randomIndex'=>$randomIndex]);
        return $newString;
    }

    /**
     * 获取全部元素及全部减少后元素的排列组合
     * @param array $arr
     * @return array|array[]
     */
    private function getAllPermutations(array $arr): array
    {
        $permutations = $this->getPermutations($arr);

        $maxReducedNum = count($arr)-1;
        if($maxReducedNum){
            for($reducedNum=1;$reducedNum<=$maxReducedNum;$reducedNum++){
                //减哪几个元素呢
                $diffCombinationList = $this->getCombinations($arr,$reducedNum);
                foreach($diffCombinationList as $diffItemList){
                    $reducedArr = array_diff($arr,$diffItemList);
                    $permutations = array_merge($permutations,$this->getPermutations($reducedArr));
                }
            }
        }
        return $permutations;
    }

    /**
     * 根据数组元素生成全部排列组合值
     * @param $items
     * @param array $perms
     * @return array|array[]
     */
    private function getPermutations($items, $perms = array()): array
    {
        if (empty($items)) {
            return array($perms);
        } else {
            $return = array();
            for ($i = count($items) - 1; $i >= 0; --$i) {
                $newItems = $items;
                $newPerms = $perms;
                list($foo) = array_splice($newItems, $i, 1);
                array_unshift($newPerms, $foo);
                $return = array_merge($return, $this->getPermutations($newItems, $newPerms));
            }
            return $return;
        }
    }

    /**
     * 从数组中挑出指定个数的元素的全部可能的组合
     * @param $base
     * @param $n
     * @return array|array[]
     */
    private function getCombinations($base, $n): array
    {
        $baseLen = count($base);
        if ($n == 0) {
            return array(array());
        } else {
            $result = array();
            for ($i = 0; $i <= $baseLen - $n; $i++) {
                $temp1 = $base[$i];
                $temp2 = array_slice($base, $i + 1);
                foreach ($this->getCombinations($temp2, $n - 1) as $subCombo) {
                    array_unshift($subCombo, $temp1);
                    $result[] = $subCombo;
                }
            }
            return $result;
        }
    }
}

测试执行结果

$result = (new KeywordLogic())->getShuffle("hello word",123,'jp');
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值