【LeetCode每日一题】525连续数组 303区域和检索(前缀和的基本概念和3个简单案例)

news2024/11/15 12:33:19

前缀和

在这里插入图片描述

// 构造prefix
let prefix = [0]
arr.forEach(num => {
    prefix.push(prefix.at(-1) + num);
})

如果想要计算某个区间 i 到 j 这个子数组的和时,可以根据 prefix[j+1] - prefix[i] 获得。

例题1:303.区域和检索 - 数组不可变

给定一个整数数组 nums,处理以下类型的多个查询:

  1. 计算索引 leftright (包含 leftright)之间的 nums 元素的 ,其中 left <= right

实现 NumArray 类:

  • NumArray(int[] nums) 使用数组 nums 初始化对象
  • int sumRange(int i, int j) 返回数组 nums 中索引 leftright 之间的元素的 总和 ,包含 leftright 两点(也就是 nums[left] + nums[left + 1] + ... + nums[right] )
/**
 * @param {number[]} nums
 */
var NumArray = function(nums) {
    this.sum = new Array(nums.length+1).fill(0);
    for(let i =0;i<n;i++){
        this.sum[i+1] = this.sum[i]+nums[i]
    }
};

/** 
 * @param {number} left 
 * @param {number} right
 * @return {number}
 */
NumArray.prototype.sumRange = function(left, right) {
    return this.sum[right+1 ]-this.sum[left];
};

/**
 * Your NumArray object will be instantiated and called as such:
 * var obj = new NumArray(nums)
 * var param_1 = obj.sumRange(left,right)
 */

例题2

数组water表示一排瓶子的水位高度。小明往这些瓶子内浇水,1次操作可以使1个瓶子的水位增加1。给定一个整数cnt,表示小明想通过浇水获得cnt个水位高度一致的瓶子。求最少需要浇水多少次?

比如:[1,2,3,4,100] ,cnt = 4,想要获得4个,最少需要浇水
(4-1) + (4-2)+(4-3)+(4-4)
⇒ 4 * 4 - (1+2+3+4)
⇒ 4* cnt - cnt个元素的区域和。

计算操作次数的公式为:water[i] * cnt - (preSum[i + 1] - preSum[i - cnt + 1])
这个公式表示将当前位置到第cnt个瓶子的水位高度都调整为当前位置的水位高度所需的总操作次数。

下面是修改后的代码实现:

const MinOperations = (water, cnt) => {
  water.sort((a, b) => b - a); // 按照从大到小排序
  let preSum = [0];
  water.forEach((element) => {
    preSum.push(preSum[preSum.length - 1] + element);
  });

  let res = Infinity;
  for (let i = cnt - 1; i < water.length; i++) {
    let temp = water[i] * cnt - (preSum[i + 1] - preSum[i - cnt + 1]);
    if (temp < res) res = temp;
    if (res === 0) break; // 如果res的值已经为0,表示不需要再进行更多操作,可以跳出循环
  }
  return res;
};

console.log(MinOperations([7, 1, 9, 10], 3));
console.log(MinOperations([5, 3, 5, 10], 2));

在给定的示例中,第一个输入数组为[7, 1, 9, 10],表示瓶子的水位高度,cnt为3。运行代码后,输出为2,表示最少需要浇水2次才能使3个瓶子的水位高度一致。第二个输入数组为[5, 3, 5, 10],cnt为2。运行代码后,输出为3,表示最少需要浇水3次才能使2个瓶子的水位高度一致。

例题3:525. 连续数组

给定一个二进制数组 nums , 找到含有相同数量的 01 的最长连续子数组,并返回该子数组的长度。

妈的 连题目都没有读懂!本来看成是找到两个连续子数组,两个连续子数组的 0 1 个数分别相同,我说怎么看着如此复杂。

题目转换:

找到一个连续子数组,其中0和1 的数量是一致的,求最大的连续子数组的长度。

解题过程

暴力

遍历所有连续子数组的0和1 的个数,如果相同,则维护这个连续子数组的最大长度。

巧妙的转换:

相同数量的0和1 ⇒ 将 0 → -1 ⇒ 连续子数组和 为 0

如果想要求子数组的元素和 ⇒ 计算数组的前缀和。

prefixSum[i] : [0…i] 的前缀和,元素的累加。

[i…k] 的元素累加和 = prefixSum[k]-prefixSum[i-1]

所以:相同数量的0和1 ⇒ 将 0 → -1 ⇒ 连续子数组和 为 0 ⇒ prefixSum[k]-prefixSum[i] = 0 长度为 i- k ⇒ 当出现前缀和相同时维护一个最大的长度。

思路1:(x)

  • 维护一个prefixSum表。遍历nums
  • 用两个for循环,遍历所有子数组。

思路2:

  • 用一个map记录前缀和和第一次出现的位置。key⇒value 的形式。
  • map.has 意味着出现了前缀和一致的情况,则维护最大长度。
