本文共 2048 字,大约阅读时间需要 6 分钟。
为了找到字符串中的最小长度为n的子串,可以采用以下贪心算法:
预处理最小值数组:首先,预处理一个数组min_right,其中min_right[i]表示从位置i到字符串末尾的最小字符。
遍历字符串:从左到右遍历字符串,使用两个指针left和right,维护一个窗口,确保窗口长度为n。
滑动窗口:在滑动窗口中找到最小的字符,并记录该字符的位置。然后,移动左指针以缩小窗口,继续寻找更小的子串。
记录最小子串:在每次找到更小的子串时,更新结果字符串。
以下是具体实现步骤:
min_right数组:从右到左遍历字符串,记录每个位置的最小字符。left和right指针,result字符串,和最小值位置min_pos。right指针,直到窗口长度等于n。k。min_pos为当前窗口的最小字符位置。left可以移动时,向右移动left,并重复上述步骤。以下是具体代码实现:
#include#include using namespace std;string findMinimalString(string s, int n) { int m = s.size(); vector min_right(m, ' '); // 预处理 min_right数组 for (int i = m - 1; i >= 0; --i) { if (i == m - 1) { min_right[i] = s[i]; } else { min_right[i] = min(s[i], min_right[i + 1]); } } string result; int left = 0, right = 0; int min_pos = 0; while (right < m) { // 扩展右指针,直到窗口长度 >= n while (right - left + 1 < n && right < m) { right++; } // 在窗口[left, right]中找到最小字符 int current_min = min_right[left]; int current_min_pos = left; for (int i = left; i <= right; ++i) { if (s[i] < current_min) { current_min = s[i]; current_min_pos = i; } } // 更新最小位置 if (current_min_pos > min_pos) { min_pos = current_min_pos; } // 尝试移动左指针 if (left <= min_pos && min_pos - left + 1 <= n) { left = min_pos + 1; } } // 构建结果字符串 for (int i = 0; i < n; ++i) { result += s[min_pos - i]; } return result;}int main() { int n; string s; // 读取输入 n = 10; s = "asdfasdfas"; string result = findMinimalString(s, n); cout << result << endl; return 0;}
代码解释:
预处理min_right数组:从右到左遍历字符串,记录每个位置的最小字符。这一步的时间复杂度为O(m),其中m是字符串的长度。
滑动窗口:使用两个指针left和right,确保窗口长度为n。在每次扩展窗口时,找到当前窗口内的最小字符及其位置。
更新最小位置:记录当前窗口内的最小字符位置,确保在后续步骤中能够正确构建结果字符串。
构建结果字符串:根据记录的最小位置,构建长度为n的最小子串。
该算法的时间复杂度为O(m),适用于大数据量的处理。
转载地址:http://hxhfk.baihongyu.com/