PHP实现数组相邻元素不重复的高效解决方案求助
嘿,这个问题我之前也碰到过——反复打乱数组的思路虽然简单,但在元素数量多或者某类元素占比很高的时候,不仅效率极低,甚至可能陷入死循环(比如数组里全是同一个元素,根本没法满足相邻不重复的要求)。下面给你几个高效的实现思路,亲测好用:
高效实现相邻元素不重复的方法
1. 先校验可行性:避免做无用功
首先得先判断这个数组能不能转换成相邻不重复的数组——如果某个元素的出现次数超过数组长度的一半(向上取整),比如长度为6的数组,某个元素出现4次,那无论怎么排列都做不到相邻不同。所以第一步必须做这个校验:
- 统计每个元素的出现频率
- 检查最大频率是否大于
ceil(n/2)(n是数组长度),如果是直接返回“无法实现”的提示
2. 贪心算法:优先放置高频元素(最推荐)
这是工业场景里最常用的高效方案,核心思路是先把频率最高的元素分散放置,避免它们扎堆,再填充剩下的元素。具体步骤:
- 把元素按出现频率从高到低排序
- 先将高频元素依次放到数组的偶数索引位置(0、2、4...)
- 偶数位填满后,切换到奇数索引位置(1、3、5...),继续填充剩下的元素
给你写个PHP的实现示例,刚好匹配你给出的输入格式:
function rearrangeAdjacentUnique($arr) { // 统计每个元素的出现次数 $frequency = array_count_values($arr); $arrayLength = count($arr); // 先校验是否能实现 $maxFrequency = max($frequency); if ($maxFrequency > ceil($arrayLength / 2)) { return false; // 无法生成相邻不重复的数组 } // 按频率从高到低排序元素 arsort($frequency); $result = array_fill(0, $arrayLength, null); $currentIndex = 0; // 先填充偶数索引位置 foreach ($frequency as $item => $count) { while ($count > 0 && $currentIndex < $arrayLength) { $result[$currentIndex] = $item; $count--; $currentIndex += 2; } // 如果偶数位用完了,切换到奇数位 if ($currentIndex >= $arrayLength) { $currentIndex = 1; } // 填充剩余的元素到奇数位 while ($count > 0) { $result[$currentIndex] = $item; $count--; $currentIndex += 2; } } return $result; } // 测试你的示例输入 $input = array("red","red","blue","green","green","blue"); $output = rearrangeAdjacentUnique($input); print_r($output); // 输出示例:Array ( [0] => red [1] => green [2] => red [3] => green [4] => blue [5] => blue ) // 注:输出顺序可能和你给的示例不完全一致,但完全满足相邻元素不重复的要求;如果需要特定顺序,可以微调填充逻辑,但核心逻辑不变
3. 交换法:适合原数组接近目标状态的场景
如果你的原数组大部分元素已经满足相邻不重复,只有少数几处重复,可以用遍历交换的思路:遇到相邻重复的元素,就和后面第一个不重复的元素交换位置。这种方法实现简单,但最坏情况下效率不如贪心算法:
function fixAdjacentDuplicates($arr) { $arrayLength = count($arr); for ($i = 0; $i < $arrayLength - 1; $i++) { if ($arr[$i] == $arr[$i+1]) { // 寻找后面第一个不同的元素 $swapIndex = $i + 2; while ($swapIndex < $arrayLength && $arr[$swapIndex] == $arr[$i]) { $swapIndex++; } // 找不到的话,说明无法调整 if ($swapIndex >= $arrayLength) { return false; } // 交换i+1和swapIndex位置的元素 $temp = $arr[$i+1]; $arr[$i+1] = $arr[$swapIndex]; $arr[$swapIndex] = $temp; } } return $arr; }
为什么不推荐反复打乱?
反复打乱的时间复杂度是完全不确定的——运气好一次就成功,运气差可能要打乱几十上百次,尤其是当元素频率接近临界值的时候(比如长度5,某元素出现3次),成功率极低,大数据量下完全不可行。而贪心算法的时间复杂度是O(n log n)(主要来自频率排序),效率稳定,处理百万级别的数组也没问题。
内容的提问来源于stack exchange,提问作者nawanTSL
相关产品推荐
相关产品推荐