/**
 * @param {number[]} nums
 * @return {number}
 */
var findMaxLength = function(nums) {
  let max = 0;
	// 如果连续子数组索引从0开始,则是priefix-prefix[-1],因此要提前保存-1,但是很难想到。
  const map = new Map();
	map.set(0,-1)

  let sum= 0;

  for (let i = 0; i < nums.length; i++) {
    if (nums[i] === 0) {
      sum--; // 遇到0 则-1,相当于把0元素简化为-1
    } else {
      sum++;
    }

    if (map.has(sum)) {
    // 出现了相同的前缀和,相减=0,说明这个区域和为0,说明0和1的个数相同
      max = Math.max(max, i - map.get(sum));// 不用更新sum的索引,因为要求的是最大的
    } else {
      map.set(sum, i);
    }
  }

  return max;
};

思路3:

最长的连续子数组是以index = 0 为开头的特殊情况,要么使用思路二,在map里添加 index = -1 的情况。

要么使用思路三:sum = 0 的情况,sum是从index = 0 开始算的,相当于算的就是每个以index = 0 为开头的连续子数组的和。

/**
 * @param {number[]} nums
 * @return {number}
 */
var findMaxLength = function(nums) {
  let max = 0;
  const map = new Map();
  let sum = 0;
  for (let i = 0; i < nums.length; i++) {
    if (nums[i] === 0) {
      sum --;
    } else {
      sum ++;
    }
		if(sum === 0){max = Math.max(max,i+1)}
    else if (map.has(sum)) {
      max = Math.max(max, i - map.get(sum));
    } else {
      map.set(sum , i);
    }
  }

  return max;
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

代码随想录算法训练营第45天|139.单词拆分、多重背包、背包问题总结

文章目录 139.单词拆分思路代码 多重背包思路代码 背包问题总结思路代码 139.单词拆分 题目链接&#xff1a;139.单词拆分 文章讲解&#xff1a;代码随想录|139.单词拆分 视频讲解&#xff1a;139.单词拆分 思路 按照双指针思路直接想这题更好理解&#xff0c;用动态规划五部曲…

Django中的SQL注入攻击防御策略

Django中的SQL注入攻击防御策略 SQL注入是一种常见的网络安全威胁&#xff0c;可以导致数据库被非法访问和数据泄露。本文将介绍在Django框架中防止SQL注入攻击的关键方法&#xff0c;包括使用参数化查询、使用ORM、进行输入验证和使用安全的编码实践。 SQL注入是一种利用应用程…

【数据分享】1929-2023年全球站点的逐年平均风速(Shp\Excel\免费获取)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、能见度等指标&#xff0c;说到气象数据&#xff0c;最详细的气象数据是具体到气象监测站点的数据&#xff01; 有关气象指标的监测站点数据&#xff0c;之前我们分享过1929-2023年全球气象站…

信息隐藏研究新动向

信息隐藏有三十年的研究历史&#xff0c;在隐写、数字水印、可逆数据隐藏等方面&#xff0c;国内外发展了一系列新技术与新方法。随着深度学习时代的来临&#xff0c;信息隐藏研究出现了新的变化。一方面&#xff0c;深度学习技术在信息隐藏的发展中发挥了重要作用&#xff1b;…

【RT-DETR进阶实战】利用RT-DETR进行视频划定区域目标统计计数

👑欢迎大家订阅本专栏,一起学习RT-DETR👑 一、本文介绍 Hello,各位读者,最近会给大家发一些进阶实战的讲解,如何利用RT-DETR现有的一些功能进行一些实战, 让我们不仅会改进RT-DETR,也能够利用RT-DETR去做一些简单的小工作,后面我也会将这些功能利用PyQt或者是…

图形系统开发实战课程:进阶篇(上)——2.图形管理类(Graph)

图形开发学院&#xff5c;GraphAnyWhere 课程名称&#xff1a;图形系统开发实战课程&#xff1a;进阶篇(上)课程章节&#xff1a;“图形管理类&#xff08;Graph&#xff09;”原文地址&#xff1a;https://graphanywhere.com/graph/advanced/2-2.html 第二章&#xff1a;图形管…

蓝桥杯训练-Huffman树(哈夫曼树)(day14)

一、题目 Huffman树在编码中有着广泛的应用&#xff0c;在这里&#xff0c;只关心Huffman树的构造过程。 给出一列数{pi}{p0,p1,...pn-1},用这列数构造Huffman树的过程如下&#xff1a; 1.找出{pi}中最小的两个数&#xff0c;设为pa和pb,将pa和pb从{pi}中删除&#xff0c;然…

【错误收录】ohpm ERROR: Install failed FetchPackageInfo: @ohos/hypium failed

创建APP的时候出现这样一个错误&#xff0c;是代理没有配置的原因 ohpm.bat install --registry https://repo.harmonyos.com/ohpm/ ohpm WARN: ETIMEDOUT Failed to search for package "ohos/hypium" from "https://repo.harmonyos.com/ohpm/", request…

Elasticsearch: 非结构化的数据搜索

很多大数据组件在快速原型时期都是Java实现&#xff0c;后来因为GC不可控、内存或者向量化等等各种各样的问题换到了C&#xff0c;比如zookeeper->nuraft(https://www.yuque.com/treblez/qksu6c/hu1fuu71hgwanq8o?singleDoc# 《olap/clickhouse keeper 一致性协调服务》)&a…

【Linux】线程池线程安全的单例模式和STL读者写者问题

需要云服务器等云产品来学习Linux的同学可以移步/–>腾讯云<–/官网&#xff0c;轻量型云服务器低至112元/年&#xff0c;优惠多多。&#xff08;联系我有折扣哦&#xff09; 文章目录 1. 线程池1.1 线程池是什么1.2 为什么要有线程池1.3 线程池的应用场景1.4 线程池的任…

异步编程(JS)

前言 想要学习Promise&#xff0c;我们首先要了解异步编程、回调函数、回调地狱三方面知识&#xff1a; 异步编程 异步编程技术使你的程序可以在执行一个可能长期运行的任务的同时继续对其他事件做出反应而不必等待任务完成。 与此同时&#xff0c;你的程序也将在任务完成后显示…

SpringBoot:日志框架

使用日志框架demo&#xff1a;点击查看LearnSpringBoot04logging 点击查看更多的SpringBoot教程 一、springboot日志框架简介 SpringBoot&#xff1a;底层是Spring框架&#xff0c;Spring框架默认是用ICL&#xff1b; SpringBoot选用SLF4j和logback&#xff1b; 统一使用slf4…

Modern C++ 内存篇1 - std::allocator VS pmr

大年三十所写&#xff0c;看到就点个赞吧&#xff01;祝读者们龙年大吉&#xff01;当然有问题欢迎评论指正。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. 前言 从今天起我们开始内存相关的话题&#xff0c;内存是个很大的话题&#xff0c;一时不…

Mac 版 Excel 和 Windows 版 Excel的区别

Excel是一款由微软公司开发的电子表格程序&#xff0c;广泛应用于数据处理、分析和可视化等领域。它提供了丰富的功能和工具&#xff0c;包括公式、函数、图表和数据透视表等&#xff0c;帮助用户高效地处理和管理大量数据。同时&#xff0c;Excel还支持与其他Office应用程序的…

传输层协议 ——— TCP协议

TCP协议 TCP协议谈谈可靠性为什么网络中会存在不可靠&#xff1f;TCP协议格式TCP如何将报头与有效载荷进行分离&#xff1f;序号与确认序号 确认应答机制&#xff08;ACK&#xff09;超时重传机制连接管理机制三次握手四次挥手 流量控制滑动窗口拥塞控制延迟应答捎带应答面向字…

架构整洁之道-软件架构-测试边界、整洁的嵌入式架构、实现细节

6 软件架构 6.14 测试边界 和程序代码一样&#xff0c;测试代码也是系统的一部分。甚至&#xff0c;测试代码有时在系统架构中的地位还要比其他部分更独特一些。 测试也是一种系统组件。 从架构的角度来讲&#xff0c;所有的测试都是一样的。不论它们是小型的TDD测试&#xff…

【Java】eclipse连接MySQL数据库使用笔记(自用)

注意事项 相关教程&#xff1a;java连接MySQL数据库_哔哩哔哩_bilibilijava连接MySQL数据库, 视频播放量 104662、弹幕量 115、点赞数 1259、投硬币枚数 515、收藏人数 2012、转发人数 886, 视频作者 景苒酱, 作者简介 有时任由其飞翔&#xff0c;有时禁锢其翅膀。粉丝群1&…

IoC原理

Spring框架的IOC是基于Java反射机制实现的&#xff0c;那具体怎么实现的&#xff0c;下面研究一下 反射 Java反射机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调用它的任意方法…

【doghead】uv_loop_t的创建及线程执行

worker测试程序,类似mediasoup对uv的使用,是one loop per thread 。创建一个UVLoop 就可以创建一个uv_loop_t Transport 创建一个: 试验配置创建一个: UvLoop 封装了libuv的uv_loop_t ,作为共享指针提供 对uv_loop_t 创建并初始化

Kafka 下载与启动

目录 一. 前言 二. 版本下载 2.1. 版本说明 三. 快速启动 3.1. 下载解压 3.2. 启动服务 3.3. 创建一个主题&#xff08;Topic&#xff09; 3.4. 发送消息 3.5. 消费消息 3.6. 使用 Kafka Connect 来导入/导出数据 3.7. 使用 Kafka Stream 来处理数据 3.8. 停止 Kaf…