例题1: 给你一个整数数组 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 范围内的有效答案都将被判断为正确。(力扣:969)
// 煎饼排序:这个名字帧的很生动形象了,关键是这个饼得怎么翻?我也不会可是评论区的大神会
// 我偷师了下面说说大致思路:就例如[3,2,4,1]
// 我们可以先找到4所在的位置,然后包裹其在内的数字进行反转,即k=3:[4,2,3,1]
// 然后因为这是第一次反转,所以将整个数组进行一次整体的反转,这样最大的4就到后面去了:k=4:[1,3,2,4]
// 同样找3,反转到最前面:k=2:[3,1,2,4] ,然后将未排序的数字进行一次反转,这样3又到后面去了:k=3:[2,1,3,4]
// 于此类推这样所有大的数都可以通过两次反转到后面的位置
class Solution {
// 将要反转的数组转化为全局变量
int[] arr;
public List<Integer> pancakeSort(int[] arr) {
this.arr=arr;
// 创建一个集合来保存每次反转的位置
List<Integer> result=new ArrayList<>();
// 使用循环获取目前数组中最大的致的位置
// 最外层循环是控制反转的次数,最后一个元素不需要反转
for(int i=0;i<arr.length-1;i++){
// 创建一个变量记录本次反转的最大值,并记录下其索引
int max=Integer.MIN_VALUE;
int maxindex=-1;
// 这层循环时在未排序的元素中找到最大的yuans
for(int j=0;j<arr.length-i;j++){
if(arr[j]>max){
max=arr[j];
maxindex=j;
}
}
// 找到未排序中的元素后准备将其反转,如果它已经时未排序中的最后一个元素就为u序反转
if(maxindex==arr.length-1-i){
continue;
}else{
// 先将其反转到最前面
// 如果它已经在最前面就直接将反转到最后即可
if(maxindex==0){
// 将其反转到未排序元素中的最后
result.add(arr.length-i);
reverse(arr.length-i);
}else{
result.add(maxindex+1);
reverse(maxindex+1);
// 将其反转到未排序元素中的最后
result.add(arr.length-i);
reverse(arr.length-i);
}
}
}
return result;
}
// 先来实现一个反转函数的方法:获取一个整数k,将数组中 0-k-1 的子数组进行反转
public void reverse(int k){
// 这里的反转我打算使用双指针
int lp=0;
int rp=k-1;
while(lp<rp){
int temp=arr[lp];
arr[lp]=arr[rp];
arr[rp]=temp;
lp++;
rp--;
}
}
}