题目来源
题目描述
题目解析
模拟
class Solution {
public:
string restoreString(string s, vector<int>& indices) {
int length = s.length();
string result(length, 0);
for(int i = 0; i < length; i++) {
result[indices[i]] = s[i];
}
return result;
}
};
原地修改
直观的想法是:对于下标i
,需要把字符s[i]
移动到indices[i]
的位置上;然后,我们前进到位置indices[i]
,并将字符s[indices[i]]
移到indices[indices[i]]
的位置上。类似的过程以此类推,直到最终回到起点 i。此时,封闭路径i->indices[i]->indices[indices[i]]->...->i
上的所有字符,都已经被设置成正确的值。
我们只要找到indices[i]
中所有这样的封闭路径,并进行对应的移动操作,就能够得到最终的答案。
问题是:
- 当在第二步试图把字符
s[indices[i]]
移到indices[indices[i]]
的位置上时,会发现字符s[indices[i]]
已经在第一步被覆写了。因此,在每一步移动前,需要先额外记录目标位置处字符的原有值。 - 另一个隐含的问题是如何避免处理重复的封闭路径。为了解决此问题,我们每处理一个封闭路径,就将该路径上的 indices数组的值设置成下标自身。这样,当某个封闭路径被处理完毕后,扫描到该路径的另一个下标时,就不会处理该封闭路径了。
class Solution {
public:
string restoreString(string s, vector<int>& indices) {
int length = s.length();
for (int i = 0; i < length; i++) {
if (indices[i] != i) {
char ch = s[i]; // 当前需要被移动的字符
int idx = indices[i]; // 该字符需要被移动的目标位置
while (idx != i) {
swap(s[idx], ch); // 使用 swap 函数,在覆写 s[idx] 之前,先将其原始值赋给变量 ch
swap(indices[idx], idx); // 将封闭路径中的 indices 数组的值设置成下标自身
}
// 此时 idx = i
// 退出循环后,还要再覆写起点处的字符
s[i] = ch;
indices[i] = i;
}
}
return s;
}
};