返回

LeetCode 探索(111):899-有序队列:打造字典序最小的字符串

前端

导言

在 LeetCode 的浩瀚题海中,899-有序队列是一个颇具挑战性的题目,它考验着我们的字符串操作功底。这道题要求我们从给定字符串的前 k 个字母中选择一个,并将其添加到字符串末尾,以此构建一个字典序最小的字符串。本文将循序渐进地分析解题思路,并结合代码示例,带你深入理解算法的精髓。

贪心算法的巧妙应用

解决有序队列问题的关键在于应用贪心算法。贪心算法是一种逐步做出最佳选择,以达到全局最优解的算法策略。在这道题中,我们每次从剩余的前 k 个字母中选择字典序最小的字母添加到字符串末尾。

算法步骤

  1. 将字符串的前 k 个字母排序。
  2. 依次从排序后的字母中选择字典序最小的字母,添加到字符串末尾。
  3. 重复步骤 2,直到前 k 个字母都添加完毕。

代码实现

def orderly_queue(s: str, k: int) -> str:
    """
    :param s: 给定字符串
    :param k: 可移动字母的数量
    :return: 字典序最小的字符串
    """
    n = len(s)
    if k == 0:
        return s
    s_sorted = sorted(s)
    result = ""
    for i in range(n):
        if s[i] == s_sorted[i]:
            continue
        index = s_sorted.index(s[i])
        if index >= k:
            result = s[i:] + s[:i]
        else:
            result = s_sorted[index] + result
    return result

代码解析

  • 判断 k 是否为 0,如果是,则无需移动字母,直接返回原始字符串。
  • 对字符串的前 k 个字母进行排序,存储在 s_sorted 中。
  • 遍历 s,如果 s[i] 等于 s_sorted[i],则表明当前字母已处于正确位置,继续遍历。
  • 如果 s[i] 不等于 s_sorted[i],则说明需要移动字母。计算字母在 s_sorted 中的位置 index。
  • 如果 index >= k,则表明当前字母需要移动到字符串末尾。否则,需要将当前字母移动到 s_sorted[index] 的前面。
  • 更新 result 为移动后的字符串。

实例

输入:
s = "cba"
k = 1

输出:
"acb"

解释:

  • 排序前 k 个字母:"abc"
  • 选择第一个字母 "a",将其添加到末尾,得到 "cab"。
  • 选择第二个字母 "b",将其添加到末尾,得到 "acb"。
    "acb" 是字典序最小的字符串。

结语

LeetCode 899-有序队列题目的精妙之处在于其贪心算法的应用。通过贪心地选择字典序最小的字母,我们可以逐步构造出字典序最小的字符串。掌握贪心算法的思想对于解决类似问题至关重要。此外,这道题还考验了我们的字符串操作能力,通过练习,我们可以不断提升自己的编程技能。