【差分数组 区间的综合用例】

根据前面两篇文章
区间合并
差分数组
对差分数组和合并区间的介绍,以下是两道相关的例题,其中综合题融合了区间合并和差分数组,非常经典,也有点难度,值得仔细琢磨

最合适的价格 (差分数组)

给定一个二维数组prices,price[i] 表示第 i 个商户能接受的价格区间范围。

商品总售价 = 店家数 * 价格,要想使得商品总售价最高,求最小的价格是?

例子:

[
    [1, 9],
    [7, 12],
    [8, 15],
  ]

在这里插入图片描述

价格为9 时,总售价最高

思路:构造一个map price ⇒ 商户个数,因为只有端点和(端点前)可能出现最大值,因此只需要用diffMap 记录即可,不需要使用diffArr 记录区间里的每个点。

const getBestPrice = (prices) => {
  // 实现一个diffMap
  const diffMap = new Map();
  for (let i = 0; i < prices.length; i++) {
    const [start, end] = prices[i];

    if (!diffMap.has(start)) {
      diffMap.set(start, 0);
    }
    if (!diffMap.has(end + 1)) {
      diffMap.set(end + 1, 0);
    }
    diffMap.set(end + 1, diffMap.get(end + 1) - 1);
    diffMap.set(start, diffMap.get(start) + 1);
  }

  const sortedDiffMap = new Map(
    [...diffMap.entries()].sort((a, b) => a[0] - b[0])
  );

  let sum = 0;

  let res = 0;
  let max = 0;
  let flag = false;
  for (const [price, count] of sortedDiffMap.entries()) {
    if (!flag) {
      //第一次
      sum += count;
      if(sum * price > max){
        max = sum * price;
        res = price;
      }
      flag = true;
    } else {
      // 如果不是第一次出现的结点,需要记录它前面一个点的价格
      if(sum * (price - 1) > max){
        max = sum * (price - 1);
        res = price - 1;
      }
      sum += count;
    }
  }
  return res;
};

console.log(getBestPrice([[3,5], [4,6], [9,10]]));
console.log(
  getBestPrice([
    [7, 9],
    [8, 10],
    [9, 10],
  ])
);
console.log(
  getBestPrice([
    [1, 9],
    [7, 12],
    [8, 15],
  ])
);

空闲服务器数 (合并与区间的综合题)

有serverNum 个服务器,给出taskList,taskList[i] = {startTime,endTime,serveId} 表示某个服务器serveceId 在startTime 到 endTime 被占用。
求在哪些时间仅有一台服务器是空闲的。

思路:

  • 用map 将相同任务id被占用的时间进行聚合
  • 对同一个id的任务进行区间合并
  • 构造差分Map,是开区间
  • 利用差分Map还原出数组时维护最终答案,不必通过还原后再去遍历寻找结果。
const mergeIntervals = (intervals) => {
  let merged = [intervals[0]];
  for (let i = 1; i < intervals.length; i++) {
    const [start, end] = intervals[i];
    if (merged[merged.length - 1][1] < start) {
      merged.push([start, end]);
    } else {
      merged[merged.length - 1][1] = Math.max(
        merged[merged.length - 1][1],
        end
      );
    }
  }
  return merged;
};

const buildDiffMap = (allTaskList) => {
  let diffMap = new Map();
  for (let i = 0; i < allTaskList.length; i++) {
    const [start, end] = allTaskList[i];
    if (!diffMap.has(start)) {
      diffMap.set(start, 0);
    }
    if (!diffMap.has(end)) {
      diffMap.set(end, 0);
    }
    diffMap.set(start, diffMap.get(start) + 1);
    diffMap.set(end, diffMap.get(end) - 1);

    // diffMap.set(start, diffMap.get(start)+1 || 1 );  // 可能会出现 0 || 1 就会取后面的1
    // diffMap.set(end, diffMap.get(end)-1 || -1);
  }
  return diffMap;
};

const getIntervals = (diffMap, target) => {
  let ans = [];
  let left = -1;
  let sum = 0;
  for (const [index, times] of diffMap.entries()) {
    sum += times;
    if (sum === target && left === -1) {
      left = index;
    }
    if (sum !== target && left !== -1) {
      ans.push([left, index]);
      left = -1;
    }
  }
  return ans;
};

/**
 * 待实现函数,在此函数中填入答题代码
 * @param {number} serverNum
 * @param {Task[]} tasks
 * @return {number[][]}
 */
