leetcode238:除自身以外数组的乘积

文章目录

  • 1.使用除法(违背题意)
  • 2.左右乘积列表
  • 3.空间复杂度为O(1)的方法

在leetcode上刷到了这一题,一开始并没有想到好的解题思路,写篇博客再来梳理一下吧。
在这里插入图片描述

在这里插入图片描述
题目要求:

  • 不使用除法
  • 在O(n)时间复杂度内

1.使用除法(违背题意)

该方法分以下几步:

  1. 先遍历数组,求数组所有元素的乘积sum
  2. 再遍历一遍数组,使用sum除以该下标对应的元素,将结果放在answer数组中

在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
int* productExceptSelf(int* nums, int numsSize, int* returnSize) {
    int* answer = (int*)calloc(numsSize, sizeof(int));
    *returnSize = numsSize;
    int sum = 1;
    for (int i = 0; i < numsSize; i++)
    {
        sum *= nums[i]; //求所有元素的乘积
    }
    for (int i = 0; i < numsSize; i++)
    {
        answer[i] = sum / nums[i];
    }
    return answer;
}

int main()
{
	int arr[] = { 1,2,3,4 };
	int sz = sizeof(arr) / sizeof(arr[0]);
    int count = 0;
    int* ret = productExceptSelf(arr, sz, &count);
    for (int i = 0; i < count; i++)
    {
        printf("%d", *(ret + i));
        if (i != count - 1)
        {
            printf(",");
        }
    }
    free(ret);
    ret = NULL;
	return 0;
}

2.左右乘积列表

相较于第一种方法,我们不必将所有数字的乘积除以给定索引处的数字得到相应的答案,而是利用索引左侧所有数字的乘积和右侧所有数字的乘积(即前缀与后缀)相乘得到答案。这也是题目中暗示我们的
在这里插入图片描述

该方法分以下几步:

  • 初始化两个空数组 Left 和 Right。对于给定下标 i,Left[i] 代表的是 i 左侧所有数字的乘积,Right[i] 代表的是 i 右侧所有数字的乘积。
  • 对于数组 Left,Left[0] 应该是 1,因为第一个元素的左边没有元素。对于数组 Right,Right[length-1] 应为 1,因为最后一个元素右侧没有元素。(length 指的是输入数组的大小)
  • 对于其它的元素,Left[i] = Left[i-1] * nums[i-1] (i从1开始 i++)

在这里插入图片描述

  • 对于其它的元素,Right[i] = Right[i+1] * nums[i+1] (i从length-2开始 i–)

在这里插入图片描述

  • 当 Left 和 Right 数组填充完成,我们只需要在输入数组上迭代:answer[i] = Left[i] * Righti]
#include<stdio.h>
#include<stdlib.h>
int* productExceptSelf(int* nums, int numsSize, int* returnSize) {
    int* answer = (int*)calloc(numsSize, sizeof(int));
    *returnSize = numsSize;
    int Left[numsSize];
    int Right[numsSize];
    Left[0] = 1;
    Right[3] = 1;
    for (int i = 1; i < numsSize; i++)
    {
        Left[i] = Left[i - 1] * nums[i - 1];
    }
    for (int i = 2; i >= 0; i--)
    {
        Right[i] = Right[i + 1] * nums[i + 1];
    }
    for (int i = 0; i < numsSize; i++)
    {
        answer[i] = Left[i] * Right[i];
    }
    return answer;
}

int main()
{
	int arr[] = { 1,2,3,4 };
	int sz = sizeof(arr) / sizeof(arr[0]);
    int count = 0;
    int* ret = productExceptSelf(arr, sz, &count);
    for (int i = 0; i < count; i++)
    {
        printf("%d", *(ret + i));
        if (i != count - 1)
        {
            printf(",");
        }
    }
    free(ret);
    ret = NULL;
	return 0;
}

复杂度分析:

  • 时间复杂度:O(N),其中 N 指的是数组 nums 的大小。预处理 Left 和 Right 数组以及最后的遍历计算都是 O(N)的时间复杂度。
  • 空间复杂度:O(N),其中 N 指的是数组 nums 的大小。使用了 Left 和 Right 数组去构造答案,Left 和 Right 数组的长度为数组 nums 的大小。

3.空间复杂度为O(1)的方法

由于输出数组不算在空间复杂度内,而且我们的answer数组只有最后才被用到,所以我们可以先将 Left 或 Right 数组用answer数组来计算。
该方法分为以下几步:

  • 先把answer数组当作 Left数组来计算,然后再动态构造 Right 数组得到结果。这样我们就节省了两个数组,空间复杂度就为O(1)了。
  • 动态构造Right数组我们只使用一个变量R就可以了,该变量初始化为1。R * nums[i] 即可得到最终的结果.

