1. 题目
给你一个字符串
s
和一个字符c
,且c
是s
中出现过的字符。返回一个整数数组
answer
,其中answer.length == s.length
且answer[i]
是s
中从下标i
到离它 最近 的字符c
的 距离 。两个下标
i
和j
之间的 距离 为abs(i - j)
,其中abs
是绝对值函数。
2. 示例
3. 分析
我们先尝试一下暴力解法:将目标字符每次出现的位置保存到数组中,然后遍历字符串依次比较每个字符与目标字符每次出现的位置进行比较,寻找较小值即可。
class Solution {
public:
vector<int> shortestToChar(string s, char c) {
vector<int> index;
vector<int> ans;
int n = s.size();
// 记录目标字符出现的位置
for(int i = 0; i < n; i++)
{
if(s[i] == c)
{
index.push_back(i);
}
}
// 遍历字符串,对每个字符与目标字符出现下标进行比较,寻找较小值
for(int i = 0; i < n; i++)
{
int minres = INT_MAX;
for(int j = 0; j < index.size(); j++)
{
minres = min(minres, abs(index[j]-i));
}
ans.push_back(minres);
}
return ans;
}
};
时间复杂度:O(N2)
能不能做到 O(N),可以的:
问题可以转换成,对 每个字符s[i] 的下标 i,求
- 每个字符s[i]到其左侧最近的字符 c 的距离。
- 每个字符s[i]到其右侧最近的字符 c 的距离。
这两者的较小值。
分别对字符串从左往右、从右往左遍历。
从左往右:在遍历的同时记录二者的距离,也需更新目标字符的下标。但在刚开始遍历时,目标字符可能不存在,所以二者距离也因此不能记录,所以为了记录二者的距离,我们可以使用 -n 初始化目标字符下标,这里 n 是 字符串的长度,距离就为 abs(index - i)。若找到第一个目标字符,二者距离也为 abs(index - i)。
从右往左:同理。初始化目标字符下标为 2n,这里 n 是 字符串的长度。顺便比较此时二者距离与从左往右遍历时二者距离哪个为较小者。
class Solution {
public:
vector<int> shortestToChar(string s, char c) {
int n = s.size();
vector<int> ans(n);
// 从左往右
for(int i = 0, index = -n; i < n; i++)
{
if(s[i] == c) index = i;
ans[i] = i - index;
}
// 从右往左
for(int i = n - 1, index = 2*n; i >= 0; i--)
{
if(s[i] == c) index = i;
ans[i] = min(ans[i], index - i);
}
return ans;
}
};