忠 ju

导航

 
  • Difficulty: Medium

Problem

Given an array A, we can perform a pancake flip: We choose some positive integer k <= A.length, then reverse the order of the first k elements of A. We want to perform zero or more pancake flips (doing them one after another in succession) to sort the array A.

Return the k-values corresponding to a sequence of pancake flips that sort A. Any valid answer that sorts the array within 10 * A.length flips will be judged as correct.

Example 1:

Input: [3, 2, 4, 1]
Output: [4, 2, 4, 3]
Explanation:
We perform 4 pancake flips, with k values 4, 2, 4, and 3.
Starting state: A = [3, 2, 4, 1]
After 1st flip (k=4): A = [1, 4, 2, 3]
After 2nd flip (k=2): A = [4, 1, 2, 3]
After 3rd flip (k=4): A = [3, 2, 1, 4]
After 4th flip (k=3): A = [1, 2, 3, 4], which is sorted.

Example 2:

Input: [1, 2, 3]
Output: []
Explanation: The input is already sorted, so there is no need to flip anything.
Note that other answers such as [3, 3], would also be accepted.

Note:

  1. 1 <= A.length <= 100
  2. A[i] is a permutation of [1, 2, ..., A.length]

Array, Sort

Solution

题目大意是给一个数组,用翻转数组前 N 项的方式对其进行排序。由于是翻转前 N 项,所以可以让数组中最大的数通过此法先放到数组末尾,从后往前完成排序。又由于题目指出了给出的数组一定是从 1 到 N 的全排列,因此可以简单地定最大值 maxA.length,每排出一个让 max--,当 max == 1 时停止操作。代码如下:

public class Solution
{
    public IList<int> PancakeSort(int[] A)
    {
        int max = A.Length;
        List<int> ret = new List<int>();
        while(max != 1)
        {
            int i = Array.IndexOf(A, max);
            if(i == max - 1)
            {
                // 情况一:max 已经有序,直接进行下一个循环
                max--;
                continue;
            }
            else if(i == 0)
            {
                // 情况二:max 为数组的首个元素,进行一次前 max 个元素翻转
                ret.Add(max);
                ArrayReverse(A, max);
            }
            else
            {
                // 其余情况:进行两步操作,第一步将其放到数组首位,第二步归位
                ret.Add(i + 1);
                ret.Add(max);
                ArrayReverse(A, i + 1);
                ArrayReverse(A, max);
            }
            max--;
        }
        return ret;
    }

    static void ArrayReverse<T>(T[] arr, int len)
    {
        int left = 0, right = len - 1;
        while (left < right)
        {
            T temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
            left++;
            right--;
        }
    }
}

当然,题目只是要求找到一组可行解即可(而且翻转次数不超过 10 倍的数组长度),这个条件是比较宽泛的,题解做法可以保证一定能解出来,且翻转次数应该是小于 2 倍数组长度(没有验证,如有错误还请指出)。若是题目改成使用最少的翻转次数完成排序,则题目就变成了所谓的“烙饼问题”,这篇文章对这个问题给出了相应的解答。

posted on 2019-02-14 23:17  忠ju  阅读(119)  评论(1编辑  收藏  举报