969. 煎饼排序题解
题目来源:[969. 煎饼排序](https://leetcode-cn.com/problems/find-center-of-star-graph/)
2022.02.19 每日一题
每日一题专栏地址:LeetCode 每日一题题解更新中❤️💕
今天的题目刚看到,有点懵,满脑子都是煎饼怎么吃。😂😂
好啦,回到正题上,一起来想想这道题怎么做。
本题目的意思是选择一个整数 k ,将下标范围 [0,k - 1] 的部分翻转,最后得到排序好的数组
这个方式我觉得稍微有一点点熟悉,感觉和冒泡算法
有点相似冒泡排序图解,同理我们也可以用同样的逻辑来完成这道题目。
冒泡排序最重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。先确定位置的是最大值,因为这个算法越小的元素会经由交换慢慢"浮"到数列的顶端。
同理,我们代换一下,在煎饼排序之中,我们是不是可以找到前 k 项未排序部分的最大值,将其放在第 0 位,然后将前 k 项统一翻转
拿示例来举个例子
// 前四项最大的值是 4 ,将 4 翻转至索引为 0 的位置,在整体翻转,使 4 到达前四项的最后
原数组:[3,2,4,1]
第一次翻转(k = 3) 翻转后:[4,2,3,1]
// 前三项最大的值是 3 ,将 3 翻转至索引为 0 的位置,在整体翻转,使 3 到达前三项的最后
第二次翻转(k = 4) 翻转后:[1,3,2,4]
第一次翻转(k = 2) 翻转后:[3,1,2,4]
// 前两项最大的值是 2 ,将 2 翻转至索引为 0 的位置,在整体翻转,使 2 到达前两项的最后
第一次翻转(k = 3) 翻转后:[2,1,3,4]
第一次翻转(k = 2) 翻转后:[1,2,3,4]
具体的代码以及注释如下:
class Solution {
public:
vector<int> pancakeSort(vector<int> &arr) {
// 创建结果数组
vector<int> res;
// 我们是从后向前进行查找,每次寻找前 i 项中的最大值
// 然后翻转,使最大项放在数组首端,再进行整体翻转
for (int i = arr.size(); i > 1; i--) {
// 寻找前 k 项的最大值的索引
int index = findIndex(arr, i);
// 如果索引所在位置已经是前 i 项的末尾,则不需要进行整体反转的操作
if (index == i - 1)
continue;
// 如果索引所在位置不是前 i 项的末尾,则将前 i 项的最大值翻转到首位
reverse(arr.begin(), arr.begin() + index + 1);
// 并在结果数组中添加本次的翻转结果
res.push_back(index + 1);
// 整体翻转前 i 项,将首位放置在对应的位置
reverse(arr.begin(), arr.begin() + i);
// 并将结果添加进数组之中
res.push_back(i);
}
return res;
}
// 找到数组 arr 中,前 k 项中的最大值的索引
inline int findIndex(vector<int> &arr, int k) {
int index = 0;
for (int i = 1; i < k; i++)
if (arr[index] <= arr[i])
index = i;
return index;
}
};
class Solution {
public List<Integer> pancakeSort(int[] arr) {
// 创建结果数组
List<Integer> res = new ArrayList<Integer>();
// 我们是从后向前进行查找,每次寻找前 i 项中的最大值
// 然后翻转,使最大项放在数组首端,再进行整体翻转
for (int i = arr.length; i > 1; i--) {
// 寻找前 k 项的最大值的索引
int index = findIndex(arr, i);
// 如果索引所在位置已经是前 i 项的末尾,则不需要进行整体反转的操作
if (index == i - 1) continue;
// 如果索引所在位置不是前 i 项的末尾,则将前 i 项的最大值翻转到首位
reverse(arr, index + 1);
// 并在结果数组中添加本次的翻转结果
res.add(index + 1);
// 整体翻转前 i 项,将首位放置在对应的位置
reverse(arr, i);
// 并将结果添加进数组之中
res.add(i);
}
return res;
}
// 找到数组 arr 中,前 k 项中的最大值的索引
public int findIndex(int[] arr, int k) {
int index = 0;
for (int i = 1; i < k; i++)
if (arr[index] <= arr[i]) index = i;
return index;
}
// 将数组下标范围 [0,index) 的部分进行翻转
public void reverse(int[] arr, int index) {
int i = 0, j = index - 1;
while (i <= j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
}