原题链接:https://leetcode.com/problems/shortest-distance-to-a-character/
1. 题目介绍
Given a string S and a character C, return an array of integers representing the shortest distance from the character C in the string.
给出一个字符串 S 和字符 C ,返回一个长度和字符串相同的数组。数组中第 i 个元素存储的是字符串的第 i 个字符到最近的 C 的距离。
Example 1:
Input: S = "loveleetcode", C = 'e'
Output: [3, 2, 1, 0, 1, 0, 0, 1, 2, 2, 1, 0]
Note:
S string length is in [1, 10000].
C is a single character, and guaranteed to be in string S.
All letters in S and C are lowercase.
字符串的长度范围是[1,10000]
C是一个单独的字符,并且保证在字符串S中存在
所有字母都是小写字母
2. 解题思路
首先这个题并不难做出来,一般的方法就是暴力搜索,不难想到。
但是如果要求时间复杂度为O(n),这就很难了。我没有想出来时间复杂度为O(n)的方法。看了题目的官方题解之后,我发现还真有时间复杂度为O(n)的方法。所以在这里就放弃我自己的方法,直接介绍题解的方法吧。
有兴趣的读者可以直接看题解原文: https://leetcode.com/problems/shortest-distance-to-a-character/solution/
整个过程需要两个循环。
第一遍循环,从左至右,为所有在C右边的字符确定距离。假设遇到的C的位置是nearC,那么C右边的字符到C的距离就是 i - nearC。
例如 Input: S = “loveleetcode”, C = ‘e’
第一遍循环后数组的值是
[ X, X, X, 0, 1, 0, 0, 1, 2, 3, 4, 0]
在这次循环中,只为在e右边的字符确定距离,而 l、o、v三个字符不在e的右边,所以不能确定他们的距离是多少,暂时用X代替,在实际的代码编写中用int类型的最大值替代。
第二遍循环,从右至左,为所有在C左边的字符确定距离。假设遇到的C的位置是nearC,那么C左边的字符到C的距离就是 nearC-i。在这一遍循环时,有些位置(比如后面的o、d)已经在上一次循环中计算出来了距离,需要取两者的最小值。
第二遍循环后数组的值是
[ 3, 2, 1, 0, 1, 0, 0, 1, 2, 2, 1, 0]
第二遍循环后的数组就是答案了。
class Solution {
public int[] shortestToChar(String S, char C) {
int length = S.length();
if (length == 0) {
return null;
}
int [] ans = new int [length];
int nearC = -1;
//第一遍循环,从左至右,为所有在C右边的字符确定距离
for (int i = 0 ; i < length ; i++ ) {
if (S.charAt(i) == C) {
nearC = i;
}
ans[i] = (nearC == -1 ? Integer.MAX_VALUE : i - nearC );
}
//第二遍循环,从右至左,为所有在C左边的字符确定距离。
nearC = Integer.MAX_VALUE;
for (int i = length-1 ; i >= 0 ; i-- ) {
if (S.charAt(i) == C) {
nearC = i;
}
ans[i] = Math.min(ans[i] , nearC-i);
}
return ans;
}
}
3. 参考资料
https://leetcode.com/problems/shortest-distance-to-a-character/solution/