【十七】【算法分析与设计】前缀和(2)

news2024/9/30 19:37:10

238. 除自身以外数组的乘积

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积

题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。

不要使用除法,且在 O(n) 时间复杂度内完成此题。

示例 1:

 
 

输入: nums = [1,2,3,4]输出: [24,12,8,6]

示例 2:

输入: nums = [-1,1,0,-3,3] 输出: [0,0,9,0,0]

提示:

  • 2 <= nums.length <= 10(5)

  • -30 <= nums[i] <= 30

  • 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内

进阶:你可以在 O(1) 的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组 不被视为 额外空间。)

 
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        vector<int> dp1(n);
        vector<int> dp2(n);

        dp1[0] = 1;
        dp2[n - 1] = 1;

        for (int i = 1; i < n; i++)
            dp1[i] = dp1[i - 1] * nums[i - 1];

        for (int i = n - 2; i >= 0; i--)
            dp2[i] = dp2[i + 1] * nums[i + 1];

        vector<int> answer(n);
        for (int i = 0; i < n; i++)
            answer[i] = dp1[i] * dp2[i];

        return answer;
    }
};

获取数组长度

int n = nums.size();

这里定义了一个整数 n 来存储输入向量 nums 的长度。

初始化前缀积和后缀积向量

vector<int> dp1(n); vector<int> dp2(n);

定义了两个向量 dp1dp2,大小均为 ndp1 用于存储从左到右的累积乘积(前缀积),dp2 用于存储从右到左的累积乘积(后缀积)。

设置前缀积和后缀积的初始值

dp1[0] = 1; dp2[n - 1] = 1;

为了方便计算,dp1 的第一个元素和 dp2 的最后一个元素被初始化为 1。

计算前缀积

for (int i = 1; i < n; i++) dp1[i] = dp1[i - 1] * nums[i - 1];

从左到右遍历 nums,使用 dp1 来计算每个位置左侧所有元素的乘积。

计算后缀积

for (int i = n - 2; i >= 0; i--) dp2[i] = dp2[i + 1] * nums[i + 1];

从右到左遍历 nums,使用 dp2 来计算每个位置右侧所有元素的乘积。

计算最终结果

vector<int> answer(n); for (int i = 0; i < n; i++) answer[i] = dp1[i] * dp2[i];

定义了一个向量 answer,其大小为 n,用于存储最终结果。通过遍历 dp1dp2 的每个元素并将它们相乘,得到 nums 中除了当前元素之外其余各元素的乘积。

时间复杂度和空间复杂度

时间复杂度:O(n)。整个算法中有三个独立的循环,每个循环都遍历了 n 次,但由于它们是顺序执行而非嵌套,所以总的时间复杂度是线性的。

空间复杂度:O(n)。除了输入数组 nums 外,主要额外空间消耗来自于两个长度为 n 的向量 dp1dp2 和结果数组 answer

560. 和为 K 的子数组

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数

子数组是数组中元素的连续非空序列。

示例 1:

输入:nums = [1,1,1], k = 2 输出:2

示例 2:

输入:nums = [1,2,3], k = 3 输出:2

提示:

  • 1 <= nums.length <= 2 * 10(4)

  • -1000 <= nums[i] <= 1000

  • -10(7) <= k <= 10(7)

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        int n = nums.size();
        int sum = 0;
        int ret = 0;
        unordered_map<int, int> hash;
        hash[0] = 1;
        for (int i = 0; i < n; i++) {
            sum += nums[i];
            if (hash.count(sum - k))
                ret += hash[sum - k];

            hash[sum]++;
        }
        return ret;
    }
};

函数签名

int subarraySum(vector<int>& nums, int k)

这行代码定义了一个函数 subarraySum,它接受一个整数向量 nums 和一个整数 k 作为参数,并返回一个整数作为结果。

获取数组长度

int n = nums.size();

这里定义了一个整数 n 来存储输入向量 nums 的长度。

初始化累计和与计数器

int sum = 0; int ret = 0;

sum 用于存储当前的累计和,ret 用于记录和为 k 的连续子数组的个数。

