LC821.字符的最短距离
思路1:两次遍历
- 这是非常自然的思路
- 从左往右扫描,记录每一个数字到左侧最近目标数字的距离。
从右往左扫描,记录每一个数字到右侧最近目标数字的距离,同时和左边最近距离比较,取近的。
代码1:
class Solution {
public:
vector<int> shortestToChar(string s, char c) {
int ns = s.size();
vector<int> ans(ns, 0);
for (int i = 0; i < ns; ) {
int cnt = 0;
if (s[i] == c) {
i += 1;
while (i < ns && s[i] != c) {
cnt += 1;
ans[i] = cnt;
i += 1;
}
} else {
i += 1;
}
}
for (int i = ns - 1; i >= 0; ) {
int cnt = 0;
if (s[i] == c) {
i -= 1;
while (i >= 0 && s[i] != c) {
cnt += 1;
if (ans[i] == 0) {
ans[i] = cnt;
} else {
ans[i] = min(ans[i], cnt);
}
i -= 1;
}
} else {
i -= 1;
}
}
return ans;
}
};
思路2:BFS
vector<int> ans
记录各个位置到目标位置的最近距离- 所有目标字母的位置,全部进入队列(多个root)
- BFS遍历,将当前节点所记录位置
cur_pos
的左右两个位置next_pos
分别进行检验,符合条件就入队。 - 在入队的时候修改
ans[next_pos]
,ans[next_pos] = ans[cur_pos] + 1
如何避免重复?可以提前把
ans
中所有位置全部置-1
,然后在入队的时候,需满足两个条件next_pos
不能越界-
代码2:
class Solution { public: vector<int> shortestToChar(string s, char c) { queue<int> q; int ns = s.size(); vector<int> ans(ns, -1); // push root for (int i = 0; i < ns; i++) { if (s[i] == c) { q.push(i); ans[i] = 0; } } // bfs while (!q.empty()) { int cur_pos = q.front(); q.pop(); for (int i = 0; i < 2; i++) { int next_pos = 0; if (i == 0) { next_pos = cur_pos + 1; } else { next_pos = cur_pos - 1; } if (0 <= next_pos && next_pos < ns && ans[next_pos] == -1) { ans[next_pos] = ans[cur_pos] + 1; q.push(next_pos); } } } return ans; } };class Solution { public: vector<int> shortestToChar(string s, char c) { queue<int> q; int ns = s.size(); vector<int> ans(ns, -1); // push root for (int i = 0; i < ns; i++) { if (s[i] == c) { q.push(i); ans[i] = 0; } } // bfs while (!q.empty()) { int cur_pos = q.front(); q.pop(); for (int i = 0; i < 2; i++) { int next_pos = 0; if (i == 0) { next_pos = cur_pos + 1; } else { next_pos = cur_pos - 1; } if (0 <= next_pos && next_pos < ns && ans[next_pos] == -1) { ans[next_pos] = ans[cur_pos] + 1; q.push(next_pos); } } } return ans; } };