当前位置: 首页 > article >正文

算法随笔_67: 使数组按非递减顺序排列

上一篇:算法随笔_66: 多数元素_方法2-CSDN博客

=====

题目描述如下:

给你一个下标从 0 开始的整数数组 nums 。在一步操作中,移除所有满足 nums[i - 1] > nums[i] 的 nums[i] ,其中 0 < i < nums.length 。

重复执行步骤,直到 nums 变为 非递减 数组,返回所需执行的操作数。

示例 1:

输入:nums = [5,3,4,4,7,3,6,11,8,5,11]
输出:3
解释:执行下述几个步骤:
- 步骤 1 :[5,3,4,4,7,3,6,11,8,5,11] 变为 [5,4,4,7,6,11,11]
- 步骤 2 :[5,4,4,7,6,11,11] 变为 [5,4,7,11,11]
- 步骤 3 :[5,4,7,11,11] 变为 [5,7,11,11]
[5,7,11,11] 是一个非递减数组,因此,返回 3 。

示例 2:

输入:nums = [4,5,7,7,13]
输出:0
解释:nums 已经是一个非递减数组,因此,返回 0 。

=====

算法思路:

首先,我们从右往左观察原数组,发现其中蕴含着递推关系。我们设如下变量:

n为原数组长度。

数组cntLst: cntLst[i]表示区间[i, n-1]变为非递减数组所需的操作数。

数组delCntLst: delCntLst[i]表示元素i在碰到比它大的元素之前需要做多少次的消除操作。

那么递推关系就是,cntLst[i]=max(delCntLst[i], cntLst[i+1])

假如cntLst[i+1]用了10次操作,无论在这段区间[i+1, n-1]如何消除的元素,如果delCntLst[i]用了15次的操作,那它的前10次是可以随着cntLst[i+1]的操作同时完成的,因此cntLst[i]就用了15次。

同理,如果delCntLst[i]用了5次的操作,那cntLst[i+1]的前5次是可以随着delCntLst[i]的操作同时完成的,因此cntLst[i]总共就用了10次。

我们再来看delCntLst[i]是如何计算的。我们设cnt为元素i当前消除的操作数,初始值为0。元素i每消除一个它后面比它小的元素,操作数cnt都加1,然后再取max(cnt, delCntLst[i+1])。原理和上面的类似。要取操作数大的那个值。因为少的操作数可以和多的操作数的部分操作同时进行。

最后在算法具体实现时,我们可以使用一个单调栈stck来维护元素的消除和添加。当我们从右往左遍历原数组时,只要当前的元素大于栈顶元素,即nums[i]>stck[-1],我们就弹出栈顶,不断判断,直到当前元素nums[i]小于等于栈顶,我们才把nums[i]放入栈。然后我们再更新delCntLst和cntLst。

代码实现时,cntLst数组可以不要,只需要一个变量res即可,具体可参考下面的Python代码。此算法的时间复杂度为O(n)。

class Solution(object):
    def totalSteps(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n=len(nums)
        stck=[n-1]
        res=0
        delCntLst=[0]*n
        for i in range(n-2, -1, -1):
            cnt=0
            while stck and nums[i]>nums[stck[-1]]:
                cnt+=1
                cnt=max(cnt,delCntLst[stck.pop()])
            delCntLst[i]=cnt
            res=max(res,cnt)
            stck.append(i)

        return res

关键词: 单调栈


http://www.kler.cn/a/576034.html

相关文章:

  • 三维建模与视频融合(3D-Video Integration)技术初探。
  • 是德科技十周年:以创新丈量未来,用科技赋能世界
  • 非常好用的账号密码管理器
  • maven 多模块 笔记
  • rust编程实战:实现3d粒子渲染wasm
  • tcc编译器教程3 简单编译gmake源代码
  • 常用无功功率算法的C语言实现(一)
  • docker1
  • 23种设计模式简介
  • 基于掩码自编码器的可扩展视觉学习者
  • pytorch3d学习(三)——渲染纹理网格
  • 服务器带宽堵塞会对网站访问产生哪些影响?
  • C/C++ 实现由用户通过键盘输入自然数并判断其是不是素数(带清空缓冲区等考虑)
  • 解决ubuntu18.04系统更新的问题
  • 风虎云龙R87与RH87八卡服务器震撼首发
  • 《白帽子讲 Web 安全》之文件操作安全
  • RV1126+FFMPEG多路码流监控项目
  • 【FSM-3: 串行序列】
  • NVIC原理和使用
  • 【免费】2000.1-2021.9上市公司仲裁数据