初始化哈希表用于存储累计和出现的次数

unordered_map<int, int> hash; hash[0] = 1;

使用一个哈希表 hash 来存储各个累计和出现的次数,初始化时加入 0 的累计和出现了 1 次,这是为了处理那些从数组开头开始的、和为 k 的子数组。

遍历数组,更新累计和并检查

for (int i = 0; i < n; i++) { sum += nums[i]; if (hash.count(sum - k)) ret += hash[sum - k]; hash[sum]++; }

遍历 nums 数组,对每个元素进行累加以更新 sum。然后检查 hash 中是否存在 sum - k 的键值,如果存在,说明找到了一个连续子数组其和为 k,将这个和的出现次数加到 ret 上。最后,将当前的 sum 出现次数加一,更新到 hash 中。

时间复杂度和空间复杂度

时间复杂度:O(n)。算法中有一个循环,遍历了一次数组 nums

空间复杂度:O(n)。主要的额外空间消耗来源于哈希表 hash,在最坏的情况下,当所有的累计和都不同,它的大小可以达到 n

974. 和可被 K 整除的子数组

给定一个整数数组 nums 和一个整数 k ,返回其中元素之和可被 k 整除的(连续、非空) 子数组 的数目。

子数组 是数组的 连续 部分。

示例 1:

输入:nums = [4,5,0,-2,-3,1], k = 5 输出:7 解释: 有 7 个子数组满足其元素之和可被 k = 5 整除: [4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]

示例 2:

输入: nums = [5], k = 9 输出: 0

提示:

  • 1 <= nums.length <= 3 * 10(4)

  • -10(4) <= nums[i] <= 10(4)

  • 2 <= k <= 10(4)

 
class Solution {
public:
    int subarraysDivByK(vector<int>& nums, int k) {
        int n = nums.size();
        int sum = 0;
        int ret = 0;
        unordered_map<int, int> hash;

        hash[0] = 1;
        for (int i = 0; i < n; i++) {
            sum += nums[i];
            int x = (sum % k + k) % k;
            if (hash.count(x))
                ret += hash[x];

            hash[x]++;
        }

        return ret;
    }
};

获取数组长度

int n = nums.size();

这里定义了一个整数 n 来存储输入数组 nums 的长度。

初始化累积和与计数器

int sum = 0; int ret = 0;

sum 用来累计 nums 中元素的和,ret 用来计数能被 k 整除的连续子数组数量。

初始化哈希表用于存储累积和模 k的结果出现的次数:

unordered_map<int, int> hash; hash[0] = 1;

使用一个哈希表 hash 来存储各个累积和模 k 的结果出现的次数,初始时加入 0 的累积和出现了 1 次,以便处理那些从数组开头开始且和能被 k 整除的子数组。

遍历数组,更新累积和模 k的结果,并检查:

for (int i = 0; i < n; i++) { sum += nums[i]; int x = (sum % k + k) % k; if (hash.count(x)) ret += hash[x]; hash[x]++; }

遍历 nums 数组,对每个元素进行累加以更新 sum。接着,计算调整后的累积和模 k 的结果,存储在 x 中。这里的 (sum % k + k) % k 确保 x 是一个非负数,因为直接 sum % k 可能会产生负数。如果 hash 中已存在 x,则表示之前已有累积和模 k 结果为 x 的子数组,这些子数组的结束点加上当前元素形成的新子数组也能被 k 整除,所以将 hash[x] 加到 ret 上。然后,将 x 对应的计数增加。

时间复杂度和空间复杂度

时间复杂度:O(n)。算法中包含一个遍历整个数组 nums 的循环。

空间复杂度:O(min(n, k))。哈希表 hash 存储的是累积和模 k 的结果,因此它的大小最多不会超过 k 的大小(在最坏的情况下,如果 k 小于 n),但也不会超过 n(如果每次迭代都产生一个不同的模数结果)。

总结

