Leetcode打卡:最小区间

执行结果:通过

题目:632 最小区间

你有 k非递减排列 的整数列表。找到一个 最小 区间,使得 k 个列表中的每个列表至少有一个数包含在其中。

我们定义如果 b-a < d-c 或者在 b-a == d-ca < c,则区间 [a,b][c,d] 小。

示例 1:

复制代码
输入:nums = [[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]
输出:[20,24]
解释: 
列表 1:[4, 10, 15, 24, 26],24 在区间 [20,24] 中。
列表 2:[0, 9, 12, 20],20 在区间 [20,24] 中。
列表 3:[5, 18, 22, 30],22 在区间 [20,24] 中。

示例 2:

复制代码
输入:nums = [[1,2,3],[1,2,3],[1,2,3]]
输出:[1,1]

提示:

  • nums.length == k
  • 1 <= k <= 3500
  • 1 <= nums[i].length <= 50
  • -105 <= nums[i][j] <= 105
  • nums[i] 按非递减顺序排列

代码以及解题思路

代码:

复制代码
#define maxn 100005

int heap[maxn];
int heap_count;
int **rec, *nx;

bool heap_comp(int *first, int *second) {
    return rec[*first][nx[*first]] < rec[*second][nx[*second]];
}

void swap(int *first, int *second) {
    int temp = *second;
    *second = *first;
    *first = temp;
    return;
}

void push(int num) {
    int pos = ++heap_count;
    heap[pos] = num;
    while (pos > 1) {
        if (heap_comp(&heap[pos], &heap[pos >> 1])) {
            swap(&heap[pos], &heap[pos >> 1]);
            pos >>= 1;
        } else
            break;
    }
    return;
}

void pop() {
    int top_num = 1;
    int now;
    swap(&heap[top_num], &heap[heap_count--]);
    while ((now = (top_num << 1)) <= heap_count) {
        if (heap_comp(&heap[now + 1], &heap[now]) && now < heap_count) now++;
        if (heap_comp(&heap[now], &heap[top_num])) {
            swap(&heap[top_num], &heap[now]);
            top_num = now;
        } else
            break;
    }
}

int top() { return heap[1]; }

int* smallestRange(int** nums, int numsSize, int* numsColSize, int* returnSize) {
    heap_count = 0;
    nx = (int *)malloc(sizeof(int) * numsSize);
    memset(nx, 0, sizeof(int) * numsSize);
    rec = nums;

    int rangeLeft = 0, rangeRight = 2147483647;
    int minValue = 0, maxValue = -2147483648;
    for (int i = 0; i < numsSize; ++i) {
        push(i);
        maxValue = fmax(maxValue, nums[i][0]);
    }

    while (true) {
        int row = top();
        pop();
        minValue = nums[row][nx[row]];
        if (maxValue - minValue < rangeRight - rangeLeft) {
            rangeLeft = minValue;
            rangeRight = maxValue;
        }
        if (nx[row] == numsColSize[row] - 1) {
            break;
        }
        ++nx[row];
        maxValue = fmax(maxValue, nums[row][nx[row]]);
        push(row);
    }
    int *ret = malloc(sizeof(int) * 2);
    ret[0] = rangeLeft, ret[1] = rangeRight;
    *returnSize = 2;
    return ret;
}

解题思路:

数据结构准备

  1. 最小堆 :使用数组 heap 来实现一个最小堆,堆中的元素是数组的索引。堆的大小由 heap_count 控制。
  2. 辅助数组nx 数组用来记录每个数组当前考虑的元素的索引,rec 指向输入的二维数组。

堆的比较函数

  • heap_comp 函数:比较两个堆中元素(即数组索引)所指向的当前值的大小。这决定了堆的排序方式,即根据当前考虑的数组元素的值进行排序。

堆的基本操作

  • swap 函数:交换两个整数的值。
  • push 函数:将一个元素(数组索引)加入到堆中,并保持堆的性质。
  • pop 函数:移除堆顶元素,并重新调整堆以保持最小堆的性质。
  • top 函数:获取堆顶元素(不移除)。

主逻辑

  1. 初始化
    • 将所有数组的第一个元素加入堆中,并记录当前的最大值 maxValue
    • 初始化差值范围的左右边界 rangeLeftrangeRight 为最大和最小可能的整数值。
  2. 迭代寻找最小差值范围
    • 从堆中取出当前最小值所在的数组索引 row
    • 更新当前的最小值 minValue
    • 检查当前的最小差值范围是否比已知的最小差值范围更小,如果是,则更新 rangeLeftrangeRight
    • 如果当前数组的所有元素都已考虑过(即 nx[row] 指向数组的最后一个元素),则停止循环。
    • 否则,移动到当前数组的下一个元素,更新 nx[row]maxValue(如果需要的话)。
    • 将当前数组索引重新加入堆中,以便在下一次迭代中考虑。
  3. 返回结果
    • 分配一个大小为2的整数数组 ret,用于存储最小差值范围的左右边界。
    • 设置 *returnSize 为2,表示返回数组的大小。
    • 返回 ret

关键点

  • 使用最小堆可以高效地获取当前所有数组中的最小值。
  • 通过动态调整每个数组当前考虑的元素的索引 nx,可以逐步探索所有可能的差值范围。
  • 不断更新和维护当前的最小差值范围,直到所有数组的所有元素都被考虑过。

这种方法的时间复杂度主要由堆操作(插入和删除)决定,为 O(N log M),其中 N 是所有数组中元素的总数,M 是数组的数量。空间复杂度为 O(M),用于存储堆和辅助数组。

相关推荐
拂拉氏5 分钟前
【知识讲解】 AVL树从基本成员的介绍到核心接口的实现(插入、判断、删除等等)
数据结构·算法·avl树
可靠的仙人掌1 小时前
SAC(Soft Actor-Critic)算法底座
开发语言·算法·php
海石2 小时前
单调栈复健,顺便,牺牲一下吧,空间复杂度!一切献给AC
算法·leetcode
海石2 小时前
JS击败94%,Hard题想不到动态规划,那就用数组和栈试试
算法·leetcode
杨逢昌工厂6S管理4 小时前
28- 杨逢昌:制造企业仓储6S反复混乱解决方案——四维定置标准化管控体系,让物料混放、通道堵塞等重复性乱象减少90%
大数据·经验分享·笔记·职场和发展·制造·学习方法
alphaTao4 小时前
LeetCode 每日一题 2026/7/6-2026/7/12
算法·leetcode
想吃火锅10055 小时前
【leetcode】56.合并区间js
算法·leetcode·职场和发展
imuliuliang5 小时前
可合并堆在多任务调度中的优势与实现技巧7
算法
学究天人5 小时前
数学公理体系大全:Comprehensive Collection of Mathematical Axiom Systems(卷6)
网络·算法·数学建模·动态规划·几何学·图论·拓扑学
wabs6665 小时前
关于动态规划【力扣72.编辑距离的思考】
算法·leetcode·动态规划