大家好,我是 @负雪明烛。👈👈 点击关注,优质题解不间断。
题目大意
煎饼排序。这个排序方式很有意思,每次可以把前 k 个数字进行翻转,问翻转多少次之后可以达到有序状态。
就像一摞煎饼一样,每次能把铲子插入煎饼中的某个位置,然后把铲子之上的煎饼都翻转一下,问一系列位置能使结果是排序的。
图源:wikiwand
解题方法
模拟法
重要思路:我们把后面的数字先排好序,这样再翻转前面的时候就不会影响到后面。
所以,先把最大的数字放到最后,然后再把次大的位置放在倒数第二个位置……
如何把最大的数字放到最后呢?一个很简单的想法就是先把它翻转到第一个位置上去!
所以,思路很清晰了:
- 每次找到还没排序的数字之中最大的数字的位置,把这个位置之前的数字翻转,这一步使得最大数字去了最前面;
- 第二步,再次翻转,把最大位置翻到它应该在的位置上去。
这个题目一个比较好的地方是:给的数字是 $1~N$ 的全排列,所以我们每次要找哪个数字很容易确定,不需要 $O(N)$ 的遍历去判断最大的数字是谁。
这个题目不好的地方是:给的第一个例子不是按照常规的煎饼排序的思想列出来的,否则大家肯定很容易想出来解法。
另外需要提醒大家,代码的结果和题目的序列是不一样的,但是提交可以通过。
C++代码如下:
class Solution {
public:
vector<int> pancakeSort(vector<int>& A) {
vector<int> res;
const int N = A.size();
int pos, i;
for (pos = N; pos > 0; pos--) {
for (i = 0; A[i] != pos; i ++);
reverse(A.begin(), A.begin() + i + 1);
if (i != 0)
res.push_back(i + 1);
reverse(A.begin(), A.begin() + pos);
res.push_back(pos);
}
return res;
}
};
Python 代码:
class Solution(object):
def pancakeSort(self, A):
"""
:type A: List[int]
:rtype: List[int]
"""
N = len(A)
res = []
for x in range(N, 0, -1):
i = A.index(x)
res.extend([i + 1, x])
A = A[:i:-1] + A[:i]
return res
Java 代码:
class Solution {
public List<Integer> pancakeSort(int[] A) {
List<Integer> res = new ArrayList<>();
int N = A.length;
int pos, i;
for (pos = N; pos > 0; pos--) {
for (i = 0; A[i] != pos; i ++);
reverse(A,0, i );
if (i != 0)
res.add(i + 1);
reverse(A,0, pos - 1);
res.add(pos);
}
return res;
}
private void reverse(int[] A, int start, int end) {
while (start < end) {
int tmp = A[start];
A[start] = A[end];
A[end] = tmp;
start ++;
end --;
}
}
}
- 时间复杂度:$O(N ^ 2)$,其中 $N$ 是数组长度;
- 空间复杂度:$O(1)$。
总结
- 这就是冒泡排序的思想,学会基础理论知识,才能以不变应万变啊!
我是 @负雪明烛 ,刷算法题 1000 多道,写了 1000 多篇算法题解,收获阅读量 300 万。关注我,你将不会错过我的精彩动画题解、面试题分享、组队刷题活动,进入主页 @负雪明烛 右侧有刷题组织,从此刷题不再孤单。
- 在刷题的时候,如果你不知道该怎么刷题,可以看 LeetCode 应该怎么刷?
- 如果你觉得题目太多,想在短时间内快速提高,可以看 LeetCode 最经典的 100 道题。
- 送你一份刷题的代码模板:【LeetCode】代码模板,刷题必会