对于上述的问题,我们的解题思路是,希望先解决一个子问题,如果这个子问题解决了,整个问题只需要遍历一遍即可。解决子问题的时候,我们需要研究符合条件的时候的情况,所以我们先把符合条件的情况拿出来进行研究,转化等价关系。不断的定义解决问题需要的参数,整个问题的解决只需要不断的维护我们的定义的参数即可。

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

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

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

相关文章

碳素光线疗法——动,植物 光育实验

碳素光线疗法——动&#xff0c;植物 光育实验 碳素光线疗法&#xff1a; 中西医、民间疗法融为一体&#xff0c;提高机体自身治愈力&#xff0c;免疫力&#xff0c;改善体质和保持健康&#xff0c;有助于疾病的预防和治疗的疗法。不吃药、不打针、不手术也能得健康&#xff0c…

【Grass Mining】教程

Grass 为用户提供了一种利用网络资源进行Mining的新途径。以下是一份简化的指南&#xff0c;帮助您轻松开始在 Grass 上的Mining活动。 开始之前&#xff1a;注册 Grass 账户 首先&#xff0c;访问 Grass 官方网站进行账户注册。如果遇到注册过程中出现的“失败”提示&#x…

Android Jetpack:简化开发、提高Android App质量的利器

Android Jetpack&#xff1a;简化开发、提高Android App质量的利器 1. Jetpack的概念和目标 Jetpack是一套库、工具和指南&#xff0c;旨在帮助开发者更轻松地编写高质量的应用程序。这些组件帮助开发者遵循最佳实践&#xff0c;减少样板代码的编写&#xff0c;并简化复杂的任…

2024年,抖音小店无货源怎么做?一篇全解!

大家好&#xff0c;我是电商糖果 无货源不能做了&#xff1f; 以后是不是要商家自己进货&#xff0c;囤货了&#xff1f; 无货源未来还有发展前景吗&#xff1f; ....... 这些问题&#xff0c;从2022年就有不少朋友开始问&#xff0c;一直到2024年。 糖果做无货源电商已经…

训练YOLOv9-S

1. YOLOv9-S网络结构 1.1 改前改后的网络结构&#xff08;参数量、计算量&#xff09;对比 修改前调用的yolo.py测试的yolov9.yaml的打印网络情况&#xff0c;包含参数量、计算量 修改后调用的yolo.py测试的yolov9.yaml的打印网络情况&#xff0c;包含参数量、计算量 1.2 …

MySQL关联查询如何优化

好久不见&#xff0c;关于这篇文章&#xff0c;我也是想了很久&#xff0c;还是决定写一篇文章&#xff0c;有很多同学问过 mysql 相关的问题&#xff0c;其实关联查询如何优化&#xff0c;首先我们要知道关联查询的原理是什么&#xff1f; 左连接 left join SELECT 字段列表…

单目测距那些事儿(上) _ 从MobileEye谈起

单目测距那些事儿(上) | 从MobileEye谈起 全面专业的自动驾驶学习资料:链接 前言 在ADAS领域&#xff0c;有个功能叫自适应巡航控制(Adaptive Cruise Control, ACC)。 ACC是一种纵向距离控制&#xff0c;具体包括发现目标车辆、判断目标车辆所在路径、测量相对本车的距离和速…

STM32之HAL开发——手动移植HAL库

HAL库移植步骤 创建目录 配置启动文件 在\Drivers\CMSIS\Device\ST\stm32f1xx\Source\Templates\ARM目录下&#xff0c;根据你的芯片型号选择对应的启动文件&#xff0c;不同容量大小的芯片&#xff0c;对应的启动文件也不一样。 注意&#xff1a;在HAL库中&#xff0c;不同容…

离散型工业生产制造MES管理系统解决方案

一、核心优势 1、业务场景高适配 ①配置好程度高,可适应不同的业务场景。 ②业务功能灵活可配,可根据客户需求及时调整。 2、功能覆盖全周期 产品功能覆盖面广,能够实现从来料管理到销售出库整个产品生命周期管控。 3、触点互联降成本 能将相关的设备集成至MES中来,实现与设…

全网最靠谱的短网址平台,你知道几个?

