栈和排序你学会了吗

问题描述

给你一个由1~n,n个数字组成的一个排列和一个栈,要求按照排列的顺序入栈。如何在不打乱入栈顺序的情况下,仅利用入栈和出栈两种操作,输出字典序最大的出栈序列。

排列:指 1 到 n 每个数字出现且仅出现一次。

示例:

输入:[2,1,5,3,4]

输出:[5,4,3,1,2]

分析问题

由于我们只能使用出栈和入栈两种操作,要想使得出栈序列字典序最大,首先想到的就是令高位尽可能地大,我们出栈的时机就是:当前入栈元素若是大于之后将要入栈的元素,那么就将其出栈。当元素出栈后,还需要判断栈顶元素与之后将要入栈元素之间的大小关系,如果此时栈顶元素大于之后将要入栈的元素,那么就将其出栈,不断判断直到栈为空或条件不满足。

为了快速判断“当前入栈元素是否大于之后将要入栈的元素”,我们需要创建一个辅助数组temp,其中temp[i]表示i之后的最大元素。借助辅助数组,我们可以以O(1)的时间复杂度去判断当前入栈元素是否大于之后将要入栈的元素。

image-20211109214153107

image-20211109214153107

image-20211109215553532

image-20211109215553532

image-20211109215610927

image-20211109215610927

image-20211109215644288

image-20211109215644288

image-20211109215700561

image-20211109215700561

image-20211109215716016

image-20211109215716016

image-20211109215736573

image-20211109215736573

image-20211109215756969

image-20211109215756969

image-20211109215816076

image-20211109215816076

下面我们来看一下代码的实现。

import sys
class Solution:
    def solve(self , a):
        n=len(a)
        res=[]
        if n==0:
            return res
        stack=[]
        temp=[0]*n
        temp[n-1]=-sys.maxsize-1
        #从右往左遍历数组a,然后取填充temp
        #使得temp[i]表示i之后的最大元素
        for i in range(n-2,-1,-1):
            temp[i]=max(a[i+1],temp[i+1])

        #遍历数组a
        for i in range(0,n):
            if a[i] > temp[i]:  #若当前元素大于之后将要入栈的元素,将其加入结果中
                res.append(a[i])
                # 若栈不为空,且栈顶元素大于temp[i],
                # 栈顶出栈,加入结果中
                while stack and stack[-1] > temp[i]:
                    res.append(stack[-1])
                    stack.pop()
            else:
                stack.append(a[i])

        while stack:
            res.append(stack[-1])
            stack.pop()
        return res

该算法的时间复杂度是O(n),空间复杂度也是O(n)。

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
快速排序算法是一种基于分治思想的排序算法,其基本思路是选择一个基准元素,将待排序序列分成两部分,左边部分所有元素都小于基准元素,右边部分所有元素都大于基准元素,再对左右两部分递归地进行快速排序,直到整个序列有序。快速排序的时间复杂度为 O(nlogn),是一种比较高效的排序算法。 下面是快速排序算法的伪代码: ``` function quickSort(arr, left, right) if left < right pivotIndex = partition(arr, left, right) quickSort(arr, left, pivotIndex - 1) quickSort(arr, pivotIndex + 1, right) function partition(arr, left, right) pivot = arr[right] i = left - 1 for j = left to right - 1 if arr[j] < pivot i = i + 1 swap arr[i] and arr[j] swap arr[i + 1] and arr[right] return i + 1 ``` 快速排序的时间复杂度分析可以参考以下步骤: 1. 最好情况下,每次选择的基准元素都能恰好将序列分成两个长度相等的部分,此时递归树的深度为 logn,每层的时间复杂度为 O(n),因此总时间复杂度为 O(nlogn)。 2. 最坏情况下,每次选择的基准元素都是序列中的最小或最大值,此时递归树呈现一支倾斜,深度为 n,每层的时间复杂度为 O(n),因此总时间复杂度为 O(n^2)。 3. 平均情况下,以任意一个元素作为基准元素的概率相等,因此递归树的平均深度为 logn,总时间复杂度为 O(nlogn)。 4. 快速排序的空间复杂度为 O(logn),因为每次递归需要额外使用 O(logn) 的空间。 希望这些内容能够帮到您学习快速排序算法和效率分析。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值