# 121. 小红的区间翻转 比较暴力的方式,就是直接模拟, 枚举所有 区间,然后检查其翻转的情况。 在检查翻转的时候,需要一些代码优化,否则容易超时。 ```CPP #include #include using namespace std; bool canTransform(const vector& a, const vector& b, int left, int right) { // 提前检查翻转区间的值是否可以匹配 for (int i = left, j = right; i <= right; i++, j--) { if (a[i] != b[j]) { return false; } } // 检查翻转区间外的值是否匹配 for (int i = 0; i < left; i++) { if (a[i] != b[i]) { return false; } } for (int i = right + 1; i < a.size(); i++) { if (a[i] != b[i]) { return false; } } return true; } int main() { int n; cin >> n; vector a(n); vector b(n); for (int i = 0; i < n; i++) { cin >> a[i]; } for (int i = 0; i < n; i++) { cin >> b[i]; } int count = 0; // 遍历所有可能的区间 for (int left = 0; left < n; left++) { for (int right = left; right < n; right++) { // 检查翻转区间 [left, right] 后,a 是否可以变成 b if (canTransform(a, b, left, right)) { count++; } } } cout << count << endl; return 0; } ``` 也可以事先计算好,最长公共前缀,和最长公共后缀。 在公共前缀和公共后缀之间的部分进行翻转操作,这样我们可以减少很多不必要的翻转尝试。 通过在公共前缀和后缀之间的部分,找到可以通过翻转使得 a 和 b 相等的区间。 以下 为评论区 卡码网用户:码鬼的C++代码 ```CPP #include #include using namespace std; int main() { int n; cin >> n; vector a(n), b(n); for (int i = 0; i < n; i++) { cin >> a[i]; } for (int i = 0; i < n; i++) { cin >> b[i]; } vector prefix(n, 0), suffix(n, 0); // 计算前缀相等的位置 int p = 0; while (p < n && a[p] == b[p]) { prefix[p] = 1; p++; } // 计算后缀相等的位置 int s = n - 1; while (s >= 0 && a[s] == b[s]) { suffix[s] = 1; s--; } int count = 0; // 遍历所有可能的区间 for (int i = 0; i < n - 1; i++) { for (int j = i + 1; j < n; j++) { // 判断前缀和后缀是否相等 if ((i == 0 || prefix[i - 1] == 1) && (j == n - 1 || suffix[j + 1] == 1)) { // 判断翻转后的子数组是否和目标数组相同 bool is_palindrome = true; for (int k = 0; k <= (j - i) / 2; k++) { if (a[i + k] != b[j - k]) { is_palindrome = false; break; } } if (is_palindrome) { count++; } } } } cout << count << endl; return 0; } ```