php判断数组连续

admin 102 0
在PHP中判断数组是否连续,通常指数组元素为连续整数(如[1,2,3]或[5,4,3]),实现方法:先通过array_unique()去重,再排序(升序/降序),然后遍历检查相邻元素差是否为1,更高效的方式是数学验证:若max($arr) - min($arr) + 1 == count(array_unique($arr)),则数组连续,需注意单元素数组默认连续,空数组可视为非连续,此方法适用于无重复元素的连续整数判断,适用于数据校验、序列验证等场景。

PHP如何高效判断数组是否连续:方法解析与代码实践

在PHP开发中,判断数组是否"连续"是一个常见需求,这里的"连续"通常指数组元素在数学上构成连续的整数序列(如[1,2,3,4][5,4,3,2]),或字符串数组按字母顺序连续(如['a','b','c']),本文将详细解析不同场景下的判断方法,并提供可落地的代码实现。

明确"连续"的定义

在开始编码前,需先明确"连续"的具体场景,常见的定义包括:

  1. 升序连续整数:元素按从小到大排列,且相邻元素差为1(如[3,4,5,6]);
  2. 降序连续整数:元素按从大到小排列,且相邻元素差为-1(如[8,7,6,5]);
  3. 允许重复的连续整数:元素可重复,但核心序列连续(如[1,2,2,3]是否算连续需明确需求);
  4. 字符串连续:按字母顺序连续(如['x','y','z'],即ASCII码连续);
  5. 环形连续:首尾相连的连续序列(如[3,4,5,1,2])。

本文以不重复的整数数组连续判断为核心,兼顾其他场景的扩展方案。

核心方法:升序/降序连续判断

方法思路

判断数组是否连续,核心逻辑是:

  • 升序连续:数组排序后,每个元素比前一个元素大1;
  • 降序连续:数组排序后,每个元素比前一个元素小1;
  • 边界情况:空数组或单元素数组,通常视为"连续"(可根据需求调整);
  • 性能考虑:对于大数组,应避免不必要的排序操作。

代码实现

以下是一个通用的判断函数,支持升序/降序模式,并允许配置是否允许重复元素:

/**
 * 判断数组是否连续(整数序列)
 * @param array $arr 待判断数组
 * @param string $order 排序方向:'asc'(升序)或'desc'(降序)
 * @param bool $allowDuplicates 是否允许重复元素
 * @return bool
 */
function isConsecutiveArray(array $arr, string $order = 'asc', bool $allowDuplicates = false): bool
{
    // 边界情况:空数组或单元素数组,视为连续
    if (count($arr) <= 1) {
        return true;
    }
    // 去重(如果不允许重复)
    if (!$allowDuplicates) {
        $uniqueArr = array_unique($arr);
        if (count($uniqueArr) !== count($arr)) {
            return false; // 存在重复元素,直接返回false
        }
        $arr = $uniqueArr;
    }
    // 排序(升序或降序)
    if ($order === 'asc') {
        sort($arr);
    } else {
        rsort($arr);
    }
    // 遍历判断相邻元素差是否为1(升序)或-1(降序)
    for ($i = 1; $i < count($arr); $i++) {
        $prev = $arr[$i - 1];
        $current = $arr[$i];
        if ($order === 'asc' && $current - $prev !== 1) {
            return false;
        }
        if ($order === 'desc' && $prev - $current !== 1) {
            return false;
        }
    }
    return true;
}

性能优化版本

对于大型数组,我们可以优化性能,避免不必要的排序操作:

/**
 * 高效判断数组是否连续(无需排序)
 * @param array $arr 待判断数组
 * @return bool
 */
function isConsecutiveArrayOptimized(array $arr): bool
{
    if (count($arr) <= 1) {
        return true;
    }
    $min = min($arr);
    $max = max($arr);
    // 检查元素数量是否等于范围大小
    if (count($arr) !== $max - $min + 1) {
        return false;
    }
    // 检查是否所有元素都存在
    $expectedRange = range($min, $max);
    return count(array_diff($arr, $expectedRange)) === 0;
}

测试用例

// 测试升序连续
var_dump(isConsecutiveArray([1, 2, 3, 4])); // bool(true)
var_dump(isConsecutiveArray([1, 3, 4, 5])); // bool(false)
// 测试降序连续
var_dump(isConsecutiveArray([5, 4, 3, 2], 'desc')); // bool(true)
var_dump(isConsecutiveArray([5, 3, 2, 1], 'desc')); // bool(false)
// 测试允许重复
var_dump(isConsecutiveArray([1, 2, 2, 3], 'asc', true)); // bool(true)
var_dump(isConsecutiveArray([1, 2, 2, 3], 'asc', false)); // bool(false)
// 边界情况
var_dump(isConsecutiveArray([])); // bool(true)
var_dump(isConsecutiveArray([42])); // bool(true)
// 性能优化版本测试
var_dump(isConsecutiveArrayOptimized([10, 11, 12, 13])); // bool(true)
var_dump(isConsecutiveArrayOptimized([10, 12, 13, 14])); // bool(false)

扩展应用场景

字符串数组连续判断

/**
 * 判断字符串数组是否按字母顺序连续
 * @param array $arr 待判断数组
 * @return bool
 */
function isStringArrayConsecutive(array $arr): bool
{
    if (count($arr) <= 1) {
        return true;
    }
    sort($arr);
    for ($i = 1; $i < count($arr); $i++) {
        if (ord($arr[$i]) - ord($arr[$i - 1]) !== 1) {
            return false;
        }
    }
    return true;
}
// 测试
var_dump(isStringArrayConsecutive(['a', 'b', 'c'])); // bool(true)
var_dump(isStringArrayConsecutive(['a', 'c', 'd'])); // bool(false)

环形连续判断

/**
 * 判断数组是否环形连续(如[3,4,5,1,2])
 * @param array $arr 待判断数组
 * @return bool
 */
function isCircularConsecutive(array $arr): bool
{
    if (count($arr) <= 1) {
        return true;
    }
    $min = min($arr);
    $max = max($arr);
    // 检查是否是连续的整数范围
    if (count($arr) !== $max - $min + 1) {
        return false;
    }
    // 检查所有元素是否都存在
    $expectedRange = range($min, $max);
    if (count(array_diff($arr, $expectedRange)) > 0) {
        return false;
    }
    // 检查是否可以形成环形连续
    $sorted = $arr;
    sort($sorted);
    // 检查普通连续情况
    for ($i = 1; $i < count($sorted); $i++) {
        if ($sorted[$i] - $sorted[$i - 1] !== 1) {
            // 如果不是普通连续,检查是否是环形连续
            // 即第一个元素是max,最后一个元素是min
            return $sorted[0] === $min && $sorted[count($sorted) - 1] === $max;
        }
    }
    return true;
}
// 测试
var_dump(isCircularConsecutive([3, 4, 5, 1,

标签: #php判断 #数组连续