LeetCode 969 pancake sorting 煎饼排序

版权声明:转载请注明原址,有错误欢迎指出 https://blog.csdn.net/iwts_24/article/details/86216774

题目链接

LeetCode 周赛 118 场 B题

https://leetcode-cn.com/problems/pancake-sorting/

题意

        先说明所谓的煎饼翻转,例如数组[1,2,3,4]其煎饼翻转后就是[4,3,2,1],就是从后到前翻转过去而已。现在给出一个排序,例如[3,2,4,1],在只能选择煎饼翻转的情况下,需要将其排序成为[1,2,3,4]。煎饼排序的时候,一定是从第一个数开始,但是有一个终止数,例如对3排序,那么就只对数组的前3个元素进行煎饼翻转,那么[3,2,4,1]就变成[4,2,3,1]。要求在有限次数内通过煎饼翻转来完成排序的功能。

        如果还是不太懂可以研究一下题目给出的例子:对于[3,2,4,1]想要还原成为[1,2,3,4]那么翻转的步骤为:

第一次翻转为4:[1,4,2,3]

第二次翻转为2:[4,1,2,3]

第三次翻转为4:[3,2,1,4]

第四次翻转为3:[1,2,3,4]

排序完成。那么答案应该输出这个翻转顺序,即:[4,2,4,3]

        值得注意的是,例如数组的长度为4,那么数组元素一定为1-4这4个数,初始顺序为其中一个排序。自然可能出现一开始就是正确排序,次数输出空。有次数限制,为10*A.length。

题解

        是否能够找到一种规律?能够进行一定次数的重复操作使得变成一种确定的排序顺序?博主想的是这样,因为题目也说明了,K长度的数组其元素一定为1-K。那么正确的升序排序使得第i个元素所在下标一定为i-1。那么这就是一个确定的位置。博主想是否可以对数组进行遍历,当碰见i元素,但是i不在i-1的位置上的时候,通过煎饼翻转将其翻转到正确位置上。

        那么对于题目例子[3,2,4,1],例如3,正确位置应该是下标2,实际位置为0,那么只需要对3进行翻转即可,即:[4,2,3,1]。同样,对于4而言,实际下标为2,正确下标为3,这样的,可以先对下标进行反转,即先反转3得到:[4,2,3,1],然后再翻转4归位:[1,3,2,4]。这样可以找到规律:

1.若i元素下标为i-1,位置正确。

2.若i元素下标为0,进行煎饼翻转,k=i

3.若i元素下标m不满足条件1与条件2,进行煎饼翻转2次,k=m+1,k=i

这样就能保证对于任何一个元素,最少0次,最多2次能够到达确定的位置上。题目给出的限制是最多移动10*A.length次,但是利用这个规律,最大移动次数为2*A.length。

        但是直接遍历是不正确的。因为这样可能会出现这样的情况,先翻转3的时候,3归位了,但是翻转4的时候有可能打乱3的顺序。所以不能通过O(n)的想法直接遍历。博主选择双重for循环,从后往前搜索,先找最大的,最大的归位以后,就绝对不可能再被移动了,因为k的值只能为m+1或者i,在最大的数已经确定为p的情况下一定有:m+1 < p、i < p。这样就保证顺序不会被打破。

        博主将煎饼排序专门写进方法里面,这样给出一个k,就能直接完成排序。煎饼排序实际上非常简单,双指针遍历也可以,头尾调换位置,直到指针相遇。

        不过这样好像挺慢的。。。比赛时跑了19ms,后来发现速度仅仅是前80%。应该有更好的算法吧。

Java 代码

class Solution {
    public static int[] A;
    
    public static void reverse(int index){
        int i = 0;
        for(;index > i;i++,index--){
            int temp = A[i];
            A[i] = A[index];
            A[index] = temp;
        }
    }
    
    public List<Integer> pancakeSort(int[] As) {
        List<Integer> ans = new ArrayList<>();
        A = As;
        int len = A.length;
        for(int i = len;i > 0;i--){
            for(int j = 0;j < len-1;j++){
                int num = A[j];
                if(i != A[j]) continue;
                if(i-1 == j) break;
                if(j == 0){
                    reverse(i-1);
                    ans.add(i);
                    break;
                }
                reverse(j);
                ans.add(j+1);
                reverse(i-1);
                ans.add(i);
            }
        }
        return ans;
    }
}

猜你喜欢

转载自blog.csdn.net/iwts_24/article/details/86216774