计算初始化内存总长度

计算初始化内存总长度

问题背景

在一个系统中,需要执行一系列的内存初始化操作。每次操作都会初始化一个特定地址范围的内存。这些操作范围可能会相互重叠。我们需要计算所有操作完成后,被初始化过的内存空间的总长度。

核心定义

  • 操作范围 : 每一次内存初始化操作由一个范围 [start, end] 定义,它代表一个左闭右开 的区间 [start, end)。这意味着地址 start 被包含,而地址 end 不被包含。
  • 内存长度 : 对于一个操作 [start, end],其初始化的内存长度为 end - start

关键假设

  1. 所有初始化操作都会成功执行。
  2. 同一块内存区域允许被重复初始化。例如,操作 [2, 5)[4, 7) 是允许的,它们有重叠部分 [4, 5)

任务要求

给定一组内存初始化操作 cmdsOfMemInit,计算所有操作完成后,被初始化过的内存空间的总长度。这等同于计算所有给定区间的并集的总长度。


输入格式

  • cmdsOfMemInit: 一个二维数组(或列表的列表),代表一系列的内存初始化操作。

    • 数组长度: 1 <= cmdsOfMemInit.length <= 100000
    • 每个元素 cmdsOfMemInit[i] 是一个包含两个整数 [start, end] 的数组。
    • 区间范围: 0 <= start < end <= 10^9

输出格式

  • 一个整数,表示最终被初始化过的内存空间的总长度。

样例说明

样例 1

  • 输入 : [[2, 4], [3, 7], [4, 6]]

  • 输出 : 5

  • 解释:

    1. 我们有三个区间:[2, 4), [3, 7), [4, 6)
    2. 合并 [2, 4)[3, 7) : 因为它们有重叠部分([3, 4)),所以可以合并成一个更大的区间 [2, 7)
    3. 合并 [2, 7)[4, 6) : 新的区间 [4, 6) 完全被 [2, 7) 覆盖。合并后的结果仍然是 [2, 7)
    4. 所有操作完成后,最终被初始化的内存区域是 [2, 7)
    5. 总长度为 7 - 2 = 5

样例 2

  • 输入 : [[3, 7], [2, 4], [10, 30]]

  • 输出 : 25

  • 解释:

    1. 我们有三个区间:[3, 7), [2, 4), [10, 30)
    2. 合并 [3, 7)[2, 4) : 它们有重叠部分,合并后的区间为 [2, 7)
    3. 合并 [2, 7)[10, 30) : 这两个区间没有重叠,因为 10 大于 7。它们是两个独立的初始化区域。
    4. 所有操作完成后,最终的初始化内存区域由两个不相交的区间组成:[2, 7)[10, 30)
    5. 总长度是这两个独立区间长度之和:(7 - 2) + (30 - 10) = 5 + 20 = 25
java 复制代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * 解决"内存空间长度"问题的方案类。
 */
