最多能完成排序的块&&水果成篮

109 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情

[769. 最多能完成排序的块]

leetcode.cn/problems/ma…

image-20221013143147545

题目的含义可以认为是:可以将数组划分为不同的子数组,然后每个子数组单独进行排序, 最后得到的排序数组的顺序要和对整个数组整体排序的结果一样! 要求的是最多可以把数组划分为多少个子数组! (最多能划分多少块)


很典型的贪心!

长度为n, 因为数组的范围是0~n-1, 这时我们发现排序后的数组它每个元素的值与它的下标值是一致当我们遍历到第i个位置的时候:

  • 如果当前i位置可以被单独切分为1块, 那么前i个位置的最大值一定是i下标, 此时i位置才能被划分为一个块
  • 要不然的话:一定有比i小的元素划分到后面的块, 这样的话,对所有块排序之后,一定不满足升序
class Solution {
public:
    int maxChunksToSorted(vector<int>& arr) {
        int ans = 0;//记录能划分成多少个块
        int maxVal = 0;//记录当前0~i位置的最大元素
        for(int i = 0;i<arr.size();i++)
        {
            maxVal = max(arr[i],maxVal);//前i个位置的最大元素
            if(maxVal == i) //当前i是0~i位置的最大元素,可以划分为单独的一个块!
                ans++;
        }
        return ans;
    }
};

[904. 水果成篮]

leetcode.cn/problems/fr…

image-20221018212433371

题目含义:找至多包含两种元素的最长子串,(求只包含两种元素的最长连续子序列)返回其长度


做法:滑动窗口:

定义一个哈希表记录当前果树种类及其对应的个数, 定义一个变量valid记录当前窗口的水果种类数,维护一个滑动窗口,不断扩展右边界,记录当前装入的水果种类和数量, 一旦水果种类超过2,就收缩左边界,移除左边界的水果,直到水果种类<=2, 然后统计当前最长子串

  • 遍历数组,假设当前i位置的水果为fruit, 先判断当前水果是否出现过 : map[fruit] == 0说明当前水果在[left,right]范围没有出现过,是新增的水果,valid++ 然后哈希表中增加当前水果的出现次数
  • 然后考察当前窗口内的水果,如果果树种类>2,从窗口左边弹出果树,直到满足规则:当前[left,right]水果种类<=2
  • 然后记录当前的最长子串
class Solution {
public:
    //维护一个滑动窗口,不断扩展右边界,记录当前装入的水果种类和数量
    //一旦水果种类超过2,就收缩左边界,移除左边界的水果,直到水果种类<=2
    //题目含义:找至多包含两种元素的最长子串,(求只包含两种元素的最长连续子序列)返回其长度
    int totalFruit(vector<int>& fruits) {
        unordered_map<int,int> map;//果树种类-个数  
        int n  = fruits.size();
        int valid = 0;//记录当前窗口的水果种类数
        int left = 0,right = 0;
        int res = 0;//记录最长的子串长度
        for(right = 0;right<n;right++)
        {
            int fruit = fruits[right];//当前窗口新加入的水果
​
            if(map[fruit] == 0)//说明当前水果没有出现过,是新增的
            {
                valid++;
            }
            map[fruit]++;//水果对应出现次数++
​
            //考察当前窗口内的水果,看是否满足规则
            //如果果树种类>2,从窗口左边弹出果树,直到满足果树种类<=2
            while(valid>2)
            {
                //弹出当前窗口左边的果树->即left往后走,次数--
                int fruit = fruits[left]; //当前左边对应的水果
                left++;
                map[fruit]--;//出现次数--
​
                if(map[fruit] == 0) //该水果没有了,种类-1
                    valid--;
            }
            //此时[left,right]的水果就是满足规则的,长度为:right-left+1
            res = max(res,right-left+1);
        }
        return res;
    }
};