題目描述
題目傳送門
給定一個長度為 $n$ 的陣列 $a$,每次可以將最後一個元素移動到第一個,問:至少需要幾次操作,讓序列從小到大排好序,若無解輸出 $-1$。
演算法1
(暴力列舉)
不難想到,將最後一個元素拼接在第一個元素之前,就可以實現將鏈轉換成環,再依次遍歷在陣列 $a_i$ 中長度為 $n$ 的子串(可以想象成在陣列 $a$ 中有一個長度為 $n$ 會滑動的視窗),再檢驗是否滿足題目要求就可以了。
時間複雜度 $O(n^3)$
C++ 程式碼
請讀者自行實現
演算法2
經過我不斷摸索(看了一眼題解),發現將最後一個元素移到最前邊,實際上就是為了將滿足 $$a_{i-1} > a_i$$ 的兩個元素分離,成為合法的序列,但是如果有兩組以上這樣的元素,就無法滿足題目要求了。
時間複雜度 $O(n)$
C++ 程式碼
#include <iostream>
using namespace std;
const int N = 100010;
int n;
int a[N];
int main() {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
a[0] = a[n];
int cnt = 0, ans = -1;
for (int i = 0; i <= n; i++)
if (a[i-1] > a[i]) { // 統計逆序對
cnt++;
ans = n - i + 1;
}
ans %= n; // 如果ans > n,肯定也可以用ans % n來滿足題目要求
cout << (cnt > 1 ? -1 : ans) << endl;
return 0;
}