给你一个整数数组 arr ,请使用 煎饼翻转 完成对数组的排序。
一次煎饼翻转的执行过程如下:
选择一个整数 k ,1 <= k <= arr.length
反转子数组 arr[0...k-1](下标从 0 开始)
例如,arr = [3,2,1,4] ,选择 k = 3 进行一次煎饼翻转,反转子数组 [3,2,1] ,得到 arr = [1,2,3,4] 。
以数组形式返回能使 arr 有序的煎饼翻转操作所对应的 k 值序列。任何将数组排序且翻转次数在 10 * arr.length 范围内的有效答案都将被判断为正确。
来源:力扣(LeetCode)
class Solution {
public List<Integer> pancakeSort(int[] arr) {
int len = arr.length;
List<Integer> result = new ArrayList<>();
if (len < 2) return result;
// 根据题目给定范围,数组元素的值是在1 到 len 之间的
// 所以可以用另外一个数组记录每个元素所在的位置,下标为元素,值为元素所在原数组的位置
int[] record = new int[len + 1];
for (int i= 0; i < len; i++){
record[arr[i]] = i;
}
// 这样record数组下标也就是有序的了,我们先从最大的元素开始,一个个的调整到合适的位置
for (int i = len; i >= 1; i--){
// 如果当前最大元素的在合适的位置,就不做处理,直接操作下一个
if (i == record[i] + 1) continue;
int curPosition = record[i]; // 当前最大元素所在位置
// 每个元素需继续两步翻转:
// 第一步:翻转到0位置;
// 第二步:再翻转到当前最后的位置(i - 1)
// 首先看是否在0的位置,是的话省去第一步
if (curPosition == 0){
result.add(i);
swap(arr, record, 0, i - 1);
}else {
// 第一步:翻转到0位置
result.add(record[i] + 1);
swap(arr, record, 0, record[i]);
i++; // 加回去,下次遍历再来,走第二步
}
}
return result;
}
private void swap(int[] arr, int[] record, int left, int right){
while (left < right){
record[arr[left]] = right; // 更新位置记录
record[arr[right]] = left;
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
}
}