821.字符的最短距离
https://leetcode-cn.com/problems/shortest-distance-to-a-character/
题目描述
解法 1:中心扩展法
思路
这是最符合直觉的思路,对每个字符分别进行如下处理:
从当前下标出发,分别向左、右两个方向去寻找目标字符
C。只在一个方向找到的话,直接计算字符距离。
两个方向都找到的话,取两个距离的最小值。

复杂度分析
时间复杂度:$O(N^2)$,N 为 S 的长度,两层循环。
空间复杂度:$O(1)$。
代码 (JS/C++)
JavaScript Code
C++ Code
解法 2:空间换时间
思路
空间换时间是编程中很常见的一种 trade-off (反过来,时间换空间也是)。
因为目标字符 C 在 S 中的位置是不变的,所以我们可以提前将 C 的所有下标记录在一个数组 cIndices 中。
然后遍历字符串 S 中的每个字符,到 cIndices 中找到距离当前位置最近的下标,计算距离。
复杂度分析
时间复杂度:$O(N*K)$,N 是 S 的长度,K 是字符
C在字符串中出现的次数,$K <= N$。空间复杂度:$O(K)$,K 为字符
C出现的次数,这是记录字符C出现下标的辅助数组消耗的空间。
代码 (JS/C++)
JavaScript Code
C++ Code
解法 3:贪心
思路
其实对于每个字符来说,它只关心离它最近的那个 C 字符,其他的它都不管。所以这里还可以用贪心的思路:
先
从左往右遍历字符串S,用一个数组 left 记录每个字符左侧出现的最后一个C字符的下标;再
从右往左遍历字符串S,用一个数组 right 记录每个字符右侧出现的最后一个C字符的下标;然后同时遍历这两个数组,计算距离最小值。
优化 1
再多想一步,其实第二个数组并不需要。因为对于左右两侧的 C 字符,我们也只关心其中距离更近的那一个,所以第二次遍历的时候可以看情况覆盖掉第一个数组的值:
字符左侧没有出现过
C字符i - left>right - i(i 为当前字符下标,left 为字符左侧最近的C下标,right 为字符右侧最近的C下标)
如果出现以上两种情况,就可以进行覆盖,最后再遍历一次数组计算距离。
优化 2
如果我们是直接记录 C 与当前字符的距离,而不是记录 C 的下标,还可以省掉最后一次遍历计算距离的过程。
复杂度分析
时间复杂度:$O(N)$,N 是 S 的长度。
空间复杂度:$O(1)$。
代码 (JS/C++/Python)
JavaScript Code
直接计算距离:
JavaScript Code
C++ Code
Python Code
解法 4:窗口
思路
把 C 看成分界线,将 S 划分成一个个窗口。然后对每个窗口进行遍历,分别计算每个字符到窗口边界的距离最小值。

复杂度分析
时间复杂度:$O(N)$,N 是 S 的长度。
空间复杂度:$O(1)$。
代码 (JS/C++/Python)
JavaScript Code
C++ Code
Python Code
Last updated
Was this helpful?