const getOneFreeTime = (serverNum, tasks) => {
  // 遍历tasks,将每个服务器的任务存起来。
  const taskMap = new Map();
  tasks.forEach((task) => {
    const { startTime, endTime, serverId } = task;
    taskMap.set(serverId, taskMap.get(serverId) || []);
    taskMap.get(serverId).push([startTime, endTime]);
  });

  // 遍历taskMap ,对每个服务器下的任务进行合并并且存放到taskList里。
  const allTaskList = [];
  for (const [serverId, taskList] of taskMap.entries()) {
    taskList.sort((a, b) => a[0] - b[0]);
    let merged = mergeIntervals(taskList);
    allTaskList.push(...merged);
  }

  // 使用diffMap 而不是 数组 提高性能
  let diffMap = buildDiffMap(allTaskList);


  // 对diffMap按照key进行排序。
  let sortedDiffMap = new Map(
    [...diffMap.entries()].sort((a, b) => a[0] - b[0])
  );

  // 根据diffMap算结果数组,并且边计算边维护答案
  let ans = getIntervals(sortedDiffMap, serverNum - 1);

  // // 遍历sortedTaskList,差分数组记录端点值
  // let len = sortedTaskList[sortedTaskList.length-1][1];
  // let diff = new Array(len).fill(0);
  // for(let i = 0;i<sortedTaskList.length;i++){
  //     const [start,end] = sortedTaskList[i];
  //     diff[start-1]++;
  //     diff[end-1]--;
  // }

  // // 根据diff数组还原结果数组
  // let result = [diff[0]];
  // for(let i = 1;i<diff.length;i++){
  //     result.push(result[result.length-1]+diff[i]);
  // }

  // // 根据结果数组返回符合条件的区间。
  // let ans = [];
  // let left = -1;
  // for(let i = 0;i<result.length;i++){
  //     if(result[i]===serverNum-1 && left===-1){
  //         left = i;
  //     }else if(result[i]!==serverNum-1 && left!==-1){
  //         ans.push([left+1,i+1]);
  //         left = -1;
  //     }
  // }
  return ans.length === 0 ? [[-1, -1]] : ans;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/367703.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java线程是怎么实现run方法的执行的呢?【 多线程在JVM中的实现原理剖析】

Java线程是怎么实现run方法的执行的呢&#xff1f;【 多线程在JVM中的实现原理剖析】 查看naive state0 方法JVM_StartThread 方法创建操作系统线程操作系统线程执行 本文转载-极客时间 我们知道Java线程是通过行start()方法来启动的&#xff0c;线程启动后会执行run方法内的代…

【Linux网络编程三】Udp套接字编程(简易版服务器)

【Linux网络编程三】Udp套接字编程(简易版服务器&#xff09; 一.创建套接字二.绑定网络信息1.构建通信类型2.填充网络信息①网络字节序的port②string类型的ip地址 3.最终绑定 三.读收消息1.服务器端接收消息recvfrom2.服务器端发送消息sendto3.客户端端发送消息sendto4.客户端…

Python使用分治算法作归并排序

对于分治算法的一个较为常规的应用中&#xff0c;归并排序是一个使用分治算法的排序方式。给定一个随机排序的数组&#xff0c;我们要将其元素按照升序或者降序的方式进行排序&#xff0c;可以设想到这样的一种算法&#xff0c;如果一个数组的上半部分和下半部分已经排好序&…

Vue打包Webpack源码及物理路径泄漏问题解决

修复前&#xff1a; 找到vue.config.js文件&#xff0c;在其中增加配置 module.exports {productionSourceMap: false,// webpack 配置configureWebpack: {devtool: false,}}其中打包的物理路径泄露我这边试了好多次&#xff0c;发现只有打包的时候NODE_ENVproduction 才能保…

JSP和JSTL板块:第三节 JSP四大域对象 来自【汤米尼克的JAVAEE全套教程专栏】

JSP和JSTL板块&#xff1a;第三节 JSP四大域对象 一、page范围二、request范围三、session范围四、application范围 在服务器和客户端之间、各个网页之间、哪怕同一个网页之内&#xff0c;总是需要传递各种参数值&#xff0c;这时JSP的内置对象就是传递这些参数的载具。内置对象…

Iceberg从入门到精通系列之二十三:Spark查询

Iceberg从入门到精通系列之二十三&#xff1a;Spark查询 一、使用 SQL 查询二、使用 DataFrame 进行查询三、Time travel四.Incremental read五、检查表六、History七、元数据日志条目八、Snapshots九、Files十、Manifests十一、Partitions十二、所有元数据表十三、参考十四、使…

泰克示波器(TBS2000系列)触发功能使用讲解——边沿触发

# Trigger区域 触发区域用于对触发功能进行配置。示波器的触发功能用于采集&#xff08;Acquire&#xff09;那些在瞬间出现的信号&#xff0c;便于我们分析观察&#xff0c;此时可以当做逻辑分析仪使用。触发区域按钮包括&#xff1a;menu、Level\Force Trig三个。 目录 1.1 …

【机器学习 深度学习】卷积神经网络简述

&#x1f680;个人主页&#xff1a;为梦而生~ 关注我一起学习吧&#xff01; &#x1f4a1;专栏&#xff1a;机器学习 欢迎订阅&#xff01;相对完整的机器学习基础教学&#xff01; ⭐特别提醒&#xff1a;针对机器学习&#xff0c;特别开始专栏&#xff1a;机器学习python实战…

telnet笔记

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、场景二、介绍1.测试端口2.访问百度3. 简单的爬虫 前言 最近telnet命令用的比较多&#xff0c;所以记录一下。 一、场景 ping应该是大家最常用的命令&…

unity角色触摸转向

1、挂载脚本到角色的父物体A上 2 、以屏幕左边的触摸为移动&#xff0c;右边为转向操作 3、加载角色时&#xff0c;将角色的父物体设置为A&#xff0c;须将角色的位置和角度置0 using System; using System.Collections; using System.Collections.Generic; using UnityEngin…

python之组合数据类型-字典dict

字典 字典的定义与特点操作字典创建字典字典的增删改查添加键值对删除键值对修改键值对访问元素 遍历字典 嵌套 字典的定义与特点 字典&#xff1a;字典是一系列键值对&#xff0c;是一种无序的数据集合&#xff0c;它是通过键来访问的&#xff0c;而不是索引 字典的特点&#…

【Go语言成长之路】安装Go

文章目录 安装Go一、下载Go语言安装包二、删除以前安装的Go版本三、添加/usr/local/go/bin到环境变量内四、确认安装成功 安装Go Note: 这里只演示安装Linux版本的Go&#xff0c;若为其它版本&#xff0c;请按照官网的安装教程进行安装即可。 一、下载Go语言安装包 ​ 在浏览…

Unity | Spine动画记录

https://blog.csdn.net/linshuhe1/article/details/79792432 https://blog.csdn.net/winds_tide/article/details/128925407 1.需要的三个文件 通常制作好的 Spine 动画导出时会有三个文件&#xff1a; .png 、.json 和 .atlas&#xff1a; skeleton-name.json 或 skeleton-…

Blender教程(基础)-面的法向-12

一、准备 新建如下图所示立方体演示面的法向 默认法向方向 二、显示法向 再菜单栏右上角、找到网络编辑模式&#xff0c;最下面的显示发法线打勾&#xff0c;如下图所示&#xff0c;出现的浅蓝色线条就是代表法向方向。 调整大小显示 三、正面 再显示叠加层菜单下找到面…

pytorch调用多个gpu训练,手动分配gpu以及指定gpu训练模型的流程以及示例

torch.device("cuda" if torch.cuda.is_available() else "cpu") 当使用上面的这个命令时&#xff0c;PyTorch 会检查系统是否有可用的 CUDA 支持的 GPU。如果有&#xff0c;它将选择默认的 GPU&#xff08;通常是第一块&#xff0c;即 “cuda:0”&#xf…

win10重装Ubuntu22.04安装报错复盘

目录 一&#xff1a;补充启动盘制作 二&#xff1a;错误信息[0xC0030570] The file or directory is corrupted and unreadable. 三&#xff1a;ubuntu重装步骤&#xff1a; 四&#xff1a;磁盘冗余阵列 五&#xff1a;尝试将SCS11(2,0.0), 第1分区(sda)设备的一个vfat文…

获取指定进程中的数据

此文章是对《打印指定进程中的数据》的扩展&#xff0c;增加了用户空间的控制接口&#xff0c;可以实现从用户空间发送指令&#xff0c;指定要获取数据的进程id和内存地址&#xff0c;然后将取到的数据返回给用户空间。 下面是驱动部分的代码 #include <linux/module.h>…

2024年混合云:趋势和预测

混合云环境对于 DevOps 团队变得越来越重要&#xff0c;主要是因为它们能够弥合公共云资源的快速部署与私有云基础设施的安全和控制之间的差距。这种环境的混合为 DevOps 团队提供了灵活性和可扩展性&#xff0c;这对于大型企业中的持续集成和持续部署 (CI/CD) 至关重要。 在混…

react+ProComponents简单实现表格

文章目录 使用ProComponents的原因 一般后台管理系统&#xff0c;大部分页面功能都是列表和表单的形式。 即便使用了组件、等&#xff0c;依旧需要写大量高度重复性的代码&#xff0c;比如列表页通常会有 筛选栏、操作栏、表格区域、和分页栏四个部分&#xff0c; 新增/编辑页…

【JavaEE Spring】Spring事务和事务传播机制

Spring事务和事务传播机制 1. 事务回顾1.1 什么是事务?1.2 为什么需要事务?1.3 事务的操作 2. Spring 中事务的实现2.1 Spring编程式事务(了解)2.2 Spring声明式事务Transactional 3. Transactional 详解3.1 rollbackFor3.2 事务隔离级别3.2.1 MySQL事务隔离级别(回顾)3.2.2 …