力扣刷题——969. 煎饼排序(详细解释、解题思路以及代码)



969. 煎饼排序

已解答

中等

相关标签

相关企业

给你一个整数数组 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 范围内的有效答案都将被判断为正确。

示例 1:

输入:[3,2,4,1]
输出:[4,2,4,3]
解释:
我们执行 4 次煎饼翻转,k 值分别为 4,2,4,和 3。
初始状态 arr = [3, 2, 4, 1]
第一次翻转后(k = 4):arr = [1, 4, 2, 3]
第二次翻转后(k = 2):arr = [4, 1, 2, 3]
第三次翻转后(k = 4):arr = [3, 2, 1, 4]
第四次翻转后(k = 3):arr = [1, 2, 3, 4],此时已完成排序。 

示例 2:

输入:[1,2,3]
输出:[]
解释:
输入已经排序,因此不需要翻转任何内容。
请注意,其他可能的答案,如 [3,3] ,也将被判断为正确。

提示:

  • 1 <= arr.length <= 100
  • 1 <= arr[i] <= arr.length
  • arr 中的所有整数互不相同(即,arr 是从 1 到 arr.length 整数的一个排列)

解题思路:

1、通过查看题目我们可知,最后的结果是将这个列表中的元素从小到大进行排序,这是我们做这道题目的关键点。

2、通过题目我们发现所谓的煎饼翻转就是:将索引在K值前面的元素倒序书写。完成这个功能我们可以使用一个for循环语句:for i in range(len(arr)),加上赋值语句:arr[i]=arr[num-i],其中num是题目中的k值。但是我们需要注意,在将一个列表中元素顺序重新排序时,显然需要一个临时列表作为缓冲,从而实现保护已经更改后的列表元素数据。翻转的代码如下:

 def paixu(self,arr,num): 
        #实现根据索引排序功能
        arr1=arr[:]
        for i in range(len(arr)):
            if i<=num:
                arr[i]=arr1[num-i]
        return arr

3.通过题目我们还可以知道若给定列表的元素是:按照从小到大的顺序或者列表元素都是相同的,则不需要进行翻转。所以我们在翻转操作前需要对列表元素进行检验,若列表元素规范,则不需要翻转,反之,则需要翻转。我的思路是:将给定的列表通过排序算法进行排序后,再与给定的列表进行比较,如果两者是相同的,则不需要翻转,返回[]。具体实现代码如下:

def maopao(self,arr):
        for i in range(len(arr)):
            for j in range(len(arr)-1):
                if arr[j]>arr[j+1]:
                    tmp=arr[j]
                    arr[j]=arr[j+1]
                    arr[j+1]=tmp
            return arr

#在进行翻转操作之前,执行检验语句
    if arr1==maopao_arr:
            return []

4.通过题目给出的实例代码我发现通过两次翻转就可实现将最大列表元素移动值最右边:

具体思路为:

①找到列表中最大元素对应的索引,将索引值加1作为题目中的k值。然后将列表和k值传入前文定义好的paixu(arr,k)函数中进行第一次翻转。同时将k追加保存到result空列表中。

②通过第一次翻转,得到的列表内容:可以发现列表中最大元素在列表的最左边,所以我们只要将第一次的翻转结果,作为第二次翻转的输入列表,并且k值传入列表的长度。同时将k追加保存到result空列表中。可以使用len函数。

最后通过两次翻转后我们就实现了将列表中最大元素移动到列表的最右边。此时我们将得到的列表中最大值删除后(通过remove函数),得到的列表作为下一轮第一次翻转的输入列表即可,然后又第一次翻转后的列表作为第二次翻转函数的输入.....依次类推,即可解决问题。

以下是我的代码分享:

class Solution(object):
    def paixu(self,arr,num): 
        #实现根据索引排序功能
        arr1=arr[:]
        for i in range(len(arr)):
            if i<=num:
                arr[i]=arr1[num-i]
        return arr
    
    def maopao(self,arr):
        for i in range(len(arr)):
            for j in range(len(arr)-1):
                if arr[j]>arr[j+1]:
                    tmp=arr[j]
                    arr[j]=arr[j+1]
                    arr[j+1]=tmp
            return arr
                
        
    def maxindex(self,arr):
        #获取给定列表中的最大值索引
        return arr.index(max(arr))
    
    def pancakeSort(self, arr):
        result=[] #存储返回结果
        arr2=[] #存储将最大列表元素放在最右边后的列表
        arr1=arr[:] #将arr的内容复制到arr1中
        arr3=arr[:] #存储去掉最大值后的列表
        arr4=[] #用于存储排完序的结果
        print(arr1) #输出当前传入函数的列表内容
        tmp=0
        maopao_arr=self.maopao(arr)
        print(maopao_arr,arr1)
        if arr1==maopao_arr:
            return []
        for i in range(len(arr1)):
            lenth_arr=len(arr3) #获取当前列表的长度
            print("arr3的列表内容为:",arr3)
            tmp=max(arr3) #获取列表arr3中的最大值
            max_index=self.maxindex(arr3) #获取arr3中最大列表元素对应的索引
            print("列表中最大值的索引为:",max_index)
            tmp_arr=arr3[:]#临时列表,保存第一次翻转内容传输给第二次翻转内容
            if max_index==lenth_arr: #如果列表中最大值已经在最右边,则去掉最大值即可
                arr3.remove(tmp)
                continue
            elif (lenth_arr!=1): #如果还有一个列表元素,则不需要翻转
                        if max_index!=0 and max_index!=lenth_arr-1: #如果次大的元素已经在列表索引为0处,则不进行翻转
                            result.append(max_index+1)
                            tmp_arr=self.paixu(arr3,max_index)
                            print("经过一次排序后输出结果为",tmp_arr,"保存的k值为:",max_index+1)
                            print("最大索引和列表长度",max_index,lenth_arr)
                        if max_index==lenth_arr-1:
                            print("huqinsong")
                            arr3.remove(tmp)
                            continue
                        if lenth_arr-1!=max_index: #如果列表中次大in列表元素与最大元素相邻,则不进行翻转
                            result.append(lenth_arr)
                            print(tmp_arr,lenth_arr-1)
                            arr2=self.paixu(tmp_arr,lenth_arr-1)
                            print("经过两次排序输出结果为:",arr2,"保存ink值为:",lenth_arr)
                            arr2.remove(tmp) #去掉列表中最大值
                            arr4.append(tmp)
                            arr3=arr2[:]
                            print("去掉表中最大值后列表内容:",arr3)
                            print("\n")
                            continue
                        
            else:
                    arr4.append(arr3[0])
                    continue                                
        print("result列表中内容为:",result)
        print("排好序后in结果为:",arr4)
        return result




arr=[3,2,4,1]
s=Solution()
s.pancakeSort(arr)
                    

# 4 2 3 1 (3)
# 1 3 2 4 (4) 
# 3 1 2 4   (2)
# 2 1 3 4 (3)
#1 2 3 4 (2)



力扣运行通过截图:

  • 16
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值