找出最长等值子数组

给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。
如果子数组中所有元素都相等,则认为子数组是一个等值子数组 。
从 nums 中删除最多 k 个元素后,返回可能的最长等值子数组的长度。

1. 哈希分组 + 反悔队列

蠢逼做法
class Solution {
public:
    int longestEqualSubarray(vector<int>& nums, int k) {
        int res = 0;
        unordered_map<int,vector<int>> m;
        for(int i=0;i<nums.size();i++)
            m[nums[i]].push_back(i);
        for(auto &[_,arr]:m){
            int n = arr.size(); //尝试进行连接
            int cur = 0; //当前等值子数组长度
            queue<pair<int,int>> q;//反悔队列
            int tricks = k;
            int pre = arr[0]-1;
            int loss = 0;//被舍弃掉的
            for(auto idx:arr){
                int interval = idx - pre - 1;
                if(interval==0)  cur++;////连续的相同元素
                else if(interval<=tricks){//通过删除进行连接
                    tricks-=interval;
                    q.push({interval,cur});//存储反悔可以获得的tricks,和失去的数
                    cur++;
                }
                else if(interval<=k){//可以通过反悔连接
                    while(interval>tricks){
                        tricks+=q.front().first;
                        loss = q.front().second; //更新丢失的数
                        q.pop();//删除
                    }
                    tricks-=interval;
                    q.push({interval,cur});//存储反悔可以获得的tricks,和失去的数
                    cur++;
                }
                else{//重新开辟
                    cur = 1;
                    loss = 0;
                    q = queue<pair<int,int>>();
                    tricks = k;
                }
                pre = idx;
                res = max(res,cur-loss);
            }
        }
        return res;
    }
};

2. 哈希分组 + 预处理 + 双指针

用双指针代替反悔队列,使用vector会比哈希更快,同时将相邻的归为一组

class Solution {
public:
    int longestEqualSubarray(vector<int> &nums, int k) {
        int n = nums.size(), ans = 0;
        vector<vector<int>> pos(n + 1);
        for (int i = 0; i < n; i++)
            pos[nums[i]].push_back(i - pos[nums[i]].size());
        for (auto &ps: pos) {
            int left = 0;
            for (int right = 0; right < ps.size(); right++) {
                while (ps[right] - ps[left] > k) // 要删除的数太多了
                    left++;
                ans = max(ans, right - left + 1);
            }
        }
        return ans;
    }
};
posted @ 2023-08-20 17:40  失控D大白兔  阅读(45)  评论(0编辑  收藏  举报