public class Solution {
    /**
     * 计算一系列内存初始化操作覆盖的总内存空间长度。
     *
     * @param cmdsOfMemInit 一个二维数组,每个内部数组 [start, end] 代表一个左闭右开的内存初始化区间。
     * @return 最终初始化的内存空间的总长度。
     */
    public long totalInitializedLength(int[][] cmdsOfMemInit) {
        // --- 1. 处理边界情况 ---
        // 如果输入为空或没有操作,则总长度为 0。
        if (cmdsOfMemInit == null || cmdsOfMemInit.length == 0) {
            return 0;
        }

        // --- 2. 按区间的起始地址(start)对所有操作进行升序排序 ---
        // 这是合并区间的关键前提步骤。
        // Comparator.comparingInt(a -> a[0]) 是一个简洁的写法,表示按内部数组a的第一个元素排序。
        Arrays.sort(cmdsOfMemInit, Comparator.comparingInt(a -> a[0]));

        // --- 3. 合并重叠和连续的区间 ---
        // 使用一个 List 来存储合并后的、不重叠的区间。
        List<int[]> mergedIntervals = new ArrayList<>();
        // 首先将第一个区间(起始地址最小)加入合并列表作为基础。
        mergedIntervals.add(cmdsOfMemInit[0]);

        // 遍历排序后的其余区间
        for (int i = 1; i < cmdsOfMemInit.length; i++) {
            int[] currentInterval = cmdsOfMemInit[i];
            // 获取合并列表中的最后一个区间,用于比较
            int[] lastMerged = mergedIntervals.get(mergedIntervals.size() - 1);

            // 检查当前区间是否与最后一个合并区间重叠或连续。
            // 因为区间是 [start, end) 左闭右开,所以当 currentInterval 的 start <= lastMerged 的 end 时,
            // 它们就需要合并。例如 [2,4) 和 [4,6) 应该合并为 [2,6)。
            if (currentInterval[0] <= lastMerged[1]) {
                // --- 合并区间 ---
                // 如果有重叠/连续,则更新最后一个合并区间的结束地址。
                // 新的结束地址是两个区间结束地址中的较大者。
                // 例如,合并 [2,7) 和 [4,6) 时,新的 end 是 max(7, 6) = 7,结果为 [2,7)。
                lastMerged[1] = Math.max(lastMerged[1], currentInterval[1]);
            } else {
                // --- 不重叠,添加新区间 ---
                // 如果没有重叠,则将当前区间作为一个新的、独立的合并区间添加到列表中。
                mergedIntervals.add(currentInterval);
            }
        }

        // --- 4. 计算合并后区间的总长度 ---
        // 使用 long 类型来存储总长度,防止因数值过大(坐标可达10^9)而溢出。
        long totalLength = 0;
        // 遍历所有不重叠的合并区间
        for (int[] interval : mergedIntervals) {
            // 累加每个区间的长度 (end - start)
            totalLength += (long) interval[1] - interval[0];
        }

        // --- 5. 返回结果 ---
        return totalLength;
    }


    public static void main(String[] args) {
        Solution sol = new Solution();

        // 样例1
        int[][] cmds1 = {{2, 4}, {3, 7}, {4, 6}};
        System.out.println("样例1 输入: [[2, 4], [3, 7], [4, 6]]");
        System.out.println("样例1 输出: " + sol.totalInitializedLength(cmds1)); // 预期: 5

        // 样例2
        int[][] cmds2 = {{3, 7}, {2, 4}, {10, 30}};
        System.out.println("\n样例2 输入: [[3, 7], [2, 4], [10, 30]]");
        System.out.println("样例2 输出: " + sol.totalInitializedLength(cmds2)); // 预期: 25

        // 边界测试
        int[][] cmds3 = {{1, 5}, {6, 10}};
        System.out.println("\n边界测试 输入: [[1, 5], [6, 10]]");
        System.out.println("边界测试 输出: " + sol.totalInitializedLength(cmds3)); // 预期: 8 (4+4)
    }
    */
}
相关推荐
会唱歌的小黄李2 分钟前
【算法】贪心算法:最大数C++
c++·算法·贪心算法
NuyoahC4 分钟前
笔试——Day8
c++·算法·笔试
Pi_Qiu_22 分钟前
Python初学者笔记第十三期 -- (常用内置函数)
java·笔记·python
hsx66628 分钟前
Android 基础筑基(一)
java
hy.z_77734 分钟前
【数据结构】反射、枚举 和 lambda表达式
android·java·数据结构
墨染点香35 分钟前
LeetCode Hot100 【1.两数之和、2.两数相加、3.无重复字符的最长子串】
算法·leetcode·职场和发展
從南走到北44 分钟前
JAVA青企码协会模式系统源码支持微信公众号+微信小程序+H5+APP
java·微信·微信小程序·小程序·uni-app·微信公众平台
草履虫建模1 小时前
Ajax原理、用法与经典代码实例
java·前端·javascript·ajax·intellij-idea
强哥叨逼叨1 小时前
别被假象迷惑!揭秘 Java 线程池中“线程空着但任务卡着”的真相
java
秋说1 小时前
【PTA数据结构 | C语言版】二叉树层序序列化
c语言·数据结构·算法