当前位置:首页 > 牛客 > 牛客17799题:滑动窗口+优先队列解决多数组最小区间

牛客17799题:滑动窗口+优先队列解决多数组最小区间

5小时前

牛客17799题:滑动窗口+优先队列解决多数组最小区间 滑动窗口 牛客题解 优先队列 C++ 第1张

一、题目解读

牛客17799题要求在一个由K个有序数组组成的集合中,找到包含所有数组元素的最小区间范围。即需确定一个区间[range_start, range_end],使得每个数组中至少有一个元素落在该区间内,且区间长度最小。题目考验对多数组合并与区间优化的处理能力。

二、解题思路

采用“滑动窗口+优先队列”策略:

1. 初始化:将每个数组的首元素加入小根堆(优先队列),记录当前堆顶元素(最小值)与最大值。

2. 滑动窗口:每次取出堆顶元素(当前窗口最小值),更新区间范围。若该元素所在数组存在后续元素,则将其加入堆并更新最大值。

3. 循环终止条件:当某个数组的所有元素已被遍历时结束,确保每个数组至少贡献一个元素到区间。

4. 区间更新逻辑:通过比较新旧区间的长度和起始值,动态维护最小范围。

三、解题步骤

1. 创建包含元素值、行索引、列索引的结构体,重载运算符支持优先队列排序

2. 初始化堆:遍历K个数组首元素,加入堆并记录当前最大值。

3. 循环:

○ 弹出堆顶元素,更新区间范围(根据差值或起始值优先级)。

○ 若该元素非所在数组末尾,则将其下一元素加入堆并更新最大值。

○ 若某数组遍历完毕,终止循环。

4. 返回最终区间[range_start, range_end]。

四、代码与注释

#include <iostream>
#include <vector>
#include <queue>
#include <climits>
using namespace std;

struct Element {
    int val;    // 元素值
    int row;    // 所属数组索引
    int col;    // 在数组中的位置
    
    bool operator>(const Element& other) const {
        return val > other.val;
    }
};

vector<int> smallestRange(vector<vector<int>>& nums) {
    int k = nums.size();
    priority_queue<Element, vector<Element>, greater<Element>> min_heap;
    
    int current_max = INT_MIN;
    // 初始化堆,放入每个数组的第一个元素
    for (int i = 0; i < k; ++i) {
        min_heap.push({nums[i][0], i, 0});
        current_max = max(current_max, nums[i][0]);
    }
    
    int range_start = 0, range_end = INT_MAX;
    
    while (true) {
        Element min_element = min_heap.top();
        min_heap.pop();
        
        // 更新最小区间
        if (current_max - min_element.val < range_end - range_start) {
            range_start = min_element.val;
            range_end = current_max;
        } else if (current_max - min_element.val == range_end - range_start && 
                  min_element.val < range_start) {
            range_start = min_element.val;
            range_end = current_max;
        }
        
        // 如果某个数组已经遍历完,结束循环
        if (min_element.col + 1 == nums[min_element.row].size()) {
            break;
        }
        
        // 将当前数组的下一个元素加入堆
        int next_val = nums[min_element.row][min_element.col + 1];
        min_heap.push({next_val, min_element.row, min_element.col + 1});
        current_max = max(current_max, next_val);
    }
    
    return {range_start, range_end};
}

int main() {
    int k, n;
    cin >> k >> n;
    
    vector<vector<int>> nums(k, vector<int>(n));
    for (int i = 0; i < k; ++i) {
        for (int j = 0; j < n; ++j) {
            cin >> nums[i][j];
        }
    }
    
    vector<int> result = smallestRange(nums);
    cout << result[0] << " " << result[1] << endl;
    
    return 0;
}

五、总结

本解法核心在于利用优先队列维护多数组元素的有序性,通过滑动窗口动态调整区间范围,避免了暴力遍历所有组合。时间复杂度为O(NlogK)(N为总元素数,K为数组数量),空间复杂度为O(K)。通过优化区间更新逻辑,确保在相等长度时优先选择更小区间,从而准确求解最小范围。


原创内容 转载请注明出处

分享给朋友:

相关文章

IOI 1994 洛谷1216:如何用O(1)空间解决数字三角形问题?附代码实现

IOI 1994 洛谷1216:如何用O(1)空间解决数字三角形问题?附代码实现

题目重解:数字三角形是一个经典的动态规划问题,给定一个由数字组成的三角形结构,从顶部出发,每次可以移动到下方相邻的数字,最终到达底部。我们需要找到一条路径,使得路径上经过的数字总和最大。这个问题可以很...

牛客14496题解:括号最大深度问题(栈思想与代码优化)

牛客14496题解:括号最大深度问题(栈思想与代码优化)

一、题目解读牛客14496题要求计算给定括号字符串中的最大深度。例如,对于字符串 "(()())",最大深度为2。题目考察对括号嵌套结构的理解,以及如何通过编程找到最深嵌套层次。二...

力扣3112题解法:带时间限制的最短路径问题解析(C++代码)

力扣3112题解法:带时间限制的最短路径问题解析(C++代码)

一、题目解读力扣3112题要求解决带时间限制的最短路径问题:给定一个有向图,节点具有消失时间,需计算从起点到各节点的最短路径,且路径总时间不能超过节点的消失时间。题目难点在于需在传统最短路径算法(如D...

洛谷1220题解:动态规划与区间DP优化解法(附代码注释)

洛谷1220题解:动态规划与区间DP优化解法(附代码注释)

一、题目解读洛谷1220题要求计算在n个位置放置灯的情况下,通过关闭连续区间灯并移动至区间端点,使得总耗电量最小。需考虑灯的功率与位置差异,设计高效的算法求解最优策略。二、解题思路1. 动态规划 +...

洛谷P2190题解:铁路售票系统车厢计算(差分数组+前缀和优化)

洛谷P2190题解:铁路售票系统车厢计算(差分数组+前缀和优化)

一、题目解读洛谷P2190题要求解决铁路售票系统中的车厢数量计算问题。题目给定n个车站和m条订票申请,每条申请包含区间[x,y)及乘客数z。需要计算在不超载的情况下(每节车厢最多36人),满足所有乘客...

洛谷2652题解析:同花顺排序问题的动态规划与滑动窗口优化

洛谷2652题解析:同花顺排序问题的动态规划与滑动窗口优化

一、题目解读洛谷2652题要求对一组扑克牌进行排序,目标是找到最少需要调整的次数,使得所有牌形成同花顺。题目中,扑克牌由花色和数字组成,需先按花色排序,再在同花色内按数字排序。核心难点在于如何处理花色...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。