在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>
int* productExceptSelf(int* nums, int numsSize, int* returnSize) {
    int* answer = (int*)calloc(numsSize, sizeof(int));
    *returnSize = numsSize;
    int left[numsSize];
    int right[numsSize];
    answer[0] = 1;
    int R = 1;
    //先求前缀之积
    for (int i = 1; i < numsSize; i++)
    {
        answer[i] = answer[i - 1] * nums[i - 1];
    }
    //求后缀之积与answer
    for (int i = numsSize - 1; i >= 0; i--)
    {
        // 对于下标 i,左边的乘积为 answer[i],右边的乘积为 R
        answer[i] = answer[i] * R;
        // R 需要包含右边所有的乘积,所以计算下一个结果时需要将当前值乘到 R 上
        R *= nums[i];
    }
    return answer;
}

int main()
{
	int arr[] = { 1,2,3,4 };
	int sz = sizeof(arr) / sizeof(arr[0]);
    int count = 0;
    int* ret = productExceptSelf(arr, sz, &count);
    for (int i = 0; i < count; i++)
    {
        printf("%d", *(ret + i));
        if (i != count - 1)
        {
            printf(",");
        }
    }
    free(ret);
    ret = NULL;
	return 0;
}

复杂度分析

  • 时间复杂度:O(N),其中 NNN 指的是数组 nums 的大小。分析与方法一相同。
  • 空间复杂度:O(1),输出数组不算进空间复杂度中,因此我们只需要常数的空间存放变量。

目前想到的方法就这些,后续想到会补充。

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

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

相关文章

vue3 模版语法

模板语法 Vue 使用一种基于 HTML 的模板语法&#xff0c;使我们能够声明式地将其组件实例的数据绑定到呈现的 DOM 上。 文本插值 最基本的数据绑定形式是文本插值&#xff0c;它使用的是“Mustache”语法 (即双大括号)&#xff1a; <span>Message: {{ msg }}</span&…

Netty-Netty实现自己的通信框架

通信框架功能设计 功能描述 通信框架承载了业务内部各模块之间的消息交互和服务调用&#xff0c;它的主要功能如下&#xff1a; 基于 Netty 的 NIO 通信框架&#xff0c;提供高性能的异步通信能力&#xff1b; 提供消息的编解码框架&#xff0c;可以实现 POJO 的序列化和反…

Qt编译OpenCV

1.CMake下载安装 官网地址&#xff1a;CMake - Upgrade Your Software Build System &#xff08;1&#xff09;下载后双击安装 &#xff08;2&#xff09;进入安装界面&#xff0c;点击【Next】 &#xff08;3&#xff09;同意协议&#xff0c;点击【Next】 &#xff08;4&a…

鸿蒙Harmony-线性布局(Row/Column)详解

人生的下半场&#xff0c;做个简单的人&#xff0c;少与人纠缠&#xff0c;多看大自然&#xff0c;在路上见世界&#xff0c;在途中寻自己。往后余生唯愿开心健康&#xff0c;至于其他&#xff0c;随缘就好&#xff01; 目录 一&#xff0c;定义 二&#xff0c;基本概念 三&am…

c++多久会被Python或者新语言取代?

c多久会被Python或者新语言取代&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「c的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&am…

使用android studio编译app到自己的手机上运行,却读取不了手机里面的图片

问题描述&#xff1a; 使用android studio编译app到自己的手机上运行&#xff0c;却读取不了手机里面的图片 问题分析&#xff1a; 这个是由于这个app没有申请手机端的 媒体文件访问权限&#xff0c;所以读取不了 解决&#xff1a;&#xff08;我的是Android 10&#xff0c;新版…

深度解析Pytest插件pytest-html

在软件开发中&#xff0c;测试报告是开发者获取测试结果和问题定位的关键工具之一。然而&#xff0c;标准的控制台输出有时难以满足我们对测试报告的需求。幸运的是&#xff0c;Pytest插件 pytest-html 提供了一种简单而强大的方式&#xff0c;可以生成漂亮、可视化的HTML格式测…

Arm LDM和STM的寻址方式

A32指令集中包含多数据传输指令LDM和STM&#xff0c;也就是单条指令可以传输多个寄存器的值与内存交互&#xff0c;这对于数据块传输以及寄存器的压入栈很有帮助。LDM和STM指令可分别用于实现堆栈的pop和push操作。对于堆栈操作&#xff0c;基寄存器通常是堆栈指针(SP)。 LDM和…

录第第五十八天——每日温度,下一个更大元素|

