[LeetCode] 768、最多能完成排序的块 II

题目描述

arr是一个可能包含重复元素的整数数组,我们将这个数组分割成几个“块”,并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排序后的原数组相同。我们最多能将数组分成多少块?

输入: arr = [2,1,3,4,4]
输出: 4
解释:
我们可以把它分成两块,例如 [2, 1], [3, 4, 4]。
然而,分成 [2, 1], [3], [4], [4] 可以得到最多的块数。 

解题思路

京东笔试题《合唱队》,单调栈解决。

  • 贪心解法:只有对于某个位置,其左边(包括该数本身)的最大值不大于位置右侧的最小值,在该处就可以分段。
  • 辅助栈解法:直接看代码就好。(如何想到的不太好理解,推荐另两种解法)
  • 哈希表法:对序列A来说,如果知道其排序后的序列B。然后将序列A与序列B对比,容易分析出各个块。那么,对于可分的块,其满足两个特点(之一即可):
    • 块的位置和长度,在序列A和序列B中,相同。
    • 块中的数字,在序列A和序列B中,相同,但顺序可能不同。(哈希表可以用==比较)

参考代码

辅助栈解法

class Solution {
public:
    int maxChunksToSorted(vector<int>& arr) {
        stack<int> s;
        for(auto &x:arr){
            if(s.empty()||x>=s.top()){
                s.push(x);
            }else{
                auto top = s.top();//保留栈顶最大值
                s.pop();
                while(!s.empty()&&x<s.top()){
                    //小的话,一直pop
                    s.pop();
                }
                s.push(top);
            }
        }
        return s.size();
    }
};

哈希表解法

class Solution {
public:
    int maxChunksToSorted(vector<int>& arr) {
        vector<int> B(arr);
        sort(B.begin(),B.end());
        unordered_map<int,int> hasha;
        unordered_map<int,int> hashb;
        
        int ans=0;
        for(int i = 0; i < arr.size(); ++i){
            ++hasha[arr[i]];
            ++hashb[B[i]];
            
            if(hasha==hashb){
                ++ans;
                hasha.clear();  // 这里不clear也行
                hashb.clear();
            }
        }
        
        return ans;
    }

};

“排序 + 累加和”解法(更简单,推荐!)

class Solution {
public:
    int maxChunksToSorted(vector<int>& arr) {
        vector<int> tmp = arr;
        sort(tmp.begin(), tmp.end());
        int res = 0;
        long sum1 = 0, sum2 = 0;
        
        for (int i = 0; i < arr.size(); i++){
            sum1 += tmp[i];
            sum2 += arr[i];
            if (sum1 == sum2) 
                res++;
        }
        return res;
    }

};
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值