返回

821. 字符的最短距离 | 算法入门

前端

迎难而上:解锁 LeetCode 821 难题

挑战即机遇

大千世界,芸芸众生,每个人都难免遭遇困境。面对逆境,有些人选择逃避,而更多人选择迎难而上。在迎难而上的征程中,"刷题打卡"无疑是解决难题的捷径。今天,让我们一起探索 LeetCode 821 题,深入理解迎难而上和解决问题的真谛。

破解 LeetCode 821

LeetCode 821 题的目的是求一个字符串中给定目标字符的最短距离。乍一看,这道题并不复杂,但深入分析后你会发现,仅遍历一次是无法解决问题的。因为,从左到右遍历只能算出当前字符到左侧目标字符的距离,却无法比较取最小值。

因此,本题的解题思路是先正向遍历一次,再反向遍历一次。正向遍历时,我们记录每个字符距离左侧最近的目标字符的距离;反向遍历时,我们记录每个字符距离右侧最近的目标字符的距离。最后,取两次遍历得到的距离的最小值,就是每个字符到目标字符的最短距离。

具体步骤

  1. 正向遍历: 从左到右遍历字符串,记录每个字符距离左侧最近的目标字符的距离。
  2. 反向遍历: 从右到左遍历字符串,记录每个字符距离右侧最近的目标字符的距离。
  3. 取最小值: 对于每个字符,取正向遍历和反向遍历得到的距离的最小值,即为该字符到目标字符的最短距离。

代码示例

def shortestDistance(s: str, c: str) -> List[int]:
  n = len(s)
  # 正向遍历
  left = [-1] * n
  for i in range(n):
    if s[i] == c:
      left[i] = i
    elif i > 0:
      left[i] = left[i - 1]
  # 反向遍历
  right = [-1] * n
  for i in range(n - 1, -1, -1):
    if s[i] == c:
      right[i] = i
    elif i < n - 1:
      right[i] = right[i + 1]
  # 取最小值
  result = []
  for i in range(n):
    if left[i] == -1:
      result.append(right[i])
    elif right[i] == -1:
      result.append(left[i])
    else:
      result.append(min(left[i], right[i]))
  return result

总结

通过对 LeetCode 821 题的分析和解决,我们再次领悟到:面对困难,迎难而上是解决问题的最佳途径。同时,我们也掌握了求字符串中给定目标字符的最短距离的算法。希望大家都能从这道题中有所收获,并在今后的刷题和工作中不断提升自己,成为一名优秀的程序员。

常见问题解答

  1. 为什么要先正向遍历,再反向遍历?
    因为只遍历一次无法得到每个字符到左侧和右侧目标字符的最小距离。正向遍历得到左侧距离,反向遍历得到右侧距离,才能比较取最小值。

  2. 如何处理目标字符不在字符串中的情况?
    如果是正向遍历,则该字符到左侧目标字符的距离为正无穷;如果是反向遍历,则该字符到右侧目标字符的距离为正无穷。

  3. 如何优化算法时间复杂度?
    时间复杂度为 O(n),无法进一步优化。

  4. 如何处理目标字符在字符串中重复出现的情况?
    可以将目标字符出现的索引保存在一个列表中,遍历时直接取最小的索引。

  5. 如何解决 LeetCode 上的 LeetCode 821 题?
    可以直接提交本文提供的代码,或者根据本文的思路自己实现算法。