题目链接
思路一:双指针
分析:
如果里面只有一个和c相同的字符。那么很好处理,只要计算和这个字符的距离即可。
如果里面有两个或两个以上。
将第一个的下标记为p1,第二个的下标记为p2。
当i<=p1的时候,最近的距离肯定是p1-i。
当i>p1 && i<= (p1+p2)/2,最近的距离是res[i] = i-p1;
当i>(p1+p2)/2,最近的距离是res[i]=p2-i;
此时要更新两个指针。
p2=p1
p2更新为下一个与c相同的字符。
代码:
class Solution {
public int[] shortestToChar(String s, char c) {
int[] res = new int[s.length()];
int p1=0;
while(s.charAt(p1)!=c){
p1++;
}
int p2 = p1+1;
while(p2<s.length() && s.charAt(p2)!=c){
p2++;
}
for(int i=0; i<s.length(); i++){
if(p2==s.length()){
if(i<=p1){
res[i] = p1-i;
}else{
res[i] = i-p1;
}
continue;
}
if(i<=p1){
res[i]=p1-i;
}else if(i>p1 && i<= (p1+p2)/2){
res[i] = i-p1;
}else if(i>(p1+p2)/2){
res[i]=p2-i;
p1=p2;
p2++;
while(p2<s.length() && s.charAt(p2)!=c){
p2++;
}
}
}
return res;
}
}
思路二:两次遍历
分析:这个问题可以拆分为对于每个字符,求:
- 左边最近的字符c的距离
- 右边最近的字符c的距离
这两者的最小值。
对于问题一,可以从左往右遍历s,若当前字符等于c,那么更新idx为当前下标。遍历的同时更新res[i]=i-idx;
对于问题二,可以从右往左遍历,若当前字符等于c,那么更新idx为当前下标。
遍历的同时更新res[i]=Math.min(res[i,idx-i).
因为最开始idx是不存在的,所以可以用-n或2n来表示。
代码:
class Solution {
public int[] shortestToChar(String s, char c) {
int n = s.length();
int[] ans = new int[n];
for (int i = 0, idx = -n; i < n; ++i) {
if (s.charAt(i) == c) {
idx = i;
}
ans[i] = i - idx;
}
for (int i = n - 1, idx = 2 * n; i >= 0; --i) {
if (s.charAt(i) == c) {
idx = i;
}
ans[i] = Math.min(ans[i], idx - i);
}
return ans;
}
}