题目地址:
https://leetcode.com/problems/pancake-sorting/
给定一个长 n n n的数组 A A A,每次允许翻转其某个前缀,要求仅仅用这个操作将 A A A从小到大排序,返回每次翻转的前缀长度。要求操作次数小于等于 10 n 10n 10n。
可以从后向前遍历,遍历到某个位置 i i i的时候,就将 A [ 0 : i ] A[0:i] A[0:i]中的最大值调整到 A [ i ] A[i] A[i]处,调整方法是,先将最大值为右端点的前缀翻转,这样最大值就成为了 A [ 0 ] A[0] A[0],然后再将最大值翻转到 A [ i ] A[i] A[i]。每次翻转两次,所以总次数小于等于 2 n 2n 2n。代码如下:
import java.util.ArrayList;
import java.util.List;
public class Solution {
public List<Integer> pancakeSort(int[] arr) {
int n = arr.length;
List<Integer> res = new ArrayList<>();
for (int i = n - 1; i > 0; i--) {
// 找A[0:i]的最大值
int pos = 0;
for (int j = 0; j <= i; j++) {
if (arr[j] > arr[pos]) {
pos = j;
}
}
// 如果最大值已经就位了,则不需要翻转
if (pos == i) {
continue;
}
// 否则翻转两次
reverse(arr, 0, pos);
res.add(pos + 1);
reverse(arr, 0, i);
res.add(i + 1);
}
return res;
}
void reverse(int[] A, int l, int r) {
for (; l < r; l++, r--) {
int tmp = A[l];
A[l] = A[r];
A[r] = tmp;
}
}
}
时间复杂度 O ( n 2 ) O(n^2) O(n2),空间 O ( 1 ) O(1) O(1)。
C++:
class Solution {
public:
vector<int> pancakeSort(vector<int>& A) {
int n = A.size();
vector<int> res;
for (int i = n - 1; i; i--) {
int pos = i;
for (int j = 0; j < i; j++)
if (A[j] > A[pos]) pos = j;
if (pos == i) continue;
reverse(A.begin(), A.begin() + pos + 1);
res.push_back(pos + 1);
reverse(A.begin(), A.begin() + i + 1);
res.push_back(i + 1);
}
return res;
}
};
时空复杂度一样。