769. 最多能完成排序的块(贪心计数+单调栈)

118 阅读1分钟

image.jpeg

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第22天,点击查看活动详情

测试岗位也越来卷了,除了基本的功能测试外,还要有编程基础、脚本经验才脱颖而出。

怎么才能提高我们的编程能力呢,刷LeetCode是最佳的途径之一,话不多数,刷题走起~

一、题目描述:

  • 题目内容

    image.png

  • 题目示例

    image.png

  • 题目提示

    • n == arr.length
    • 1 <= n <= 10
    • 0 <= arr[i] < n
    • arr 中每个元素都 不同

二、思路分析:

我们今天拿到本题是 leetcode 难度为中等题 769. 最多能完成排序的块。题目要求对arr进行分割成几个块,块中的元素排序后拼接起来与arr升序排序一致,并返回块的个数。在本题中需要注意的细节点:

  • arr数组中的元素都是不同的
  • 长度为n的arr数组,其元素的范围在[0,n-1]
  • 分割的块的结果需要是最多的数量

根据题目内容,我们可以使用贪心计数和单调栈方法来求解,思路如下:

  • 方法一:贪心计数

    • 题目中arr的元素的范围在[0,n-1]内,因此将该范围内最大值与其下标进行比较
    • 例如:[1,0,5,2,3,4] 升序排序后[0,1,2,3,4,5]的索引位置与其元素是相等的
    • 所以我们只需将遍历过的最大数与当前的索引位置相等,则代表需要分割一次,ans进行累计和
    class Solution(object):
        def maxChunksToSorted(self, arr):
            """
            :type arr: List[int]
            :rtype: int
            """
            ans,maxnum = 0,0
            for idex,num in enumerate(arr):
                maxnum = max(maxnum,num)
                if maxnum == idex:
                    ans +=1
            return ans
    
  • 方法二:栈模拟

    • 对arr数组元素划分多个块,我们发现从左到右每一个分割的块都一个最大值,具有单调递增的特点,因此可以使用单调栈来模拟
    • 定义一个数组st来存储每一个块的最大值
    • 当st是空的或num值大于栈顶第一个元素,则将num进行入栈操作
    • 否则将栈顶推出并赋值给tmp变量,将st栈顶值与num值进行比较循环比较,将小于num的元素推出栈
    • 直到遍历完整个栈后,将tmp值重新进行入栈操作
    • 当遍历完arr数组,则栈的长度就是块的个数
    class Solution(object):
        def maxChunksToSorted(self, arr):
            """
            :type arr: List[int]
            :rtype: int
            """
            st = []
            for idex,num in enumerate(arr):
               if not st or num > st[-1]:
                   st.append(num)
               else:
                    tmp = st.pop()
                    while st and st[-1] > num:
                        st.pop()
                    st.append(tmp)
    
            return len(st)
    

三、总结:

本题又是一道关于数组分组概念的题,关键点每一个块都有一个最大值,我们只需判断块中最大值与当前索引位置是否一样时,就能求出分割的块数。AC提交记录如下:

image.png

  • 时间复杂度:O(n),n为arr的长度
  • 空间复杂度:O(n),n为arr的长度

以上是本期内容,欢迎大佬们点赞评论,下期见~~~