当前位置: 面试刷题>> 排列序号Ⅱ (经典算法题500道)


题目描述补充

题目:排列序号Ⅱ

给定一个字符串 s 和一个整数 k,其中 s 仅由小写英文字母组成,表示一个未完成的排列。我们需要在 s 的基础上,通过插入恰好 k 个未在 s 中出现过的最小字母(按字母顺序),使得结果字符串是一个完整的排列(即包含所有小写英文字母恰好一次)。返回所有可能的完整排列的第 k 个排列的字符串。

注意

  1. 输入的 s 不包含重复字符。
  2. k 的取值范围在 126 - s.length 之间(包括边界值)。
  3. 题目保证至少存在一个有效的完整排列,使得第 k 个排列存在。

示例

输入

  • s = "abc"
  • k = 3

输出

  • "ahfbcd"

解释

  • 未完成的排列 "abc" 缺少 d, e, f, g, ..., z 这些字母。
  • 插入这些字母后的所有可能排列中,第 3 个排列是 "ahfbcd"

PHP 示例代码

function getPermutation($s, $k) {
    $n = strlen($s);
    $remaining = 26 - $n; // 剩余需要插入的字母数量
    $total = 1; // 初始排列数

    // 计算在s的每个位置后插入新字母能形成的排列总数
    for ($i = 0; $i < $n; $i++) {
        $total *= ($remaining + 1 - $i);
    }

    // 确定第k个排列的起始位置
    $index = 0;
    while ($k > $total) {
        $k -= $total;
        $total /= ($remaining--);
        $index++;
    }

    // 构建第k个排列
    $result = '';
    $inserted = 0; // 已插入的字母数量
    for ($i = 0; $i < $n; $i++) {
        $curTotal = ($remaining - $inserted) * factorial($remaining - $inserted - 1);
        if ($k <= $curTotal) {
            $result .= $s[$i];
        } else {
            $k -= $curTotal;
            $result .= chr(ord('a') + $inserted);
            $inserted++;
        }
    }

    // 插入剩余的字母
    for ($i = ord('a'); $i <= ord('a') + $remaining - 1; $i++) {
        if ($inserted < $remaining) {
            $result .= chr($i);
            $inserted++;
        }
    }

    return $result;
}

function factorial($n) {
    $result = 1;
    for ($i = 2; $i <= $n; $i++) {
        $result *= $i;
    }
    return $result;
}

// 示例调用
echo getPermutation("abc", 3); // 输出 ahfbcd

注意:上述PHP代码是一个简化的版本,用于说明算法思路,并未完全优化性能(如计算阶乘和排列数时)。在真实面试中,可能需要更高效的算法或使用数据结构来优化性能。

码小课

码小课网站中有更多相关内容分享给大家学习,涵盖算法、数据结构、编程语言等多个方面,帮助大家提升编程能力和解决复杂问题的能力。

推荐面试题