LeetCode 969. 煎饼排序题解

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--;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值