单调栈 栈里的元素保持单调递增或者递减&#xff0c;栈内元素是元素下标。单调栈的本质是空间换时间&#xff0c;因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素&#xff0c;优点是整个数组只需要遍历一次求一个元素右边第一个更大元素&#xff0c;单调栈…

Unity游戏图形学 Shader结构

shader结构 shader语言 openGL&#xff1a;SLG跨平台 >GLSL&#xff1a;openGL shaderlauguge DX&#xff1a;微软开发&#xff0c;性能很好&#xff0c;但是不能跨平台 >HLSL&#xff1a;high level shader language CG&#xff1a;微软和Nvidia公司联合开发&#xff…

【c++】利用嵌套map创建多层树结构

通常树的深度都大于1&#xff0c;即树有多层&#xff0c;而树结构又可以用c的map容器来实现&#xff0c;所以&#xff0c;本文给出了一种多层树结构的实现思路&#xff0c;同时也给出了相应的c代码。 整体思路概述 首先定义一个节点类Node类&#xff0c;要包括children&#x…

WIndows系统重装、备份与恢复实操问题笔记

一 windows重装 1.1 基本步骤 下载大白菜根据官网使用教程制作启动u盘从MSDN或者微软官网下载Windows镜像根据查询的快捷键进入BIOS系统&#xff0c;设置U盘为第一启动 重装 1.2 Windows 11 激活 微软其实在2023年9月20日的公告中宣布停掉免费升级&#xff0c;数字激活工具…

C++中使用vector保存新建对象中自指指针的问题

问题 在某些场景中&#xff08;例如并查集&#xff09;&#xff0c;我们需要将新建对象中的指针指向对象自己。例如&#xff0c; struct factor {int data;factor* next;factor(int i) : data(i), next(this){} }; 这样的结构体当然没有问题&#xff0c;如果我们想以类似链表…

DolphinScheduler伪集群部署

一.伪集群部署 伪集群部署目的是在单台机器部署 DolphinScheduler 服务&#xff0c;该模式下master、worker、api server、logger server都在同一台机器上。单机版本稳定性较差&#xff0c;官方建议20个以下流程使用。 二.前置需求 &#xff11;、&#xff12;.&#xff10;.…

杨中科 EFCORE 第四部分 命令详解56-61

Migrations 深入研究Migrations 1、使用迁移脚本&#xff0c;可以对当前连接的数据库执行编号更高的迁移&#xff0c;这个操作叫做“向上迁移” (Up)&#xff0c;也可以执行把数据库回退到旧的迁移&#xff0c;这个操作叫“向下迁移(Down&#xff09; 2、除非有特殊需要&…

STM32F103_ESP8266基于RTOS移植MQTT

STM32F103_ESP8266基于RTOS移植MQTT 目录 STM32F103_ESP8266基于RTOS移植MQTT一、准备工作二、移植mqttclient代码三、编译包含mqttclient的工程四、编写ESP8266驱动程序1、ESP8266 AT命令代码框架2、UART硬件和抽象层相关代码3、AT命令发送和解析代码4、plat_sock网络层相关代…

Python+甘特图及标签设置

图示 甘特图代码 import matplotlib.pyplot as plt import numpy as npclass ProjectEmement:def __init__(self, name_, starttime_: float, endtime_: float, fact_endtime_: float, grade_, rootlist_: list, keylist_: list, isover_=-1):self.name = name_self.starttime…

使用VS2015在win7 x64上编译调试FFmpeg(附源码和虚拟机下载)

1. 前言 在文章《使用VS2017在win10 x64上编译调试FFmpeg&#xff08;附源码和虚拟机下载&#xff09;》中&#xff0c;我们在win10VS2017的环境下基于开源项目ShiftMediaProject完成了FFmpeg源码调试环境的配置。在win7VS2015的环境下&#xff0c;ShiftMediaProject配置过程和…

苏州倍丰智能新型雾化粉末技术量产成功!金属3D打印全产业链更进一步

苏州倍丰智能深耕金属3D打印技术领域&#xff0c;以金属3D打印全产业链为目标&#xff0c;围绕金属3D打印设备&#xff0c;涵盖包括金属粉末前后处理设备、金属粉末原材料制备、先进工艺研发等多个领域&#xff0c;完成了一整条自上而下的金属3D打印全产业链。 近日&#xff0c…

计算日期到天数转换

根据输入的日期&#xff0c;计算是这一年的第几天。 保证年份为4位数且日期合法。 本题对三个输入数字依次使用&#xff0c;由年份可得到闰年或平年&#xff0c;故分为两种计算。 在月份中&#xff0c;由于每月天数不好找规律&#xff0c;故分为1—2月&#xff0c;3—7月&am…