在当今互联网时代&#xff0c;短网址平台成为了人们分享链接的常用工具。它们不仅可以将冗长的网址压缩为简洁的短链接&#xff0c;还能提供更多的功能和优势。在众多的短网址平台中&#xff0c;有几个平台以其可靠性和出色的性能脱颖而出。今天&#xff0c;我们就来介绍几个全…

跳槽多次未成功,问题源自何处?

众所周知&#xff0c;2023年市场很难&#xff01;看着企业们纷纷裁员&#xff0c;甚至连内推这个后门都走不通&#xff01;哪怕有面试&#xff0c;都是屡屡碰壁&#xff0c;你想清楚问题出在哪了吗&#xff1f;&#x1f62d;“求职不得&#xff0c;夜不能寐&#xff1b;三更半夜…

设计模式—观察者模式与发布订阅

观察者设计模式 观察者设计模式&#xff08;Observer Design Pattern&#xff09;是一种常用的软件设计模式&#xff0c;它是一种行为型模式。该模式用于定义对象之间的一种一对多的依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都将得到通知…

NeuralForecast 超参数优化

NeuralForecast 超参数优化 flyfish 不使用超参数优化的方式 import numpy as np import pandas as pd from IPython.display import display, Markdownimport matplotlib.pyplot as plt from neuralforecast import NeuralForecast from neuralforecast.models import NBEA…

C#事件实例详解

一、什么是事件&#xff1f; 在C#中,事件(event)是一种特殊的类成员,它允许类或对象通知其他类或对象发生了某些事情。 从语法上看,事件的声明类似于字段,但它们在功能和行为上有一些重要的区别。 从技术角度来说,事件实际上是一个封装了事件订阅和取消订阅功能的委托字段。…

通过JWT完成token登录验证

前言 什么是JWT&#xff1f; 全称是JSON Web token&#xff0c;是用于对应用程序上的用户进行身份验证的标记&#xff0c;使用 JWTS 的应用程序不再需要保存有关其用户的 cookie 或其他session数据 使用JWT的优势 提高了程序的可伸缩性&#xff0c;也极大的提高了应用程序的安全…

鸿蒙Harmony应用开发—ArkTS(@Link装饰器:父子双向同步)

子组件中被Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。 说明&#xff1a; 从API version 9开始&#xff0c;该装饰器支持在ArkTS卡片中使用。 概述 Link装饰的变量与其父组件中的数据源共享相同的值。 限制条件 Link装饰器不能在Entry装饰的自定义组件中使用…

前端canvas项目实战——简历制作网站(六):加粗、斜体、下划线、删除线(上)

目录 前言一、效果展示二、实现步骤1. 视图部分&#xff1a;实现用于切换字体属性的按钮2. 逻辑部分&#xff1a;点击按钮之后要做什么&#xff1f;3. 根据Textbox的属性实时更新按钮的状态 三、Show u the code后记 前言 上一篇博文中&#xff0c;我们实现了对文字的字体、字…

ChatGLM3 Linux 部署

1.首先需要下载本仓库&#xff1a; git clone https://github.com/THUDM/ChatGLM3 2.查看显卡对应的torch 版本 官方文档说明&#xff1a; Start Locally | PyTorch 例如&#xff1a; a. 先查看显卡的CUDA版本 nvcc --version 查看对应版本 Previous PyTorch Versions …

Error:No such property: GradleVersion for class: JetGradlePlugin

Gradle版本对照表 Android Gradle 插件版本在项目的根目录&#xff08;不是App目录&#xff09;下的build.gradle文件中&#xff0c;如图 插件所需的Gradle 版本在gradle目录下的gradle-wrapper.properties文件中&#xff0c;如图

安全认证|CISSP认证是什么证书?考了有什么用?能做什么工作?

很多人总是听说CISSP是顶级的信息安全证书&#xff0c;在国内或者国外都有盛誉&#xff0c;那么CISSP到底是个什么样的证书&#xff0c;本期就给大家介绍下&#xff01; 什么是CISSP CISSP&#xff08;Certification for Information System Security Professional&#xff0…